js 重难点——this指向

113 阅读3分钟

在JavaScript编程中,理解和正确使用this关键字是非常重要的,因为它决定了函数内部代码的行为。本文将介绍JavaScript中this的相关规则和使用情况,并通过例子来帮助读者更好地理解这一概念。

this关键字的默认绑定规则

在JavaScript中,函数的this关键字默认绑定到全局对象(通常是window对象)。这意味着当一个函数被独立调用时,它的this将指向全局对象。

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

greet(); // 在浏览器环境下,输出为window对象

这种默认绑定规则可以在很多情况下带来便利,但有时也会导致意想不到的结果,特别是在嵌套函数或回调函数中。

隐式绑定规则

除了默认绑定规则外,JavaScript还提供了隐式绑定规则,当一个函数被对象所拥有且调用时,函数的this指向该对象。

var person = {
  name: 'Alice',
  greet: function() {
    console.log('Hello, ' + this.name);
  }
};

person.greet(); // 输出为"Hello, Alice"

在这个例子中,greet函数被person对象所拥有,并且通过person.greet()方式调用,this指向了person对象。

隐式丢失

然而,并不是所有情况下都能正确地使用隐式绑定规则。当函数被多个对象链式调用时,this指向的是最后一个调用它的对象。(就近原则)

var person1 = {
  name: 'Bob',
  greet: function() {
    console.log('Hello, ' + this.name);
  }
};

var person2 = { name: 'Charlie' };

person1.greet.call(person2); // 输出为"Hello, Charlie"

在这个例子中,虽然greet函数本来属于person1对象,但是通过call方法的显示绑定,this指向了person2对象。

显示绑定

为了解决隐式丢失的问题,JavaScript提供了call、apply和bind等方法,用于显式地绑定this的指向。

function foo(x, y){
    console.log(this.a,x + y);
}
var obj = {
    a: 1
}
// foo.call(obj, 4, 5)
foo.apply(obj,[4, 5])
//call是零散接受参数,apply是用数组接受参数
let bar = foo.bind(obj)
bar(4, 5)
//bind方法会返回一个函数体

new绑定

当使用new关键字调用构造函数时,this将指向新创建的实例对象。

function Person(name) {
  this.name = name;
}

var alice = new Person('Alice');
console.log(alice.name); // 输出为"Alice"

在这个例子中,this指向了新创建的实例对象alice,从而成功地给它的name属性赋值。

箭头函数中的this

与普通函数不同,箭头函数没有自己的this绑定,它的this取决于外层普通函数的this。

var obj = {
  foo: function() {
    setTimeout(() => {
      console.log(this);
    }, 100);
  }
};

obj.foo(); // 输出为obj对象,因为箭头函数的this绑定到了foo函数的this

在上述例子中,箭头函数中的this指向了外层的foo函数的this,即obj对象。

总结

理解并正确使用this关键字对于JavaScript开发者来说至关重要。掌握this的各种绑定规则以及箭头函数中的this行为,将有助于避免许多潜在的错误,同时提高代码的可读性和可维护性。希望本文所介绍的内容能够帮助读者更好地理解JavaScript中this的工作原理,并在实际开发中加以运用。