为什么初始化的 JavaScript 对象不包含原型对象?

Why doesn't an initialized JavaScript object contain the prototype object?

我尝试使用以下代码向对象添加 start 方法:

var Bounce = Bounce || {
    Info : {},
    Game : {}
};

Bounce.Game.prototype.start = function() {
    Bounce.log("Starting " + new Bounce.Info());
}

但这会导致以下错误(在 Bounce.Game.prototype.start 行):

Uncaught TypeError: Cannot set property 'start' of undefined

查看 Chrome 控制台中的对象,我可以看到它不包含 prototype 对象(但有 toStringvalueOfconstructor 等.).

通过在原型访问之前添加以下行可以轻松解决此问题:

Bounce.Game = function() {};

我不知道为什么在对象已经初始化的情况下还需要这样做?

W3Schools 告诉我 "Every JavaScript object has a prototype",但事实并非如此。

从概念上讲,所有对象都有原型,但只有函数对象(包括 ObjectArray 这样的构造函数,尽管它们不产生函数)有 属性 名为 prototype。他们不一样。

如果你阅读 ECMAScript 规范,原型通常表示为 [[Prototype]],这是 JS 引擎的实现细节,而不是语言功能。然而,在一些引擎中 [[Prototype]] 被公开并且可以通过 __proto__ 属性 (非标准)访问。


顺便说一句:

  1. 如果你想访问[[Prototype]]Object.getPrototypeOf()是你的朋友。

  2. 使用a instanceof b时,实际上是在比较a[[Prototype]]链与bprototype属性.

  3. 而为什么说null是所有的原型呢?它也不是指 prototype 而是 [[Prototype]]:

    Object.getPrototypeOf(Object.getPrototypeOf({})) // null
    Object.getPrototypeOf(Object.getPrototypeOf(Object.getPrototypeOf([]))) // null
    Object.getPrototypeOf(Object.getPrototypeOf(Object.getPrototypeOf(new String("")))) // null
    
    // or shorter like this
    ({}).__proto__.__proto__ // null
    ([]).__proto__.__proto__.__proto__ // null
    ("").__proto__.__proto__.__proto__ // null
    

因此,受到 @Leo 评论的启发,我想到了这个解决方案,使用一个普通的 {} 对象及其原型。

我们有这个对象:

var Bounce = Bounce || {
    Info : {},
    Game : {}
};

我们为给定的对象定义prototype 属性

Object.defineProperty(Bounce.Game, 'prototype', {
    get: function() {
      return Object.getPrototypeOf(Bounce.Game); 
    }
});

现在,我们可以照常使用原型了:

Bounce.Game.prototype.start = function(){
  console.log('start');
};

Bounce.Game.start();

看看这个:http://jsbin.com/bapuvo/3/edit