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

    第一步:创建一个空的构造函数。function Person(){}。此时构造函数的prototype属性指向原型对象,而原型对象的constructor属性指向Person构造函数。

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

  第二步:利用对象字面量的方法创建一个Person构造函数的新原型对象。

1

2

3

4

5

6

7

8

 

  Person.prototype={

    name:"zzw",

    age:21,

    school:"xjtu",

    sayName:function (){

        console.log(this.name);

    }

};

 

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

此时,由于创建了Person构造函数的一个新原型对象,所以Person构造函数的prototype属性不再指向原来的原型对象,而是指向了Object构造函数创建的原型对象(这是对象字面量方法的本质)。但是原来的原型对象的constructor属性仍指向Person构造函数。

   第三步:由Person构造函数创建一个实例对象。

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

这个对象实例的constructor指针同构造它的构造函数一样指向新的原型对象。

  总结:从上面的这个例子可以看出,虽然新创建的实例对象仍可以共享添加在原型对象里面的属性,但是这个新的原型对象却不再指向Person构造函数而指向Object构造函数,如果constructor的值真的非常重要的时候,我们可以像下面的代码这样重新设置会适当的值:

1

2

3

4

5

6

7

8

9

10

 

function Person(){}

Person.prototype={

    constructor:Person,

    name:"zzw",

    age:21,

    school:"xjtu",

    sayName:function (){

        console.log(this.name);

    }

};

 

  这样,constructor指针就指回了Person构造函数。即如下图所示:

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

  值得注意的是:这种方式重设constructor属性会导致它的[[Enumerable]]特性设置位true,而默认情况下,原生的constructor属性是不可枚举的。但是我们可以试用Object.defineProperty()将之修改为不可枚举的(这一部分可以参见我的另一篇博文:《深入理解JavaScript中的属性和特性》)。

F.原生对象的原型

  原型的重要性不仅体现在自定义类型方面,就连所有原生的引用类型,都是使用这种模式创建的。所有原生引用类型(Object、Array、String,等等)都在其构造函数的原型上定义了方法。例如在Array.prototype中可以找到sort()方法,而在String.prototype中就可以找到substring()方法。

1

2

 

console.log(typeof Array.prototype.sort);//function

console.log(typeof String.prototype.substring);//function

 

  于是,实际上我们是可以通过原生对象的原型来修改它。比如:   

1

2

3

4

5

 

String.prototype.output=function (){

    alert("This is a string");

}

var message="zzw";

message.output();

 

   这是,便在窗口中弹出了“This is a string”。尽管可以这样做,但是我们不推荐在产品化的程序中修改原生对象的原型。这样做有可能导致命名冲突等问题。

G.原型模式存在的问题

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

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