Javascript创建对象几种方法解析

Javascript面向对象编程一直是面试中的重点,将自己的理解整理如下,主要参考《Javascript高级程序设计 第三版》,欢迎批评指正。

通过字面量形式,创建对象:

        var person_1 = {
name: "userName",
age: 20
}

工厂模式创建对象

    通过一个构造函数接收参数的方式构造对象,可无数次调用这个函数,通过改变参数构造不同的对象
         function createPerson(name,age){
var o = new Object();//创建一个空的对象 -- 原料 o.name = name;
o.age = age;
o.sayName = function(){ //给对象属性赋值 -- 加工过程
alert(this.name)
} return o; //返回加工后的对象 -- 出厂
}
var leo = createPerson('Leo',30);
leo.sayName(); //"Leo"
var cherry = createPerson('Cherry',20);
cherry.sayName(); //"Cherry"
    缺点:工厂模式创建的对象,无法判断其类型

构造函数模式:

    类似Array,Object这种原生的构造函数,我们可以通过创建自定义的构造函数,从而定义自定义对象的类型和方法
        function Person(name,age){
this.name = name;
this.age = age;
this.sayName = function(){
alert(this.name);
}
}
var leo = new Person('Leo',18);
var cherry = new Person('Cherry',25);
leo.sayName();
cherry.sayName();
  1. 与工厂模式对比,几点不同:没有现实的创建空对象;直接将属性和方法赋值给this;不需要return
  2. 通过New操作符创建Person对象的新实例:①创建一个新的对象 ②this指向这个新对象(作用域)③执行构造函数中的代码,对新对象添加属性和方法④返回新对象
  3. 通过instanceof检测对象类型,发现通过Person构造函数创建的对象,即使Person类的实例,又是Object对象的实例 - 创建自定义的构造函数表明可以将它的实例标识为一种特定的类型
        alert(leo instanceof Person); //true
alert(leo instanceof Object); //true 所有对象都继承自Object
  1. 区分构造函数和普通函数

    ①. 任何函数通过new操作符调用,就可做为构造函数

    ②. 自定义的构造函数,不通过new调用,与普通函数没有区别
        Person('window',100);//直接调用,相当于将Person类的属性方法直接添加到了this上
window.sayName(); //window
  1. 缺点:通过构造函数,每个方法都要在实例上重新创建一遍,每个实例的sayName方法,相当于执行this.sayName = new Function("alert(this.name)")单独创建出来的
        alert(leo.sayName==cherry.sayName);//false

原型模式:

  1. 创建的每个函数都有prototype属性,这个属性指向一个其属性和方法由某个特定类的所有实例共享的对象,利用prototype,我们就可将定义对象实例的信息放在原型对象中,不必在构造函数中定义。
        function Person(){} //构造函数变成空
Person.prototype.name = 'Leo';
Person.prototype.age =30;
Person.prototype.sayName = function(){
alert(this.name);
}
var person1 = new Person();
var person2 = new Person();
alert(person1.sayName==person2.sayName);//true 将sayName方法定义在Person的prototype属性中,可由多个不同的实例共享
//简化写法:
function Person() { } //构造函数变成空
Person.prototype = {
name: 'Leo',
age: 30,
sayName: function () {
alert(this.name);
}
}
var person1 = new Person();
var person2 = new Person();
  1. 只要创建一个新函数,就会为该函数创建一个prototype属性,这个属性指向原型对象。在我们创建的对象person1和person2中都包含一个内部属性,该属性指向Person.prototype,因此两个实例都可以调用原型中的sayName()方法。Object.getPrototypeOf()方法可以更方便的取得一个对象的原型.
      alert(Person.prototype.isPrototypeOf(person1));//true
alert(Person.prototype.isPrototypeOf(person2));//true
alert(Object.getPrototypeOf(person1)==Object.getPrototypeOf(person2));//true
  1. 给一个对象添加一个属性,这个属性会屏蔽原型对象中存储的同名属性,通过hasOwnProperty()方法可判断是实例对象中的属性,还是原型中的属性;通过in运算符,可以判断在对象上能否找到某属性,而不区分是实例属性还是原型属性,for in循环中只会遍历可访问、可枚举的属性。
        person1.name='Nancy';
alert(person1.name);//Nancy
alert(person1.hasOwnProperty("name"));//True 实例对象上的属性
alert(person2.hasOwnProperty("name"));//false 原型中的属性
alert("name" in person1);//true
alert("name" in person2);//true
for(key in person1){
alert(`${key}:${person1[key]}`)
}
  1. 原型模式的缺点:①缺少向构造函数传递初始化参数这一环节,使得同一个对象的所有实例在默认情况下都会取得相同的属性值。②在实例中修改引用属性的值,会影响其他的实例。
        function Newperson(){
} Newperson.prototype = {
constructor : Newperson,
name:"Tony",
age:30,
job:"Developer",
friends:['Leo','Cherry'],
sayName:function(){
alert(this.name);
}
} let newPerson1 = new Newperson();
let newPerson2 = new Newperson();
alert(newPerson1.friends);//Leo, Cherry
alert(newPerson2.friends);//Leo, Cherry
newPerson1.friends.push('Mai');//friends属性引用数组在Newperson.prototype而非newPerson1中,newPerson1.friends和newPerson2.friends指向的是同一个引用
alert(newPerson1.friends);//Leo, Cherry, Mai
alert(newPerson2.friends);//Leo, Cherry, Mai
alert(newPerson1.friends === newPerson2.friends);//true

组合使用构造函数模式和原型模式

  1. 组合使用构造函数模式和原型模式是创建自定义类型的常见方式,构造函数用于定义实例属性,原型模式用于定义方法和共享属性。
      function Person(name,age,job){
this.name = name;
this.age = age;
this.job = job;
this.friends = ["Leo","Cherry"];
} Person.prototype = {
constructor:Person,
sayName:function(){
alert(`${this.name} is a ${this.job}.`);//公共方法
}
} let person1 = new Person('Mai',18,'actor');
let person2 = new Person('Bob',25,'developer');
person1.sayName();
person2.sayName();
alert(person1.friends == person2.friends);//false friends属性在构造函数中定义,不在原型中,两个实例不会相互影响
person1.friends.push('Tony');
person2.friends.push('Melody');
alert(person1.friends);//Leo, Cherry, Tony
alert(person2.friends);//Leo, Cherry, Melody

Javascript创建对象几种方法解析的更多相关文章

  1. 创建JAVASCRIPT对象3种方法

    创建JAVASCRIPT对象3种方法 方法一:直接定义并创建对象实例 var obj = new Object();    //创建对象实例 //添加属性obj.num = 5;   //添加属性 o ...

  2. ASP.NET,C#后台调用前台javascript的五种方法

    C#后台调用前台javascript的五种方法 由于项目需要,用到其他项目组用VC开发的组件,在web后台代码无法访问这个组件,所以只好通过后台调用前台的javascript,从而操作这个组件.在网上 ...

  3. VC调用javascript的几种方法

    第一种:通过execScript调用.这种方法,虽然操作方便,但不能获取返回值.m_spHtmlDoc->get_parentWindow(&m_pHtmlWindow);VARIANT ...

  4. Java/JSP获得客户端网卡MAC地址的三种方法解析

    java/jsp获得客户端(IE)网卡MAC地址的方法大概有三种. 1.通过命令方式,在客户端执行Ipconfig 等等.(java/jsp) 2.通过ActiveX的方法.(jsp) 3.通过向13 ...

  5. C#后台调用前台javascript的五种方法小结

    第一种,OnClientClick (vs2003不支持这个方法) <asp:Button ID="Button1" runat="server" Tex ...

  6. 【转】 C#后台调用前台javascript的五种方法

    第一种,OnClientClick    (vs2003不支持这个方法)<asp:ButtonID="Button1" runat="server" Te ...

  7. 四种方法解析JSON数据

    (1)使用TouchJSon解析方法:(需导入包:#import "TouchJson/JSON/CJSONDeserializer.h") //使用TouchJson来解析北京的 ...

  8. JAVA 创建对象4种方法

    java创建对象的几种方式 博客分类: java   (1) 用new语句创建对象,这是最常见的创建对象的方法.(2) 运用反射手段,调用java.lang.Class或者java.lang.refl ...

  9. 网页中插入javascript的几种方法

    网页中插入javascript的方法常见的有两种: 一.直接使用html标记 JavaScript 可以出现在 html的任意地方.使用标记<script>…</script> ...

随机推荐

  1. codeforces round#432 div2

    C:这道题没做出来...写了个类似极角排序的东西被卡掉了...事实上暴力就行了,因为如果在二维平面内那么最多只能有4个点,因为每个象限只能有一个点,然后这里拓展一下就是最多只能有2*k个点,k是维数, ...

  2. java中jsp页面的css资源定位---备忘录

    1:同级目录下(应该是相对定位) web-inf下的内容是不对外开放的/安全的,不能通过url直接访问.已避免非法人员通过url自己操作一些比较私密的文件信息. 能在sevlet(或者spring的c ...

  3. Codeforces 451E Devu and Flowers【容斥原理+卢卡斯定理】

    题意:每个箱子里有\( f[i] \)种颜色相同的花,现在要取出\( s \)朵花,问一共有多少种颜色组合 首先枚举\( 2^n \)种不满足条件的情况,对于一个不被满足的盒子,我们至少拿出\( f[ ...

  4. 洛谷 P4012 深海机器人问题 【最大费用最大流】

    和火星那个有点像,但是这个价值直接在路径上,不用拆点,对于每条价值为w的边(i,j),连接(i,j,1,w)(i,j,inf,0),表示价值只能取一次,然后连接源点和所有出发点(s,i,k,0),所有 ...

  5. springboot(七) 配置嵌入式Servlet容器

    github代码地址:https://github.com/showkawa/springBoot_2017/tree/master/spb-demo/spb-brian-query-service ...

  6. vultr 购买vps

    基本安装转自:https://github.com/uxh/shadowsocks_bash/wiki/Vultr%E4%BD%BF%E7%94%A8%E6%95%99%E7%A8%8B 连接 Vul ...

  7. flask框架基础入门一

    首先:flask是一个基于Werkzeug,Jinja2的一个python的微服务框架. 安装flask框架: pip install flask 一个最小的最简单的flask应用: from fla ...

  8. POJ 3683 Priest John's Busiest Day

    看这个题目之前可以先看POJ2186复习一下强联通分量的分解 题意:给出N个开始时间和结束时间和持续时间三元组,持续时间可以在开始后或者结束前,问如何分配可以没有冲突. -----–我是分割线---- ...

  9. C plus plus sprintf用法

    sprintf int sprintf ( char * str, const char * format, ... ); Write formatted data to string Compose ...

  10. 暴力/图论 hihoCoder 1179 永恒游戏

    题目传送门 /* 暴力:也是暴力过了,无语.无向图,两端点都要加度数和点 */ #include <cstdio> #include <algorithm> #include ...