JavaScript 原型浅析
JavaScript 中所有的函数默认都有一个名为 prototype(原型)的公有并且不可枚举的属性,这个属性是一个指针,它会指向一个对象。
function Foo () {
}
Foo.prototype; //{ }
而这个对象通常被称为 Foo 的原型对象,用 FooPrototype(自己假想的)表示。 Foo.prototype = FooPrototype; 在默认情况下,所有原型对象都会获得一个 constructor 属性,这个属性包含一个指向prototype属性所在函数的指针。当我们使用 new 来调用这个函数Foo创建一个实例时,该实例的内部会包含一个指针(内部属性),指向这个构造函数的原型对象,这个指针叫 [[prototype]] ,可以使用 proto 来访问这个原型对象。
function Foo () {
}
Foo.__proto__ === Function.prototype // true
var a = new Foo();
a.__proto__ === Foo.prototype; // true
Object.getPrototypeOf(a) === Foo.prototype; // true
Foo.prototype.__proto__ === Object.prototype; // true
Object.prototype.__proto__ === null;// true
Foo.prototype.constructor === Foo; // true
a.constructor === Foo; // true
a.constructor === Foo.prototype.constructor; // true
这里有个比较疑惑的点在于 a.constructor ,难道 a 也有 .constructor 属性?实际上a本身并没有 .constructor 属性,而且,虽然 a.constructor 确实指向 Foo 函数,但是这个属性并不是表示 a 有 Foo 构造 的。
实际上,.constructor 引用同样被委托给了 Foo.prototype ,而 Foo.prototype.constructor 默认指向 Foo 。举个例子:
function Foo () {
}
Foo.prototype = { /**/ };//创建一个新原型对象,相当于 new Object()。
var a1 = new Foo();
a1.constructor === Foo;//false
a1.constructor === Object.prototype.constructor;//true
a1.constructor === Object;//true
a1 并没有 .constructor 属性,所以它会委托 [[prototype]] 链上的 Foo.prototype 。但是这个对象也没有 .constructor 属性(不过默认的 Foo.prototype 对象有这个属性!),所以它会继续委托,这次它会委托给委托链顶端的 Object.prototype 。这个对象有 .constructor 属性,指向内置的 Object(...) 函数。
当然,我们可以给 Foo.prototype 添加一个 .constructor 属性,这需要手动添加一个符合正常行为的不可枚举属性。
function Foo () {
}
Foo.prototype = { /**/ };
Object.defineProperty({
enumerable: false,
writable: true,
configurable: true,
value: Foo // 让 .constructor 指向 Foo
})
JavaScript 里其他的引用类型,如 Array ,Date ,RegExp ,Function ,String ,Number ,Boolean 等。举例如下:
var a = new Array();
a.__proto__ === Array.prototype; // true
a.__proto__.__proto__ === Object.prototype; // true
a.__proto__.__proto__.__proto__ === null; // true
Array.prototype.constructor === Array;//true
a.constructor === Array;//true
a.constructor === Array.prototype.constructor;//true
Array.constructor === Function;// true
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论