Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

javaScript原型浅析 #20

Open
wengjq opened this issue Jan 23, 2018 · 0 comments
Open

javaScript原型浅析 #20

wengjq opened this issue Jan 23, 2018 · 0 comments
Labels

Comments

@wengjq
Copy link
Owner

wengjq commented Jan 23, 2018

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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant