function Foo(name) { this.name = name; } Foo.prototype.myName = function () { return this.name; } var a = new Foo('a'); var b = new Foo('b'); a.myName(); // 'a' b.myName(); // 'b'
这段代码展示了“面向类”的 2 个技巧
1、this.name = name 给每个对象都添加了 .name 属性。(this 的 new 绑定规则)
2、Foo.prototype.myName 给 Foo.prototype对象添加了一个函数。a.myName 能正常工作是因为在创建的过程中,a 和 b 的内部都会关联到 Foo.prototype 上。当 a 和 b 中无法找到 myName 时,它会通过委托在 Foo.prototype 找到
a.constructor === Foo 为真意味着 a 确实有一个指向 Foo 的 .constructor 属性,但是事实不是这样。.constructor 引用同样被委托给了 Foo.prototype,而 Foo.prototype.constructor 默认指向 Foo
Foo.prototype 的 .constructor 属性只是 Foo 函数在声明时的默认属性。如果创建了一个新对象并替换了函数默认的 .prototype 对象引用,那么新对象并不会自动获得 .constructor 属性
function Foo() {/** .. */} Foo.prototype = {/** .. */} // 创建一个新原型对象 var a1 = new Foo(); a1.constructor === Foo; // false a1.constructor ==== Object; // true
a1 并没有 .constructor 属性,所以它会委托 [[Prototype]] 链上的 Foo.prototype。但是这个对象也没有 .constructor 属性,所以它会继续委托,这次会委托到委托链顶端的 Object.prototype。 这个对象有 .constructor 属性,指向内置的 Object(...) 函数。
当然也可以给 Foo.prototype 手动添加一个 .constructor 属性。.constructor 并不是一个不可变属性。所以 a1.constructor 实际上是不被信任的。它们不一定指向默认的函数引用。a1.constructor 是一个非常不可靠并且不安全的引用。通常来说要尽量避免使用这些引用