这个JavaScript成语的基础是:var self = this?

时间:2009-06-07 14:59:30

标签: javascript scope closures

我在WebKit HTML 5 SQL Storage Notes Demo的来源中看到以下内容:

function Note() {
  var self = this;

  var note = document.createElement('div');
  note.className = 'note';
  note.addEventListener('mousedown', function(e) { return self.onMouseDown(e) }, false);
  note.addEventListener('click', function() { return self.onNoteClick() }, false);
  this.note = note;
  // ...
}

作者在某些地方(函数体)使用 self ,在其他地方使用 this (在方法的参数列表中定义的函数体)。这是怎么回事?现在我已经注意到它了,我会在各处开始看到它吗?

10 个答案:

答案 0 :(得分:419)

请参阅此article on alistapart.com

self用于维护对原始this的引用,即使上下文正在发生变化。这是一种常用于事件处理程序的技术(特别是在闭包中)。

答案 1 :(得分:96)

我认为变量名'self'不应再以这种方式使用了,因为现代浏览器提供了一个global variable self指向普通窗口或WebWorker的全局对象。

为避免混淆和潜在冲突,您可以改为编写var thiz = thisvar that = this

答案 2 :(得分:34)

是的,你会在任何地方看到它。通常是that = this;

了解如何在事件调用的函数中使用self?这些将有自己的上下文,因此self用于保存this中的Note()

self仍然可用于函数的原因,即使它们只能在Note()函数执行完毕后才能执行,因为内部函数由于 闭合

答案 3 :(得分:28)

还应该注意,如果您不喜欢this成语,则可以使用另一种代理模式来维护对回调中原始var self = this的引用。

由于可以使用function.applyfunction.call使用给定的上下文调用函数,因此可以编写一个包装器,该函数返回一个函数,该函数使用apply或{{1使用给定的上下文。有关此模式的实现,请参阅jQuery的call函数。以下是使用它的示例:

proxy

然后可以调用

var wrappedFunc = $.proxy(this.myFunc, this);,并将您的wrappedFunc版本作为上下文。

答案 4 :(得分:9)

该变量由方法中定义的内联函数捕获。函数中的this将引用另一个对象。这样,您可以使该函数保留对外部范围中this的引用。

答案 5 :(得分:9)

这是一个JavaScript的怪癖。当一个函数是一个对象的属性时,更恰当地称为一个方法,这个引用该对象。在事件处理程序的示例中,包含对象是触发事件的元素。调用标准函数时,将引用全局对象。如示例所示,当您具有嵌套函数时,根本不与外部函数的上下文相关。内部函数与contains函数共享范围,因此开发人员将使用var that = this的变体来保留内部函数中所需的 this

答案 6 :(得分:7)

正如其他人所解释的那样,var self = this;允许closure中的代码引用回父范围。

然而,它现在是2018年,ES6得到了所有主要网络浏览器的广泛支持。 var self = this;成语并不像以前那么重要。

现在可以通过使用arrow functions来避免var self = this;

在我们使用var self = this的情况下:

function test() {
    var self = this;
    this.hello = "world";
    document.getElementById("test_btn").addEventListener("click", function() {
        console.log(self.hello); // logs "world"
    });
};

我们现在可以使用不带var self = this的箭头功能:

function test() {
    this.hello = "world";
    document.getElementById("test_btn").addEventListener("click", () => {
        console.log(this.hello); // logs "world"
    });
};

箭头函数没有自己的this,只是假定封闭范围。

答案 7 :(得分:5)

实际上self是对窗口(window.self)的引用,因此当你说var self = 'something'覆盖对自身的窗口引用时 - 因为self存在于window对象中。

这就是为什么大多数开发人员更喜欢var that = this而不是var self = this;

反正; var that = this;与良好实践不一致......假设您的代码稍后会被其他开发人员修改/修改,您应该使用与开发人员社区相关的最常见的编程标准

因此你应该使用像var oldThis / var oThis / etc这样的东西 - 在你的范围内清楚// ..不是那么多,但会节省几秒钟和几个脑循环

答案 8 :(得分:0)

如上所述,“self”只是用于在进入函数之前保持对“this”的引用。一旦进入函数'this'指的是其他东西。

答案 9 :(得分:-1)

function Person(firstname, lastname) {
  this.firstname = firstname;

  this.lastname = lastname;
  this.getfullname = function () {
    return `${this.firstname}   ${this.lastname}`;
  };

  let that = this;
  this.sayHi = function() {
    console.log(`i am this , ${this.firstname}`);
    console.log(`i am that , ${that.firstname}`);
  };
}

let thisss = new Person('thatbetty', 'thatzhao');

let thatt = {firstname: 'thisbetty', lastname: 'thiszhao'};

thisss.sayHi.call(thatt);