JavaScript中的this指向问题

69 阅读2分钟

一、this指向

1、this默认指向window

console.log(this) // window

2、当函数作为对象属性时,this指向调用的对象

const a = { name: 'aaa', func: function() { console.log(this.name) } }
a.func() // aaa

3、箭头函数是特例,this继承自父级

const a = { name: 'aaa', func: () => { console.log(this.name) } }
a.func() // undefined

4、构造函数的this,指向new 新创建的对象

function Person(name) {
    this.name = name;
}
const a = new Person('aaa');
console.log(a.name) // aaa

5、类的this,指向引用类的实例

class Person {
    constructor(name) {
        this.name = name;
    }
    logName() { console.log(this.name) }
}
const a = new Person('aaa');
a.logName() // aaa

二、改变this指向

  • call、apply 和 bind 是 Function 对象自带的三个方法,作用是改变函数中的 this 指向

1、call(thisArgs, param1, param2, ...)

  • thisArgs 指定了函数在运行期的调用者,也就是函数中的 this 对象,取值有以下四种情况:
    1. 不传,或者传null,undefined, 函数中的 this 指向 window 对象
    2. 传递另一个函数的函数名,函数中的 this 指向这个函数的引用
    3. 传递字符串、数值或布尔类型等基础类型,函数中的 this 指向其对应的包装对象,如 String、Number、Boolean
    4. 传递一个对象,函数中的 this 指向这个对象
const a = {
    name: 'aaa',
    logName: function() {
        console.log('logName:', this.name);
    }
};
function b(name) {
    console.log('name:', name);
    console.log('this.name:', this.name);
    this.logName();
}
b('bbb');         // name: bbb
                  // this.name: undefined
                  // logName: this.logName is not a function
b.call(a, 'bbb'); // name: bbb
                  // this.name: aaa
                  // logName: aaa

2、apply(thisArgs [param1, param2, ...])

  • apply 和 call 的唯一区别是第二个参数的传递方式不同,apply 的第二个参数必须是一个数组(或者类数组),但在传递给调用函数时,却是以参数列表的形式传递
function b(x,y,z){
    console.log(x,y,z);
}
b.apply(null,[1,2,3]); // 1 2 3

3、bind(thisArgs, param1, param2, ...)

  • bind 不会执行对应的函数,只是返回了对函数的引用
  • 当对一个函数调用多次bind的时候,最终起作用的是第一个bind
const a = { name: 'aaa' };
document.addEventListener('click', onClick.bind(a,'bbb'), false);
function onClick(name) {
    console.log('name:', name);             // bbb
    console.log('this.name:', this.name);   // aaa
}

4、场景应用

  • 继承
function Animal(name,weight){
    this.name = name;
    this.weight = weight;
}
function Cat(){
    Animal.call(this,'cat','50');
    //Animal.apply(this,['cat','50']);
    this.say = function(){
        console.log("I am " + this.name+",my weight is " + this.weight);
    }
}
const cat = new Cat();
cat.say(); // I am cat,my weight is 50
  • 借用方法
// Math.max(p1,p2,...) 方法返回参数中的最大值。
const arr = [2,3,1,5,4];
Math.max.apply(null,arr); // 5;通过apply方法将数组转换为参数列表传递给Math.max