JavaScript和面向对象语言(例Java)一样,在创建对象都是通过调用构造函数,但是又与面向对象语言有所区别。初学JavaScript时,总把函数的构造属性和对象的构造属性弄混淆,总结下面几点。
1、constructor属性始终指向创建当前对象的构造函数
1 // 等价于 var foo = new Array(1, 56, 34, 12);
2 var arr = [1, 56, 34, 12];
3 console.log(arr.constructor === Array); // true
4 // 等价于 var foo = new Function();
5 var Foo = function() { };
6 console.log(Foo.constructor === Function); // true
7 // 由构造函数实例化一个obj对象
8 var obj = new Foo();
9 console.log(obj.constructor === Foo); // true
10 // 将上面两段代码(第6,9行)合起来,就得到下面的结论
11 console.log(obj.constructor.constructor === Function); // true
2、每个函数均有一个prototype指针属性,指向一个原型对象,在原型对象中也有一个constructor属性,而这个prototype的constructor(prototype.constructor)默认指向这个构造函数
1 function Person(name) {
2 this.name = name;
3 };
4 Person.prototype.getName = function() {
5 return this.name;
6 };
7 var p = new Person("TT");
8
9 console.log(p.constructor === Person); // true
10 console.log(Person.prototype.constructor === Person); // true
11 // 将上两行代码合并就得到如下结果
12 console.log(p.constructor.prototype.constructor === Person); // true
3、当我们把一个实例对象赋值(覆盖)给原型对象时,原型对象的constructor属性将不再指向原构造函数(重点)
1 function Person(name) {
2 this.name = name;
3 };
4 Person.prototype = {
5 getName: function() {
6 return this.name;
7 }
8 };
9 var p = new Person("TT");
10 console.log(p.constructor === Person); // false
11 console.log(Person.prototype.constructor === Person); // false
12 console.log(p.constructor.prototype.constructor === Person); // false
//因为此赋值语句等价于
Person.prototype = new Object({ //Object的实例
getName: function() {
return this.name;
}
});
//所以
console.log(p.constructor === Object); // true
console.log(Person.prototype.constructor === Object); // true
console.log(p.constructor.prototype.constructor === Object); // true
在用对象直接量赋值原型对象时,如果又不想改变constructor的值,只需在对象直接量中加一个constructor属性,再次指定值等于构造函数就可以了
Person.prototype = {
constructor: Person,
getName: function() {
return this.name;
}
};