这个JavaScript习惯用法的基础是什么:var self=this?

这个JavaScript习惯用法的基础是什么:var self=this?,javascript,scope,closures,Javascript,Scope,Closures,我在源代码中看到以下内容: 作者在某些地方使用self函数体,在其他地方使用方法参数列表中定义的函数体。发生什么事?现在我已经注意到了一次,我会开始到处看到它吗。埃德:这篇文章从最初链接到现在已经更新了 self被用来维护对原始文档的引用,即使上下文在变化。这是一种经常在事件处理程序中使用的技术,尤其是在闭包中 编辑:请注意,目前不鼓励使用self,如果不小心,可能会导致错误 你所说的变量并不特别重要。var=这个;很好,但是这个名字没有什么神奇之处 在上下文中声明的函数(例如回调、闭包)可以访

我在源代码中看到以下内容:

作者在某些地方使用self函数体,在其他地方使用方法参数列表中定义的函数体。发生什么事?现在我已经注意到了一次,我会开始到处看到它吗。埃德:这篇文章从最初链接到现在已经更新了

self被用来维护对原始文档的引用,即使上下文在变化。这是一种经常在事件处理程序中使用的技术,尤其是在闭包中

编辑:请注意,目前不鼓励使用self,如果不小心,可能会导致错误

你所说的变量并不特别重要。var=这个;很好,但是这个名字没有什么神奇之处

在上下文中声明的函数(例如回调、闭包)可以访问在相同或更高范围内声明的变量/函数

例如,一个简单的事件回调:

功能MyConstructoroptions{ 让那=这; this.someprop=options.someprop | |“defaultprop”; document.addEventListener“单击”,事件=>{ 注意,someprop; }; } 新MyConstructor{ 你好,世界
}; 该变量由方法中定义的内联函数捕获。函数中的此项将引用另一个对象。这样,您可以使函数在外部作用域中保留对This的引用。

是的,您可以在任何地方看到它。经常是这样

查看事件调用的函数中如何使用self?这些都会有自己的背景,所以self被用来保存记录下来的信息


原因self对函数仍然可用,即使它们只能在Note函数完成执行后执行,内部函数由于闭包而获得外部函数的上下文。

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

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

var wrappedFunc=$.proxythis.myFunc,this


然后可以调用wrappedFunc,并将您的版本作为上下文。

我认为变量名“self”不应该再以这种方式使用,因为现代浏览器提供指向普通窗口或WebWorker的全局对象的指针


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

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

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

无论如何;var=这个;不符合良好做法。。。假设您的代码稍后会被其他开发人员修改/修改,您应该使用开发人员社区中最常见的编程标准


因此,你应该使用像var oldThis/var oThis/etc这样的东西——在你的范围内要清楚//……没有那么多,但会节省几秒钟和几个大脑周期

如上几次所述,“self”只是用来在进入函数之前保留对“this”的引用。一旦在函数中,“this”指的是其他内容。

这是一个JavaScript怪癖。当一个函数是一个对象的属性时,更恰当地称为方法,它指的是对象。在事件处理程序的示例中,包含的对象是触发事件的元素。当调用标准函数时,它将引用全局对象。当您具有示例中的嵌套函数时,这与外部函数的上下文完全无关。内部函数确实与包含函数共享作用域,因此开发人员将使用var的变体this,以便在内部函数中保留所需的this。

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

然而,现在是2018年,所有主要的web浏览器都广泛支持ES6。var自=此;习语不像以前那么重要了

现在可以避免var self=这种情况;通过使用

在本应使用var self=的情况下:

现在,我们可以在不使用var self=的情况下使用箭头函数:

Arrow函数没有自己的范围,只是假设了封闭范围

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'};

这是sayHi.callthatt

这是一个JS语言功能,名为“词法闭包。可能与:。重复。下面解释了它的概念
在这个问题的答案中,明确地给出了一个相关的例子,如何在回调中访问正确的this?对我来说,令人信服的一点是self没有特殊的意义。我个人更喜欢使用名为self以外的变量,因为它经常让我感到困惑,因为我希望“self”是一个保留字。所以我喜欢你的回答。在OP的例子中,我更喜欢var thisNote=this或类似的方法。@steve同意,尽管我尽量避免使用this/self引用,因为它们在可维护性方面非常脆弱。我通常使用_this@djheru +1. 比我的大脑永远无法习惯的要好得多。我开始使用我:直到现代浏览器开始提供一个全局变量——这个,那个,或者我。使用self这个名字绝对没有问题,只要你把它声明为一个变量,它就会影响全局变量。当然,如果您忘记了var,那么它也不会与任何其他名称一起工作。@previor我认为它在最后一段之前是有意义的。@JohnPaul。。。这确实提供了一个答案。这可能不是正确的答案,但你怎么能说它已经被用来。。。这不是他为什么这么做的答案吗?你应该用代码来解释你做了什么特别。或者——震惊,恐怖!——为什么不把实际相关的东西作为参数传递给函数闭包呢?为什么要引用范围外状态,为什么有人会这样编程?从来没有任何真正的理由这样做。而是.addEventListenerClick,x=>{console.logx;};您已经非常清楚地解释了方法和原因,我同意使用箭头函数更有意义,但仍然。。。这就是糟糕、懒惰、混乱的编程。在JavaScript中,引用父范围是非常常见和必要的。它是语言的基本组成部分。您建议将父作用域作为事件处理程序的参数传入实际上是不可能的。此外,在ES6中,箭头函数使用词法作用域——“this”指的是它当前周围的作用域,而不是更进一步——它没有引用范围外状态或类似的东西@伯恩斯坦,谢谢。我会相应地更新答案。
function test() {
    var self = this;
    this.hello = "world";
    document.getElementById("test_btn").addEventListener("click", function() {
        console.log(self.hello); // logs "world"
    });
};
function test() {
    this.hello = "world";
    document.getElementById("test_btn").addEventListener("click", () => {
        console.log(this.hello); // logs "world"
    });
};
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'};