【问题标题】:How prototype method work?原型方法如何工作?
【发布时间】:2014-11-28 15:56:03
【问题描述】:

我正在尝试理解原型继承。但不清楚以下代码:

var obj1 = {
   objMethod : function(){
     return 'name: ' + this.name;
   }
};

var obj2 = {
  [[Prototype]] : obj1,
  name : 'Bhojendra'
};

所以,为了理解代码要表达的意思,我试过了:

obj2.objMethod();
obj1.objMethod();

但是会抛出错误。那么,代码试图说明原型是什么?以及如何使用它?

【问题讨论】:

  • “obj2”代码看起来不像是有效的 JavaScript(甚至是 ES6)。
  • [[Prototype]] 是 EMCAScript 规范用来描述原型设计行为如何工作的概念上的“内部属性”。不能直接按名称设置;当您使用new Constructor(将[[Prototype]] 设置为Constructor.prototype)或使用Object.create(proto)(将[[Prototype]] 设置为proto )。
  • 那么,这本书想告诉我什么?
  • 我想知道这本书的名字。

标签: javascript


【解决方案1】:

这是无效代码:

var obj2 = {
  [[Prototype]] : obj1,
  name : 'Bhojendra'
};

您使用的规范语言不是实际语言语法的一部分。

目前没有(标准)方法可以在对象字面量中设置原型对象,但它会出现在 ECMAScript 6 中。

此时,您将能够在浏览器环境和其他决定支持该语法的环境中执行此操作:

var obj2 = {
  __proto__ : obj1,
  name : 'Bhojendra'
};

目前这在某些浏览器中确实有效,但在 ECMAScript 6 最终确定并包含它之前,它不是官方语法。


所以语言规范通过引用[[Prototype]] 所做的是对原型链中的下一个对象进行通用引用。

例如,假设我有一个这样的构造函数:

function Foo() {
    this.x = 123;
}

我们从构造函数创建一个对象,如下所示:

var foo = new Foo();

现在foo 对象的原型链如下所示:

foo --> Foo.prototype --> Object.prototype --> null

foo 对象的[[Prototype]] 是位于Foo.prototype 的对象。因此,当您在 foo 对象上查找属性时,如果找不到,它将继续在 Foo.prototype 对象上进行搜索。它继续沿着链向下直到找到您的属性或用完要搜索的对象,然后返回undefined


因此,原型继承的概念性高级模型应该是这样的:

原型链只是一个对象链。假设您想要一个对象,如果您在其中找不到属性,它会自动在另一个对象上查找属性。假设另一个对象被设置为在另一个对象上寻找它。这就是原型链。

my_obj -> other_obj -> another_obj 

如果您在 my_obj 上找不到属性,它将自动在链中的下一个对象上搜索它,依此类推,直到找到它或返回 undefined

JavaScript 使用“构造函数”以一种有点奇怪和令人困惑的方式来设置它。更清晰的方法是使用Object.create() 进行设置。

var another_obj = {foo: "FOO"}; // `another_obj` inherits from `Object.prototype`

// prototype chain of `another_obj` is...
// another_obj -> Object.prototype -> null


var other_obj = Object.create(another_obj); // `other_obj` inherits from `another_obj`

// prototype chain of `other_obj` is...
// other_obj -> another_obj -> Object.prototype -> null


var my_obj = Object.create(other_obj); // `my_obj` inherits from `other_obj`

// prototype chain of `my_obj` is...
// my_obj -> other_obj -> another_obj -> Object.prototype -> null

【讨论】:

  • 请用我对本书感兴趣的原型链扩展您的答案。谢谢。
  • @Bhojendra-C-LinkNepal:我已经更新了一点。原型链只是一个对象链。假设您想要一个对象,如果您在其中找不到属性,它会自动在另一个对象上查找属性。假设另一个对象被设置为在另一个对象上寻找它。这就是原型链。 my_obj -> other_obj -> another_obj 如果在 my_obj 上找不到属性,它将自动在链中的下一个对象上搜索它,依此类推,直到找到它或返回 undefined
  • 如果 obj2 继承自 obj1 那么 obj1 也自动继承自 obj2? (混淆了这些对象之间的关系)
  • @Bhojendra-C-LinkNepal:不,箭头只指向一个方向。您可以拥有许多都继承自同一个对象的对象。就像在Foo 构造函数示例中一样,您可以使用new Foo() 创建许多对象。所有这些新对象都指向Foo.prototype,但Foo.prototype 不知道这些对象。
【解决方案2】:

请试试这个:

var obj1 = {
objMethod : function(){
    return 'name: ' + this.name;
    }
};

var obj2 = {
    __proto__ : obj1,
    'name' : 'Bhojendra'
};

console.log(obj2.objMethod());
console.log(obj1.objMethod());

问题在于你如何定义obj2的原型。

取自here

对象继承自其构造函数的原型属性,而不是其 自己的。构造函数的原型分配给内部 [[Prototype]] 属性在某些浏览器中作为 proto 属性。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-06-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-03-15
    相关资源
    最近更新 更多