[翻译]Javascript Object Layout

[翻译]Javascript Object Layout

Javascript Object Layout

大图

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 ...]

引用

mollypages.org

标签: js