Interesting Points
- 所有实例都会继承创建这个实例的函数的原型对象 (prototype object)。
- 一些浏览器会有一个具体实践:__proto__ 属性。它指向创造这个对象的函数的原型对象。(注:上图最上面绿和蓝虚线)
- 无论是否存在 __proto__ 属性,所有对象都使用创造该对象的方法的 prototype object。 此属性是 Javascript 标准的一部分,称为原型 (prototype)。 默认情况下,prototype object 有一个 constructor 属性,指向把该 prototype object 作为原型的的函数。(注:上图绿黑实线、蓝黑实线、橙黑实线)
- prototype 被函数的实例当作属性继承。而这个函数本身不使用关联的原型(注:也就是下面代码的 Foo.x),这个函数其实也是一个对象,比如图中的 Foo() 继承了 JS 系统 Function 对象的 prototype object。(注:上图橙虚线)
function Foo() { } ;
var f1 = new Foo();
Foo.prototype.x = "hello";
f1.x //=> hello
Foo.x //=> undefined
// 注意,我们用 Foo.prototype 来设置属性给由 Foo 创建的对象来使用。
// 我们不会说 f1 用 f1.prototype 设置属性给自己用。
- 默认 prototype object 可以被用户替换掉。在这样做时,必须手动设置 prototype.constructor 属性,使其指向原来的函数。
function foo() { } ; var f1 = new foo();
f1.constructor === foo.prototype.constructor === foo
//replace the default prototype object
foo.prototype = new Object();
//create another instance l
f1 = new foo();
//now we have:
f1.constructor === foo.prototype.constructor === Object
//so now we say:
foo.prototype.constructor = foo
//all is well again
f1.constructor === foo.prototype.constructor === foo
- 每个 prototype object 默认由 Object() constructor 创造,因此 prototype 具有原型 Object.prototype(注:第一条 point)。所以无论什么类型,所有实例最总都从 Object.prototype 继承属性。
- 所有对象优先读取自己的属性,未定义的话则读取原型链 (prototype chain) 中的属性。
function foo() { }
f1 = new foo();
f2 = new foo();
foo.prototype.x = "hello";
f1.x => "hello"
f2.x => "hello";
f1.x = "goodbye"; //setting f1.x hides foo.prototype.x
f1.x => "goodbye" //hides "hello" for f1 only
f2.x => "hello"
delete f1.x
f1.x => "hello"; //foo.prototype.x is visible again to f1.
More Interesting points
观察上图的各种箭头,你能看到一些 js 中有趣的关系。
- Function.__proto__ 指向 Function.prototype。结果是:Function.constructor === Function也就是说:Function 是自己的 constructor!
- Object instanceof Object == true.这是因为:Object.__proto__.__proto__.constructor == Object注意:不像 Object instanceof Object,Foo instanceof Foo == false。
This is because: Foo does not exist as a constructor for it’s own prototype chain.
- Function.prototype.toString 是一个内置方法,并且和另一个内置方法 Object.prototype.toString 完全不同。
f1.toString() finds:
Object.prototype.toString
We get something like: [object ...]
然而:
Foo.toString() first finds & uses:
Function.prototype.toString()
We get something like: [Function foo...]
如果这样:
delete Function.prototype.toString
Foo.toString()
We get something like: [object ...]
引用