为什么这会返回对全局窗口对象的引用,即使“this”在另一个函数中

Why does this return a reference to the global window object, even though 'this' is within another function

本文关键字:this 即使 函数 另一个 引用 返回 全局 对象 窗口 为什么      更新时间:2023-09-26
if (typeof obj == 'undefined') {
  obj = {};
}
obj.thing = new function () {
  if (typeof this.global == 'undefined') {
    this.global = (function () {return this;})();
  }
}

this.global 被分配给函数内部的 this。那么,为什么这会返回对窗口对象的引用呢?

console.log(this) > DOMWindow
console.log(obj.thing.global) > DOMWindow
console.log(window) > DOMWindow

我很想更好地理解这一点。

在 ES 3 和 ES 5 中,有一个与每个执行上下文 (ES 3( 或词法环境 (ES 5( 关联的 this 关键字。该值是根据 ECMA-262 §10.4 中所述的输入全局代码或函数代码的规则设置的。

在您的代码中,您有:

  this.global = (function () {return this;})();  

其中调用匿名函数的结果分配给 this.global。在该匿名函数中,值是根据 §10.4.3 中的算法设置的。

由于调用函数时未设置 this 的值,并且代码未处于严格模式,因此 this 的值设置为全局对象(在浏览器中,通常是窗口对象(,每个算法的步骤 2

如果代码处于严格模式,则匿名函数中的 this 值将是未定义的,这是分配给 this.global 的值。

this是一个

始终返回当前上下文的关键字。试试这个:

if (typeof obj == 'undefined') {
  obj = {};
}
obj.thing = new function () {
  if (typeof this.global == 'undefined') {
    var self = this;
    this.global = (function () {return self;})();
  }
}

问题是,在自调用匿名函数中,上下文是全局对象,也就是window。因此,它返回window引用。即使 new 关键字创建了一个新对象作为外部函数的上下文。该外部上下文对于调用自调用函数无关紧要。

为了避免这种情况,您可以将代码稍微修改为:

obj.thing = new function () {
  if (typeof this.global == 'undefined') {
    this.global = (function (that) {return that;})(this);
  }
}
JavaScript

中的this非常棘手。它并不意味着你认为它的意思,并且确实可以通过很多小方式替换它的值,这取决于函数的调用方式。虽然它可以帮助优化并给你一定程度的功能和javascript知识点,但你可能想避免使用它,直到你对这个想法感到满意。

最好将"this"视为一个特殊变量,其中包含函数调用者传入的额外信息。 如果你想锁定值,你可以使用函数上的调用/应用方法或浏览器 Function.bind 或 _.bind 在库(如 underscore.js(中执行此操作。

var x = {
  name: "George",
  hiThere: function() { return "hi "+(this.name || "no value") ; }
}
x.hiThere(); // hi George
var thisWillBeGlobal = hiThere;
thisWillBeGlobal() // hi no value
var manuallyBoundToGeorge = function() {
  return x.hiThere();
}    
manuallyBoundToGeorge(); //hi George (always)
manuallyBoundToFred = function() {
  return x.hiThere.call({name: 'Fred'});
}
manuallyBoundToFred(); //hi Fred (always)
var hiGeorge = Function.bind(x.hiThere, x);
hiGeorge(); //hi George (always) - same as manual bind above

请注意,Function.bind 在较旧的浏览器中不可用,通常首选使用 underscroe 的 _.bind 之类的东西

  • 当然,在使用像jquery这样通过它传递信息的库时,你仍然会使用this