likes
comments
collection
share

解密JavaScript中的this关键字(法外篇)

作者站长头像
站长
· 阅读数 11

"在JavaScript中,this关键字的行为由一系列规则确定。然而,除了这些规则之外,还存在一些特殊情况需要额外注意。本文将探讨JavaScript中this规则之外的一些情况。"

引言

JavaScript中的this关键字在函数执行过程中扮演着重要的角色,它决定了函数在运行时的上下文环境。在之前的文章中,我们讨论了this的四种标准规则:默认绑定、隐式绑定、显式绑定和new绑定。然而,除了这些规则之外,JavaScript还存在一些特殊情况需要特别留意。本文将探索这些规则之外的情况,帮助您更好地理解和应用this关键字。

正文

忽略显示绑定

在显示绑定中,如果传入null或undefined作为参数,this的绑定会被忽略,使用默认规则。考虑以下示例:

javascriptCopy code
function foo() {
  console.log(this);
}

var obj = {
  name: "why"
}

foo.call(obj); // 输出:obj对象
foo.call(null); // 输出:window
foo.call(undefined); // 输出:window

var bar = foo.bind(null);
bar(); // 输出:window

在上述示例中,通过call方法将函数foo与对象obj绑定,此时this指向obj对象。然而,当传入nullundefined时,显示绑定被忽略,this使用默认规则,指向全局对象window

间接函数引用

另一个情况是通过间接引用来创建函数的引用,此时使用默认绑定规则。考虑以下示例:

javascriptCopy code
var num1 = 100;
var num2 = 0;
var result = (num2 = num1);
console.log(result); // 输出:100

function foo() {
  console.log(this);
}

var obj1 = {
  name: "obj1",
  foo: foo
}; 

var obj2 = {
  name: "obj2"
}

obj1.foo(); // 输出:obj1对象
(obj2.foo = obj1.foo)();  // 输出:window

在上述示例中,(num2 = num1)的结果是num1的值,即100。对于函数赋值 (obj2.foo = obj1.foo),由于立即调用了函数,因此遵循默认绑定规则。在函数foo中,this会绑定到全局对象window

ES6箭头函数

在ES6中引入了箭头函数,它们是一种非常实用的函数类型。箭头函数不使用四种标准规则来确定this的值,而是根据外层作用域来决定this的值。

考虑以下模拟网络请求的示例:

javascriptCopy code
var obj = {
  data: [],
  getData: function() {
    var _this = this;
    setTimeout(function() {
      // 模拟获取到的数据
      var res = ["abc", "cba", "nba"];
      _this.data.push(...res);
    }, 1000);
  }
}

obj.getData();

在上述示例中,我们使用setTimeout来模拟网络请求。为了能够在回调函数中访问到obj对象,我们在外部定义了变量_this来保存obj对象的引用,然后在setTimeout的回调函数中使用_this来操作data数组。

从ES6开始,我们可以使用箭头函数来简化代码:

javascriptCopy code
var obj = {
  data: [],
  getData: function() {
    setTimeout(() => {
      // 模拟获取到的数据
      var res = ["abc", "cba", "nba"];
      this.data.push(...res);
    }, 1000);
  }
}

obj.getData();

由于箭头函数不绑定this对象,它会从上层作用域中找到对应的this值。因此,箭头函数中的this会指向外层作用域中的this,即obj对象。

思考一下,如果将getData也改为箭头函数,那么setTimeout的回调函数中的this将指向谁呢?答案是window,因为箭头函数会继续向上层作用域查找,最终找到全局作用域,而在全局作用域中,this代表的就是window对象。

javascriptCopy code
var obj = {
  data: [],
  getData: () => {
    setTimeout(() => {
      console.log(this); // 输出:window
    }, 1000);
  }
}

obj.getData();

总结

本文介绍了JavaScript中this规则之外的一些情况。了解这些特殊情况可以帮助我们更好地理解和应用this关键字。通过忽略显示绑定中的null和undefined参数,我们可以使用默认规则确定this的值。在间接函数引用中,函数被直接调用时会遵循默认绑定规则。此外,ES6的箭头函数不会绑定this对象,而是根据外层作用域来决定this的值。我们希望本文能够帮助您更好地理解和应用JavaScript中this规则之外的情况。