以下两个Javascript原型之间的功能差异是什么,选择其中一个有什么好处?
选项1:
Person.prototype.sayName = function(name) {
alert(name);
}
选项2:
Person.prototype = {
sayName: function(name) {
alert(name);
}
}
假设选项2 导致某些隐含绑定到原型的函数被废弃,我是否正确?
答案 0 :(得分:5)
我是否认为选项2会导致某些与原型隐式绑定的函数混乱?
是的,确切地说。虽然唯一隐式绑定的属性是constructor
属性,但您很少需要它。
有哪些功能差异?
选项1只是扩展现有原型。如果已经从原型对象继承了Person
个实例,那么它们也可以使用sayName
方法。使用选项2,新原型将仅用于在覆盖后实例化的对象。
选择其中一个是否有任何好处?
这些应该是现在自我解释的。选项1(扩展)被认为是更清晰的,如果您正在修改外来/未知/原生原型,则必须使用它。尽量避免使用选项2.
如果您仍然更喜欢对象文字语法,则应考虑使用Object.assign
扩展现有原型:
Object.assign(Person.prototype, {
sayName: function(name) {
alert(name);
}
});
对于ES6之前的环境,您可能需要polyfill Object.assign
。或者,$.extend
或_.extend
也可以正常工作。当然,您最喜欢的库也带有辅助功能。
答案 1 :(得分:3)
第二个将用对象覆盖person.prototype。
方法一:
Object.toString=function(){
return "Object to string";
}
var Person = function(){
};
Person.toString=function(){
return "Person to string";
}
Person.prototype.sayName=function(){}
console.log(Person.prototype.constructor.toString());// "Person to string"
方法二:
Object.toString=function(){
return "Object to string";
}
var Person = function(){
};
Person.toString=function(){
return "Person to string";
}
Person.prototype = {
sayName:function(){}
}
console.log(Person.prototype.constructor.toString());// "Object to string"
答案 2 :(得分:2)
第一个适用于一个或两个额外的功能,但是定义具有许多功能的全新原型将是非常重复的。另一方面,如上所述,执行后者会破坏原型的所有现有定义。
在实践中,我使用第一个来定义Array和Math等中的附加函数,有点像Objective-C中的类别。后者我用作“类定义”。
答案 3 :(得分:1)
构造函数的任何现有实例都将继续指向旧的原型对象。创建的任何新实例都将指向新的原型对象。
选项1优于选项2的优点很简单,就是您不必重新构建构造函数属性,并且保存一个对我来说很大的缩进级别。
为了节省重复,我只需将属性分配给局部变量:
var method = Person.prototype;
method.getAge = function() {
return this.age;
};
method.getName = function() {
return this.name;
};
常见的选择是fn
(jQuery)和p
,它们甚至比method
更短。
答案 4 :(得分:0)
简单来说,差异在于Person.prototype.sayName
,您所做的就是向prototype
添加一个函数。只是添加新功能。
在第二个Person.prototype = {}
中,您正在创建一个新的整个对象并将其分配给prototype
。因此,您创建新对象或使用新对象覆盖prototype
。
第一种方法可以根据需要添加许多功能按需。你可以按时添加它们,所以当你的程序很简单并且你的应用程序对象不能在它们之间共享很多函数或对象时,我认为这很好。
如果您的应用程序对象在其中共享一些对象(或Math functions
中所说的@isaach中的一组函数),则第二种方法很好。