构造函数模式

实现方式:
function Person(name, age, job) {
this.name = name;
this.age = age;
this.job = job;
this.sayName = function() {
return this.name
}
} // 测试
var person = new Person('Nicholas', 29, 'Engineer'); // 检测对象类型
console.log(person.constructor === Person); // true
console.log(person instanceof Person); // true
console.log(Person instanceof Object); // true
注意:
  • 构造函数名使用首字母大写。
  • 使用new操作符创建实例。
  • 优点:
    • 可以使用instanceof操作符检测对象类型。
  • 缺点:
    • 每个方法都要在每个实例上重新创建一遍。不同实例的同名函数不相等。
var person1 = new Person('Nicholas', 29, 'Engineer');
var person2 = new Person('Greg', 30, 'Doctor');
console.log(person1.sayName === person2.sayName); // false

原型模式

实现方式:
function Person() {}
Person.prototype.name = "Nicholas";
Person.prototype.age = 29;
Person.prototype.job = "Engineer";
Person.prototype.sayName = function() {
return this.name;
} // 测试
var person = new Person();
console.log(person.sayName()); // Nicholas // 检测对象类型
console.log(person.constructor === Person); // true
console.log(person instanceof Person); // true
console.log(Person instanceof Object); // true
原型链:

关于原型:
  • 构造函数与原型对象

    • 构造函数获得一个prototype属性,指向函数的原型。
    • 原型获得一个constructor属性,指向构造函数。
  • 实例对象与原型对象
    • 创建实例后,实例获得内部属性[[Prototype]]_proto_,指向构造函数的原型。
    • isPrototypeOf()方法会返回一个布尔值,可以确定实例和原型的关系。
    • Object.getPrototypeOf()方法会返回实例对应的原型。
// isPrototypeOf()方法
console.log(Person.prototype.isPrototypeOf(person)); // true
// Object.getPrototypeOf()方法
console.log(Object.getPrototypeOf(person) === Person.prototype); // true
  • 访问原型链

    • 读取实例的属性:如果在实例中找到了该属性,则返回属性的值;如果没有找到,则继续搜索原型的同名属性,如果找到则返回该属性。
    • 添加实例的属性:如果在实例中添加一个属性,而该属性与原型中的一个属性同名。则在实例中创建该属性,并屏蔽原型中的同名属性。
    • 删除实例的属性:如果删除了实例的属性,则会使原型中的同名属性暴露出来。
// 添加属性
person.name = "Greg";
console.log(person.name); // Greg
// 删除属性
delete person.name;
console.log(person.name); // Nicholas
  • 使用对象字面量定义原型

    • 需要手动设置原型的constructor属性
    • 默认的construnctor属性是不可枚举的。可以使用Object.defineProperty()方法定义。
function Person() {};
Person.prototype = {
// constructor: Person,
name: 'Nicholas',
age: 29,
job: 'Engineer',
sayName: function() {
return this.name;
}
};
Object.defineProperty(Person.prototype, 'constructor', {
enumerable: false,
value: Person
}); // 测试
var person = new Person();
console.log(person.sayName()); // Nicholas // 检测对象类型
console.log(person.constructor === Person); // true
console.log(person instanceof Person); // true
console.log(Person instanceof Object); // true
注意:
  • 使用new操作符创建实例。
  • 优点:
    • 可以使用instanceof操作符检测对象类型。
    • 所有对象实例共享原型对象所包含的属性和方法。
  • 缺点:
    • 对于引用类型值,会存在实例意外修改原型的风险。
function Student() {}
Student.prototype.friends = ['Shelby', 'Court']; // 测试
var stu1 = new Student();
var stu2 = new Student();
stu1.friends.push('Van'); // 实例stu1修改了原型的friends属性,并影响到了stu2
console.log(stu1.friends); // ["Shelby", "Court", "Van"]
console.log(stu2.friends); // ["Shelby", "Court", "Van"]

组合模式:构造函数模式&原型模式

实现方式:
function Person(name, age, job) {
this.name = name;
this.age = age;
this.job = job;
}
Person.prototype.sayName = function() {
return this.name;
} // 测试
var person = new Person('Nicholas', 29, 'Engineer');
console.log(person.sayName()); // Nicholas // 检测对象类型
console.log(person.constructor === Person); // true
console.log(person instanceof Person); // true
console.log(Person instanceof Object); // true
注意:
  • 使用new操作符创建实例。
  • 构造函数用于自定义实例属性,原型中定义方法和共享属性。
  • 优点:
    • 可以使用instanceof操作符检测对象类型。
    • 每个实例都会有自己的一份实例属性的副本,同时又共享着对方法的引用,最大限度地节省了内存。
    • 支持向构造函数传递参数。

动态原型模式

实现方式:
function Person(name, age, job) {
// 属性
this.name = name;
this.age = age;
this.job = job; // 方法
if (typeof this.sayName !== 'function') {
Person.prototype.sayName = function() {
return this.name;
}
}
} // 测试
var person = new Person('Nicholas', 29, 'Engineer');
console.log(person.sayName()); // Nicholas // 检测对象类型
console.log(person.constructor === Person); // true
console.log(person instanceof Person); // true
console.log(Person instanceof Object); // true
注意:
  • 使用new操作符创建实例。
  • 原型初始化只在初次调用构造函数时才执行。
  • 不能使用对象字面量方式重写原型。否则就会切断现有实例与新原型之间的关系。
  • 优点:
    • 可以使用instanceof操作符检测对象类型。
    • 把所有信息都封装在构造函数中,在构造函数中初始化原型,保持了同时使用构造函数和原型的优点。

寄生构造函数模式

实现方式:
function Person(name, age, job) {
var o = new Object();
o.name = name;
o.age = age;
o.job = job
o.sayName = function() {
return o.name;
}
return o;
} // 测试
var person = new Person('Nicholas', 29, 'Engineer');
console.log(person.sayName()); // Nicholas // 检测对象类型
console.log(person.constructor === Person); // false
console.log(person instanceof Person); // false
console.log(Person instanceof Object); // true
注意:
  • 可以不使用new操作符创建实例。在不使用new操作符时,又被称为工厂模式
  • 在构造函数末尾添加return语句,可以重写调用构造函数时的返回值。
  • 无法使用instanceof操作符检测对象类型。因为返回的对象与构造函数及原型之间没有关系。

参考:《JavaScript高级程序设计》

JavaScript中创建对象的5种模式的更多相关文章

  1. JavaScript中创建对象的三种模式

    JS中,便于批量创建对象的三种模式: 1.工厂模式:用一个函数封装创建对象的细节,传入必要的参数,在函数内部new一个对象并返回. 缺点:创建的对象无法识别类型(全是Object) 2.构造函数模式: ...

  2. JavaScript中创建对象的几种模式

    代码如下: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF ...

  3. javascript中创建对象的几种不同方法

    javascript中创建对象的几种不同方法 方法一:最直白的方式:字面量模式创建 <script> var person={ name:"小明", age:20, s ...

  4. JavaScript中创建对象的三种方式!

    JavaScript中创建对象的三种方式! 第一种 利用对象字面量! // 创建对象的三种方式! // 1 对象字面量. var obj = { // 对象的属性和方法! name: 'lvhang' ...

  5. javascript中创建对象的几种方式

    1. 使用Object构造函数来创建一个对象,下面代码创建了一个person对象,并用两种方式打印出了Name的值. var person = new Object(); person.name=&q ...

  6. javascript 创建对象的7种模式

    使用字面量方式创建一个 student 对象: var student = function (){ name : "redjoy", age : 21, sex: women, ...

  7. 深入理解JavaScript中创建对象模式的演变(原型)

    深入理解JavaScript中创建对象模式的演变(原型) 创建对象的模式多种多样,但是各种模式又有怎样的利弊呢?有没有一种最为完美的模式呢?下面我将就以下几个方面来分析创建对象的几种模式: Objec ...

  8. 《JAVASCRIPT高级程序设计》创建对象的七种模式

    细看javascript创建对象模式的诞生,具体的脉络为:不使用任何模式——工厂模式——构造函数模式——原型模式——组合使用构造函数模式——动态原型模式——寄生构造函数模式——稳妥构造函数模式.每一种 ...

  9. javascript中创建对象和实现继承

    # oo ##创建对象 1. 原型.构造函数.实例之间的关系 * 原型的construct->构造函数:调用isPrototypeOf(obj)方法可以判定和实例的关系:  * 构造函数的pro ...

随机推荐

  1. bzoj 3132: 上帝造题的七分钟 (二维树状数组)

    推推公式,最后变成四个东西的前缀和 然后不知道为什么一直wa,数据在本地测是没有错的& 好心的管理员还给了某位p党大神a了的代码,感人肺腑(虽然还是没发现到底我的程序是问题) var f1,f ...

  2. BZOJ4584 & 洛谷3643 & UOJ204:[APIO2016]划艇——题解

    https://www.lydsy.com/JudgeOnline/problem.php?id=4584 https://www.luogu.org/problemnew/show/P3643 ht ...

  3. BZOJ2458:[BJOI2011]最小三角形——题解

    http://www.lydsy.com/JudgeOnline/problem.php?id=2458 Description Xaviera现在遇到了一个有趣的问题. 平面上有N个点,Xavier ...

  4. [usaco] 2008 Dec Largetst Fence 最大的围栏 2 || dp

    原网站大概已经上不了了-- 题目大意: 求出平面上n个点组成的一个包含顶点数最多的凸多边形.n<=250. 考虑我们每次枚举凸包的左下角为谁(参考Graham求凸包时的左下角),然后像Graha ...

  5. Linux实验二

    一        第一个实验 Linux基础 1 通过娄老师关于分析学霸学渣的前言 明白了真正的学习一门功课应该是思考本质 而不是纯属记忆 2 全部的命令如下 Linux命令格式:command [o ...

  6. bzoj3224: Tyvj 1728 普通平衡树(打个splay暖暖手)

    (其实今天好热啊? 题目大意:插入,删除,k小,前驱后继,数的排名. splay和treap裸题...过几天补个treap的 splay: #include<iostream> #incl ...

  7. Django ORM 查询

    过滤器 过滤器 作用 all() 查出所有行 filter() 可以添加过滤条件 order_by() 查出所有数据,如果有参数则按参数排序,参数是字符串 ,如:"-username&quo ...

  8. JS获取移动端系统信息(操作系统、操作系统版本、横竖屏状态、设备类型、网络状态、生成浏览器指纹)

    function getOS() { // 获取当前操作系统 var os; if (navigator.userAgent.indexOf('Android') > -1 || navigat ...

  9. ACE自适配通信环境简介

    转载于:http://www.cnblogs.com/TianFang/archive/2006/12/03/580795.html ACE自适配通信环境 (Adaptive Communicatio ...

  10. asp:DropDownList与asp:DataList的联合使用

    情况:当在asp:DropDownLis点击选取其中的一个值来响应datalist的值. <form id="form1" runat="server"& ...