与直接在构造函数中定义方法相比,使用原型的优点是什么?

2022-08-29 23:52:43

我想知道使用其中任何一个是否比其他任何一个有什么优势,我应该走哪条路?

构造函数方法:

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 () {};

function Class () {};

谢谢!


答案 1

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

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

注意如何更改应用于两个实例的方法?这是因为 和 共享相同的功能。为了使用在构造期间创建的公共方法来执行此操作,您必须将新方法分配给已创建的每个实例,这是一项艰巨的任务。这是因为并且将拥有自己的单独创建的功能。ins1ins2calc()ins1ins2calc()

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

至于你的vs问题,前者在执行之前被“吊”到当前范围的顶部。对于后者,将提升变量声明,但不提升赋值。例如:function Class() {}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!"); }

答案 2

原型方法的优点是效率。所有对象之间共享一个函数对象(我的意思是通过调用构造函数创建的对象)。另一种方式(在构造函数中分配方法)为每个对象创建一个新的函数对象,在调用构造函数时使用更多的内存并花费更多的处理时间。但是,这种方法确实有一个优点:该方法可以访问构造函数中的局部变量,您可以使用它来发挥自己的优势:calc()ClassClassClassClasscalc()

function Class() {
    var calcCallCount = 0;

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

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