【自我解惑】constructor

Author Avatar
Klein 3月 12, 2019

今天在复习 JavaScript 原型的时候发现了一个疑惑:

1
2
3
4
function Foo (){}
Foo.prototype.constructor === Foo.constructor // false
Foo.prototype.constructor // ƒ Foo (){}
Foo.constructor // ƒ Function() { [native code] }

嗯?不是说 prototypeconstructor 属性指向函数本身吗?

先分析一下右边:

Foo.prototype.constructor 指向 Foo 函数本身。

左边:

这里是原型链的知识:

访问一个对象的属性时,会先在基本属性中查找,如果没有,再沿着 __proto__ 这条链向上找。

Foo 本身并没有 constructor 属性,所以会沿着 __proto__ 查找:

然后就是隐式原型 __proto__ 的知识点了:

所有的引用类型的 __proto__ 属性值都指向它的构造函数的 prototype 属性值

1
Foo.__proto__ === Function.prototype // true

所以等号左边的 Foo.constructor 会等于 Foo.__proto__.constructor 并等于 Function.prototype.constructor

1
2
3
4
5
6
7
8
Foo.constructor // 1
Foo.__proto__.constructor // 2
Function.prototype.constructor // 3
Foo.constructor === Foo.__proto__.constructor // true 1等于2
Foo.constructor === Function.prototype.constructor // true 1等于3
Foo.__proto__.constructor === Function.prototype.constructor // true 2等于3
// ∵ 1等于2,1等于3,2等于3
// ∴ 1 = 2 = 3

你问为什么要这样大费周章的写?

1
Foo.constructor === Foo.__proto__.constructor === Function.prototype.constructor

等式会最先从最右边开始解析:

1
2
(Foo.constructor === (Foo.__proto__.constructor === Function.prototype.constructor))
(Foo.constructor === true) // false

分析:

我搞混了原型链的知识:

当对象的基本属性中没有要查找的属性,会沿着 __proto__ 这条链向上找,而不是 prototype 这条链。