我们可以从上面的例子中看到,Object.keys()方法返回的是其自身的属性。如原型对象只返回原型对象中的属性,对象实例也只返回对象实例自己创建的属性,而不返回继承自原型对象的实例。
E 更简单的原型语法在之前的例子中,我们在构造函数的原型对象中添加属性和方法时,每次都要在前面敲一遍Person.prototype,如果属性多了,这样的方法会显得更为繁琐,那么下面我将介绍给大家一种简单的方法。
我们知道,原型对象说到底它还是个对象,只要是个对象,我们就可以使用对象字面量方法来创建,方法如下:
1 2 3 4 5 6 7 8 9
function Person(){} Person.prototype={ name:"zzw", age:21, school:"xjtu", sayName:function (){ console.log(this.name); } };//原来利用Person.prototype.name="zzw"知识对象中的属性,对于对象并没有任何影响,而这里创建了新的对象<br>
同样,最开始,我们创建一个空的Person构造函数(大家发现了没有,其实每次我们创建的都是空的构造函数),然后用对象字面量的方法来向原型对象中添加属性。这样既减少了不必要的输入,也从视觉上更好地封装了原型。 但是,这时原型对象的constructor就不会指向Person构造函数而是指向Object构造函数了。
为什么会这样?我们知道,当我们创建Person构造函数时,就会同时自动创建这个Person构造函数的原型(prototype)对象,这个原型对象也自动获取了一个constructor属性并指向Person构造函数,这个之前的图示中可以清楚地看出来。之前我们使用的较为麻烦的方法(e.g. Person.prototype.name="zzw")只是简单地向原型对象添加属性,并没有其他本质的改变。然而,上述这种封装性较好的方法即使用对象字面量的方法,实际上是使用Object构造函数创建了一个新的原型对象(对象字面量本质即利用Object构造函数创建新对象),注意:此时Person构造函数的原型对象不再是之前的原型对象(而之前的原型对象的constructor属性仍然指向Person构造函数),而和Object构造函数的原型对象一样均为这个新的原型对象。这个原型对象和创建Person构造函数时自动生成的原型对象风马牛不相及。理所应当的是,对象字面量创建的原型对象的constructor属性此时指向了Object构造函数。
我们可以通过下面几句代码来验证:
1 2 3 4 5 6 7 8 9 10 11 12
function Person(){} Person.prototype={ name:"zzw", age:21, school:"xjtu", sayName:function (){ console.log(this.name); } }; var person1=new Person(); console.log(Person.prototype.constructor==Person);//false console.log(Person.prototype.constructor==Object);//true
通过最后两行代码我们可以看出Person构造函数的原型对象的constructor属性此时不再指向Person构造函数,而是指向了Object构造函数。但是这并被影响我们正常使用,下面几行代码便可以清楚地看出:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
function Person(){} Person.prototype={ name:"zzw", age:21, school:"xjtu", sayName:function (){ console.log(this.name); } }; var person1=new Person(); console.log(person1.name);//zzw console.log(person1.age);//21 console.log(person1.school);//xjtu person1.sayName();//zzw
下面我将以个人的理解用图示表示(如果有问题,请指出):