基于JS对象创建常用方式及原理分析(2)

2.构造函数与原型是一对一的关系,与对象实例是一对多的关系,而并不是每创建一个对象实例,就相应的生成一个`prototype`
这就是原型模式的核心所在,结论:在原型上声明属性或方法,可以让对象实例之间共用它们

然后原型模式就是完美的吗?并不是,它有以下两个主要问题:

问题1:如果对象实例有与原型上重名的属性或方法,那么,当访问该属性或方法时,实例上的会屏蔽原型上的

function Person (name) {   this.name = name } Person.prototype = {   constructor: Person,   name: 'lucy' } var p1 = new Person('jack'); console.log(p1.name); //jack

问题2:由于实例间是共享原型上的属性和方法的,所以当其中一个对象实例修改原型上的属性(基本值,非引用类型值或方法时,其他实例也会受到影响

基于JS对象创建常用方式及原理分析


原因就是,当实例自身的基本值属性与原型上的重名时,实例就会创建该属性,留着今后自己使用,而原型上的属性不会被修改;但如果属性是引用类型值,如:`Array`、`Object`,当发生重名时,实例是不会拷贝一份新的留给自己使用的,还是坚持实例间共享,所以就会出现上图中的情况

以上两个问题就是原型模式的明显缺点,为了改掉这些缺点,我们一般会采用一种组合模式“组合使用构造函数模式和原型模式”,其实在原型模式这一节,该模式已经有所应用了

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

这种模式可谓是集构造函数模式和原型模式之所长,用构造函数模式来定义对象实例的属性或方法,而共享的属性或方法就交给原型模式

function Person (name) {   this.name = name //实例的属性,在构造函数中声明 } Person.prototype = {   constructor: Person,   sayName: function () { //共享的方法存在原型中     alert(this.name)   } }

注:此模式目前是ECMAScript中使用最广泛、认同度最高的一种创建自定义类型的方法

-----------------

下面要介绍的几个模式是针对不同场景的,而不是说`组合使用构造函数模式和原型模式`有什么缺点,又用这几个模式来弥补,不是这样的

动态原型模式

特点:共享的方法是在构造函数中检测并声明的,原型并没有被显示创建

function Person (name) {   this.name = name;   if (typeof this.sayName !== 'function') { //检查方法是否存在     console.log('sayName方法不存在')     Person.prototype.sayName = function () {       alert(this.name)     }   } else {     console.log('sayName方法已存在')   } } var p1 = new Person('jack'); //'sayName方法不存在' p1.sayName(); //因为sayName不存在,我们来创建它,所以这里输出'jack' var p2 = new Person('lucy'); //'sayName方法已存在' p2.sayName(); //这时sayName已存在,所以输出'lucy'

当`Person`构造函数第一次被调用时,`Person.prototype`上就会被添加`sayName`方法;《Javascript高级程序设计》一书说到:使用动态原型模式时,不能使用对象字面量重写原型。我们来理解一下:

基于JS对象创建常用方式及原理分析

分析:

1.`p1`实例创建,此时原型没有`sayName`方法,那我们就为原型添加一个

2.随后,我们以字面量的形式重写了原型,这时旧的原型并没有被销毁,而且它和`p1`还保持着联系

3.之后的实例,也就是这里的`p2`,都是与新原型保持联系;所以`p1`、`p2`有各自的构造器原型,即使它们的构造器是同一个

基于JS对象创建常用方式及原理分析

所以切记:当我们采用动态原型模式时,千万不要以字面量的形式重写原型

寄生构造函数模式

了解此模式之前,我们先来想一个问题:构造函数为什么要用`new`关键字调用?代码说话:

基于JS对象创建常用方式及原理分析

基于JS对象创建常用方式及原理分析

我们发现什么?如果不是`new`方法调用构造函数,那么就要显式的`return`,否则构造函数就不会有返回值;但如果使用`new`,那就没有这个问题了

下面我们再来看寄生构造函数模式:

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wyffdz.html