在 Javascript 中重新定义原型与附加到原型
Redefining prototype vs appending to prototype in Javascript
从这里开始:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures
Performance considerations
function MyObject(name, message) {
this.name = name.toString();
this.message = message.toString();
}
MyObject.prototype = {
getName: function() {
return this.name;
},
getMessage: function() {
return this.message;
}
};
However, redefining the prototype is not recommended. The following example instead appends to the existing prototype:
function MyObject(name, message) {
this.name = name.toString();
this.message = message.toString();
}
MyObject.prototype.getName = function() {
return this.name;
};
MyObject.prototype.getMessage = function() {
return this.message;
};
以上引用和代码来自给定的 link.
我想了解第一个代码如何提示我们正在重新定义原型,而第二个代码如何提示我们正在附加原型?
上面几段代码中什么代表重定义什么代表追加?
第一个代码 MyObject.prototype = { ... }
建议重新定义原型,因为我们将全新的对象设置为 MyObject.prototype
。
但第二个代码建议附加,因为它仅通过对象的特定键(getName
和 getMessage
)分配函数。
当您重新定义 prototype
对象时,您正在创建一个全新的对象,而不是保留现有原型及其属性,这是不可取的。
如果我们重新定义原型对象,它会打破继承层次。特别是 instanceof
和 Object.prototype.isPrototypeOf
将无法按预期工作。
让我们举个例子,展示一个简单的继承层次结构,ChildClassOne
和 ChildClassTwo
继承自 ParentClass
。
在第一种情况下,继承被打破,因为 prototype
被一个全新的对象覆盖,该对象擦除已经存在的所有信息,而不是附加到从 Object.create
接收到的原型打电话。
在第二种情况下,它按预期工作,因为原型没有被替换:
function ParentClass(param) {
this.param = param;
}
ParentClass.prototype.getParam = function() {
return this.param;
}
function ChildClassOne(param, name, message) {
ParentClass.call(param);
this.name = name.toString();
this.message = message.toString();
}
//Inheriting through prototype
ChildClassOne.prototype = Object.create(ParentClass.prototype);
ChildClassOne.constructor = ChildClassOne;
//Prototype completely overriden, destroying the hierarchy
ChildClassOne.prototype = {
getName: function() {
return this.name;
},
getMessage: function() {
return this.message;
}
};
//the instanceof and isPrototypeOf is broken
const child1 = new ChildClassOne("bazz", "foo", "bar");
console.log(child1 instanceof ParentClass);
console.log(ParentClass.prototype.isPrototypeOf(child1));
console.log(ChildClassOne.prototype instanceof ParentClass)
function ChildClassTwo(param, name, message) {
ParentClass.call(param);
this.name = name.toString();
this.message = message.toString();
}
//Inheriting through prototype
ChildClassTwo.prototype = Object.create(ParentClass.prototype);
ChildClassTwo.constructor = ChildClassTwo;
//Preserving the heirarchy information, by appending to existing prototype
ChildClassTwo.prototype.getName = function() {
return this.name;
};
ChildClassTwo.prototype.getMessage = function() {
return this.message;
}
//Works as expected
const child2 = new ChildClassTwo("bazz", "foo", "bar");
console.log(child2 instanceof ParentClass);
console.log(ParentClass.prototype.isPrototypeOf(child2));
console.log(ChildClassTwo.prototype instanceof ParentClass)
从这里开始:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures
Performance considerations
function MyObject(name, message) {
this.name = name.toString();
this.message = message.toString();
}
MyObject.prototype = {
getName: function() {
return this.name;
},
getMessage: function() {
return this.message;
}
};
However, redefining the prototype is not recommended. The following example instead appends to the existing prototype:
function MyObject(name, message) {
this.name = name.toString();
this.message = message.toString();
}
MyObject.prototype.getName = function() {
return this.name;
};
MyObject.prototype.getMessage = function() {
return this.message;
};
以上引用和代码来自给定的 link.
我想了解第一个代码如何提示我们正在重新定义原型,而第二个代码如何提示我们正在附加原型?
上面几段代码中什么代表重定义什么代表追加?
第一个代码 MyObject.prototype = { ... }
建议重新定义原型,因为我们将全新的对象设置为 MyObject.prototype
。
但第二个代码建议附加,因为它仅通过对象的特定键(getName
和 getMessage
)分配函数。
当您重新定义 prototype
对象时,您正在创建一个全新的对象,而不是保留现有原型及其属性,这是不可取的。
如果我们重新定义原型对象,它会打破继承层次。特别是 instanceof
和 Object.prototype.isPrototypeOf
将无法按预期工作。
让我们举个例子,展示一个简单的继承层次结构,ChildClassOne
和 ChildClassTwo
继承自 ParentClass
。
在第一种情况下,继承被打破,因为 prototype
被一个全新的对象覆盖,该对象擦除已经存在的所有信息,而不是附加到从 Object.create
接收到的原型打电话。
在第二种情况下,它按预期工作,因为原型没有被替换:
function ParentClass(param) {
this.param = param;
}
ParentClass.prototype.getParam = function() {
return this.param;
}
function ChildClassOne(param, name, message) {
ParentClass.call(param);
this.name = name.toString();
this.message = message.toString();
}
//Inheriting through prototype
ChildClassOne.prototype = Object.create(ParentClass.prototype);
ChildClassOne.constructor = ChildClassOne;
//Prototype completely overriden, destroying the hierarchy
ChildClassOne.prototype = {
getName: function() {
return this.name;
},
getMessage: function() {
return this.message;
}
};
//the instanceof and isPrototypeOf is broken
const child1 = new ChildClassOne("bazz", "foo", "bar");
console.log(child1 instanceof ParentClass);
console.log(ParentClass.prototype.isPrototypeOf(child1));
console.log(ChildClassOne.prototype instanceof ParentClass)
function ChildClassTwo(param, name, message) {
ParentClass.call(param);
this.name = name.toString();
this.message = message.toString();
}
//Inheriting through prototype
ChildClassTwo.prototype = Object.create(ParentClass.prototype);
ChildClassTwo.constructor = ChildClassTwo;
//Preserving the heirarchy information, by appending to existing prototype
ChildClassTwo.prototype.getName = function() {
return this.name;
};
ChildClassTwo.prototype.getMessage = function() {
return this.message;
}
//Works as expected
const child2 = new ChildClassTwo("bazz", "foo", "bar");
console.log(child2 instanceof ParentClass);
console.log(ParentClass.prototype.isPrototypeOf(child2));
console.log(ChildClassTwo.prototype instanceof ParentClass)