【发布时间】:2012-07-27 01:45:38
【问题描述】:
给定以下代码,我在弄清楚如何设置原型链时遇到了一些麻烦。
var Model = {
prototype: {
init: function(){},
log: function(){ console.log('instance method log was called') }
},
log: function(){ console.log('class method log was called') },
create: function() {
var object = Object.create(this);
object.parent = this;
object.prototype = object.fn = Object.create(this.prototype);
return object;
},
init: function() {
var instance = Object.create(this.prototype);
instance.parent = this;
instance.init.apply(instance, arguments);
return instance;
}
}
var User = Model.create();
User.log(); // 'class method log was called'
// create a new method after creation
Model.warn = function() { console.warn('warn was called') }
User.warn() // 'warn was called'
var user = User.init();
user.log(); // 'instance method log was called'
特别是这一行在 create 方法中让我感到困惑:
object.prototype = object.fn = Object.create(this.prototype);
我了解 create 方法如何创建一个原型指向 Model 的新对象,但倒数第二行似乎用新对象 (Model.prototype) 覆盖了该原型。但是,原来的原型似乎仍然完好无损,因为我可以在创建新对象后向模型添加方法,并且新对象仍然可以访问它。
有人能解释一下到底发生了什么吗?
编辑 - 我应该指出这段代码来自 O'reilly 的 Javascript Web Applications
【问题讨论】:
-
有点不清楚是什么让你感到困惑,但也许你认为
this和object指的是Model.create中的同一件事。如果是这样,他们不是。this是对Model的引用,但object是对从Object.create(this)创建的新对象的引用。因此,当您执行object.prototype = ...whatever时,您并没有覆盖Model.prototype,而是通过放置具有相同属性的属性来遮蔽存在于object原型链中的.prototype属性直接在object上命名。 -
我理解 'this' 是 Model 而 'object' 是一个新对象,让我感到困惑的是最初 Object.create(this) 将新对象原型设置为 'Model',但是然后几行之后 object.prototype 被重置为 Object.create(this.prototype)。这是我不明白的线。在我看来,object.prototype 现在设置为一个对象,其原型设置为 Model.prototype(init 和 log 函数),但返回的对象可以直接访问 Model 上的方法。
-
我想我明白什么让你感到困惑了。在
object上设置的.prototype属性与原型链本身无关。一旦你创建了一个对象,就不可能改变原型链。所以当一个值写入object.prototype时,它完全不会干扰object和Model之间的关系。唯一一次设置.prototype属性对原型链有影响,就是当您更改构造函数的.prototype属性时,只有构造函数生成的未来对象才会受到该更改的影响。 -
谢谢。这正是让我感到困惑的地方。
-
很高兴找到这个问题;我对书中相同的 sn-p 感到困惑。对于 JS 新手来说,使用
.prototype属性绝对是一个陷阱。
标签: javascript prototype object-create