JavaScript中this指向问题
1、this指向window的情况
对于非箭头函数情况下,谁调用就指向谁,如果函数在全局作用域下调用,里面的this就是window。
在全局作用域下,this = window
function sum() {console.log(this); }sum(); // windowconsole.log(this); // window
2、this指向对象的情况
- 当函数在对象中以方法的形式调用,this指向当前对象
function sum() {console.log(this);}let obj = {name : "sb",sum, // 如果Key value名字相同,可以简写add : function() {console.log(this); }}console.log(obj.add()); // thisconsole.log(obj.sum); // this
-
如果对象里面还有对象,里面的对象还有方法,此时这个方法就是指向最近的对象,
如果对象的方法里面,还有函数调用,该函数里面的this指向window对象,因为该函数是window调用,并执行的。
function deletex() {console.log(this);}let obj = {name :"sb",add : function() {console.log(this);},user : {sum : function() {deletex();console.log(this);}}}obj.add(); // obj对象obj.user.sum(); // 第一个window 第二个是user对象
- 通过构造函数,就是通过构造函数new对象时,this指向当前new的实例对象
function Person(name,age) {this.name = name;this.age = age;let say = function() {console.log(`${this.name} ${this.age} = ${this}`);}}let person = new Person('lfj',26);console.log(person.name); // 'lfj';
- 通过class 来构造对象,this指向的就是new出来的对象
class Person {constructor(name,age) {this.name = name;this.age = age;}}let person = new Person('lfj',20);console.log(person.name); // lfjconsole.log(person.age); // 20
3、借助函数的call、apply方法的调用
参数中传入了对象,this就是指传入的对象,参数为空,就是window
call()、apply()都是函数对象的一个方法,它们的作用是改变函数的调用对象,它们的第一个参数就表示改变后的调用这个函数的对象。因此,this指的就是这第一个参数。
function sayHello() {console.log(`hello ${this.name}`);}let obj = {};obj.name = 'Tom';obj.sayHello().apply(); // hello undefined 此时的this就是window
function sayHello() {console.log(`hello ${this.name}`);}let object1 = {};let object2 = {};object1.name = 'Tom';object2.name = 'Jack';object2.sayHello = sayHello;object2.sayHello.apply(object1); // hello Tom
4、借助函数的bind方法
bind方法和apply和call方法作用一样,区别就是不立即执行和立即执行
let object1 = {name : "lfj",say : function() {console.log(this.name);}}let object2 = {name : "wmz",say : function() {console.log(this.name);}}object2.say.bind(object1,object1.say);// bind并不会立即执行object2.say(); //
5、箭头函数中this的指向
箭头函数不会创建自己的this,它只会从自己的作用域链的上一层继承 this
let obj1 = {name : 'lfj',say : () => {console.log(this);}obj2 : {name : 'wz',eat : () => {console.log(this); // obj1}}}obj.say(); // window // 会向上一层作用域链继承this,obj1作用域中的this就是windowobj1.obj2.eat(); // obj1 // 此时继承的this是上一层作用域链的对象,obj1
let obj1 = {name : 'xx',say : function() {setTimeout(()=>{console.log(this); // obj1.},1000);}}