使用原型的优点,vs直接在构造函数中定义方法?

我想知道使用这些方法是否有什么优点,我应该走哪条路?

构造函数的方法:

var Class = function () {


this.calc = function (a, b) {
return a + b;
};


};

原型的方法:

var Class = function () {};


Class.prototype.calc = function (a, b) {
return a + b;
};

我不喜欢这样,使用原型,方法定义从类中分离出来,我不知道是否有任何特定的原因,我应该使用这种方法而不仅仅是第一种方法。

另外,使用函数字面量来定义“类”比仅仅使用函数定义有什么好处:

var Class = function () {};

vs

function Class () {};

谢谢!

93465 次浏览

通过原型链继承的方法可以对所有实例进行通用更改,例如:

function Class () {}
Class.prototype.calc = function (a, b) {
return a + b;
}


// Create 2 instances:
var ins1 = new Class(),
ins2 = new Class();


// Test the calc method:
console.log(ins1.calc(1,1), ins2.calc(1,1));
// -> 2, 2


// Change the prototype method
Class.prototype.calc = function () {
var args = Array.prototype.slice.apply(arguments),
res = 0, c;


while (c = args.shift())
res += c;


return res;
}


// Test the calc method:
console.log(ins1.calc(1,1,1), ins2.calc(1,1,1));
// -> 3, 3

注意如何更改应用于两个实例的方法?这是因为ins1ins2共享相同的calc()函数。为了使用构造过程中创建的公共方法来实现这一点,您必须将新方法分配给已创建的每个实例,这是一项棘手的任务。这是因为ins1ins2有它们自己单独创建的calc()函数。

在构造函数内部创建方法的另一个副作用是性能较差。每次构造函数运行时都必须创建每个方法。原型链上的方法只创建一次,然后由每个实例“继承”。另一方面,公共方法可以访问“私有”变量,这在继承方法中是不可能的。

至于你的function Class() {} vs var Class = function () {}问题,前者在执行前被“提升”到当前作用域的顶部。对于后者,提升的是变量声明,而不是赋值。例如:

// Error, fn is called before the function is assigned!
fn();
var fn = function () { alert("test!"); }


// Works as expected: the fn2 declaration is hoisted above the call
fn2();
function fn2() { alert("test!"); }

原型方法的优点是效率高。所有Class对象(这里指的是通过调用Class构造函数创建的对象)之间共享一个calc()函数对象。另一种方法(在构造函数中分配方法)为每个Class对象创建一个新的函数对象,在调用Class构造函数时使用更多内存并占用更多处理时间。然而,这种方法确实有一个优势:calc()方法可以访问构造函数中的局部变量,你可以利用它:

function Class() {
var calcCallCount = 0;


this.calc = function (a, b) {
++calcCallCount;
alert("Calc called " + calcCallCount + " times");
return a + b;
};
};

关于var Class = function() {...}function Class() {...},我通常更喜欢后者,因为它意味着函数有一个名称,在调试时很有用。另一个区别是后一个版本(函数声明)被提升,这意味着它在定义范围内的任何地方都可用,而不仅仅是在定义之后。然而,有些人更喜欢在任何地方使用前者(函数表达式)。

var YourClass = function(){
var privateField = "somevalue";
this.publicField = "somevalue";
this.instanceMethod1 = function(){
//you may access both private and public field from here:
//in order to access public field, you must use "this":
alert(privateField + "; " + this.publicField);
};
}


YourClass.prototype.instanceMethod2 = function(){
//you may access only public field 2 from this method, but not private fields:
alert(this.publicField);
//error: drawaback of prototype methods:
alert(privateField);
};

原型法的优点:

  1. 当你通过原型定义方法时,它们会被所有YourClass实例共享。因此,这些实例的总大小为<而不是在构造函数中定义方法;有测试表明,通过原型方法定义如何减少html页面的总大小,从而降低其加载速度。

  2. 通过prototype定义的方法的另一个优点是,当你使用继承类时,你可以重写这样的方法,在派生类的重写方法中,你可以调用基类的同名方法,但在构造函数中定义的方法,你不能这样做。