javascript中的this指向

64 阅读2分钟

javaScipt中this的指向是动态的,是在运行时确定的,直接指向函数的调用对象。

全局函数中的this

function Person(name, age) {
    console.log(this); // window
}
Person('Ian', 25);// 等同于window.Person('Ian', 25)

对象中的this

const obj = {
  name: "Ian",
  sayName: function () {
    console.log(this.name);
  },
};

obj.sayName(); // Output: "Ian"

const outerObj = {
  name: "John",
  innerObj: {
    name: "Jane",
    sayName: function () {
      console.log(this.name);
    },
  },
};
outerObj.innerObj.sayName(); // Output: "Jane"

outerObj.innerObj.sayName()的实际调用者是outerObj.innerObj,所以this指向innerObj。

new 运算符中的this

this指向新创建的对象

function Person(name) {
  this.name = name;
  this.sayName = function () {
    console.log(this.name);
  };
}
const person1 = new Person("Ian");
person1.sayName(); // Output: "Ian"

在使用new操作符的时候,会自动创建一个新对象,并将this指向这个新对象。

箭头函数

箭头函数没有自己的this,它的this指向的是它外层作用域的this。

const book = {
  title: "The Great Gatsby",
  author: "F. Scott Fitzgerald",
  getTitle: () => {
    return this.title;
  },
};

console.log(book.getTitle()); // undefined

getTitle()箭头函数的this指向外层作用域的this,即window。 在react中我们也经常使用箭头函数使this指向当前组件的实例, 或者使用bind将this指向组件实例。

class MyComponent extends React.Component {
  constructor(props) {
    super(props);
    this.handleClick2 = this.handleClick2.bind(this);
  }

  handleClick = () => {};

  handleClick2 (){}

  render() {
    return <button onClick={this.handleClick}>Click me</button>;
  }

改变this指向

使用apply()、call()、bind()方法可以改变函数的this指向。

call(thsi, arg1, arg2, ...)方法可以改变函数的this指向为指定的对象,并传入参数。

const operations = {
   num1: 1,
   num2: 2,
   add: function(num3 = 0, num4 = 0) {
     return `result is: ${this.num1 + this.num2 + num3 + num4}`;
   }
};

const obj2 = {
    num1: 3,
    num2: 4,
};

operations.add.call(obj2, 5, 6); // Output: "result is: 18"

bind函数改变this指向并返回一个新的函数,函数的参数可以放到前面也可以放到后面,当参数超过的时候从前往后选取。

operations.add.call(obj2, 5, 6); // Output: "result is: 18"

operations.add.bind(obj2, 5, 6)(); // Output: "result is: 18"

operations.add.bind(obj2, 5)(6,7); // Output: "result is: 18"

apply方法和call用法一致,唯一的区别是call方法接受一个参数列表,而apply方法接受一个参数数组。

operations.add.apply(obj2, [5, 6]); // Output: "result is: 18"