考虑到以下代码,我在确定如何设置原型链时遇到了一些麻烦。
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'
具体来说,这一行让我对创建方法感到困惑:
object.prototype = object.fn = Object.create(this.prototype);
我理解create方法是如何创建一个新对象,其原型指向Model,但倒数第二行似乎用新对象(Model.prototype)覆盖该原型。但是,原始原型似乎仍然完好无损,因为即使在创建新对象后我也可以向Model添加方法,新对象仍然可以访问它。
有人可以了解实际发生的事情吗?
编辑 - 我应该指出这段代码来自O'reilly的 Javascript Web Applications
答案 0 :(得分:2)
确定。所以只是为了删除噪音代码,你问这个代码:
var Model = {
prototype: {},
create: function() {
var object = Object.create(this);
object.prototype = Object.create(this.prototype);
return object;
}
};
Model.create()函数的第一行很简单,它创建了一个扩展(prototypes)Model的新对象。
但是你得到了反对,因为下一行会覆盖对象“prototype”属性。它不是对象的原型,对象原型仍然是Model,它存储在一个名为[[Prototype]]的隐藏属性中,代码修改的属性与对象的[[Prototype]]无关,它只有相同的名称。让我们更改名称以理解它,它将是相同的:
var Model = {
blablabla: {},
create: function() {
var object = Object.create(this);
object.blablabla = Object.create(this.blablabla);
return object;
}
};
它扩展了Model.blablabla,所以当你改变object.blablabla时,它不会影响Model.blablabla。
var SubModel = Model.create();
SubModel.blablabla.newMethod = function() { };
console.log(Model.blablabla.newMethod); // undefined
多次为字段选择正确的名称比看起来更重要。