1

我可以通过两种方式声明对象的方法:

第一种方式使用self=this成语。

function SelfIdiomExample(name){
    var self = this;

    self.sayHello = function (name){
         alert("Hello, "+name);
    }
}

当您需要在方法中引用对象时(例如,如果该方法将作为回调传递),这很有用。另一种方法是通过修改原型来做到这一点:

function PrototypeModExample(){
   //pass
}

PrototypeModExample.prototype.sayHello = function(name){
   alert("Hello, "+name);
}

两者都有相同的结果:

var sieg = new SelfIdiomExample();
var pmeg = new PrototypeModExample();

sieg.sayHello("Barnaby");
pmeg.sayHello("Josephine");

虽然我了解self=this成语的用例,但我想知道:

使用在构造函数中创建的方法与在原型上创建的方法相比,是否存在性能损失?

4

2 回答 2

2

好吧,这里:

var self = this;

根本就没有性能影响。它非常快,因为它只是访问一个局部变量。即使是嵌套函数,这在 JavaScript 中也是一个非常快速的操作。

但是,在构造函数中创建的方法与在原型中创建的方法具有巨大的性能差异。

在这个例子中:

var PrototypeModExample = function(){
  this.name = "Joe";
};

PrototypeModExample.prototype.sayHello = function(){
   alert("Hello, " + this.name);
};

var a = new PrototypeModExample();
var b = new PrototypeModExample();
console.log(a.sayHello === b.sayHello); // true

构造函数的每个实例都可以访问相同的函数对象。这可以通过使用===运算符比较两个实例上的函数对象来证明。true只有当它们是同一个对象时才会返回。因此,在全局范围内,我们现在有 2 个实例,但它们共享一个函数对象来实现该sayHello方法。这意味着当您想要创建一个新实例时,该函数已经设置并创建。

换句话说,所有实例都obj.sayHello指向同一个函数对象,该对象是在任何实例完全存在之前创建的。


但另一方面:

function SelfIdiomExample(name){
    var self = this;
    this.name = "Joe";

    this.sayHello = function(){
         alert("Hello, " + self.name);
    }
}

var a = new SelfIdiomExample();
var b = new SelfIdiomExample();
console.log(a.sayHello === b.sayHello); // false

工作方式不同。现在我们看到===比较是错误的。那是因为为每个实例创建了一个新的函数对象。创建此函数需要时间(需要对其进行解析)和内存(需要存储该函数的唯一版本)。因此,当创建大量此类实例时,此方法会更慢并消耗更多内存。

换句话说,所有实例都obj.sayHello指向一个唯一的函数对象,该对象是在创建实例本身时创建的。


因此,通常首选原型方法。特别是在可能存在大量实例的情况下,因为每个实例都可以共享其方法的函数对象。

于 2012-08-21T00:06:06.677 回答
1

与往常一样,您必须进行测试才能回答这样的问题:http: //jsperf.com/this-vs-self/2

当您进行测试时,似乎没有太大差异(self在某些情况下不到几个百分点,略有优势)。一个优点self是可以通过将其更改为单字符变量名来更好地最小化它,这显然是某些框架使用它的原因。

在您的示例中,我会说使用self是多余的而不是必要的。通常人们只在使用self闭包并且this某些回调中的值不再是您希望它是这样的时候使用:

counter.prototype.incrementWithDelay(delay) {
    var self = this;
    setTimeout(function() {
        self.counter++;
    }, delay);
}

但是,如果你只是有一个普通的方法,没有理由使用self.

counter.prototype.set(val) {
    this.counter = val;
}
于 2012-08-21T00:06:02.503 回答