this指向问题

64 阅读3分钟

this指向

  1. 全局作用域中或者普通函数中this指向全局对象window
  2. 立即执行函数this必定指向window
  3. 定时器this指向window
  4. 事件中this指向事件源对象
  5. 方法中谁调用就指向谁(谁调用,就指向谁)
  6. 构造函数中this指向对象实例

this绑定规则

默认绑定规则

  1. 默认绑定全局对象window
console.log(this === window);   //true
// Window对象
  1. 全局作用域下独立调用函数,this指向window
    function get() {
        console.log(this === window) // true
    }

    get()

隐式绑定规则

    var person = {
        name: '张三',
        run: function(time) {
            console.log(`${this.name}跑了,${time}分钟`);
        }
    };

    // 对象调用
    person.run(30)
    person.run.call(person, 30)
    // 张三跑了,30分钟
    var name = 222;
    var a = {
        name: 111,
        say: function () {
            console.log(this.name);
        }
    }

    var fun = a.say;
    fun();  // fun拿到a.say的引用,然后在全局下独立调用:222

    a.say(); // 111

    var b = {
        name: 333,
        say: function(fun) {
            fun()
        }
    }

    b.say(fun) // window调用:222
    b.say = a.say;
    b.say() // 333

记住:父函数有能力决定子函数this的指向,例如forEach里第一个参数是一个函数,第二个参数就是this绑定的对象,不写默认绑定window

显式绑定

call、apply、bind bind返回一个新函数,新函数指向绑定的对象,旧函数不会

call、apply和bind call、apply、bind方法的共同点: call:xxx.call(thisArg, arg1, arg2, ...) apply:xxx.apply(thisArg, argsArray) bind:xxx.call(thisArg, arg1, arg2, ...) call、apply和bind区别:call、apply是先执行,bind是后执行(绑定后需要再次执行)

new绑定

this指向函数实例化之后的对象

绑定规则优先级

new绑定 > 显式绑定 > 隐式绑定 > 默认绑定

箭头函数this指向问题

箭头函数没有自己的this指向,它的this指向上一级作用域的this(最外层代码块) 之前,我们想让内部函数的this指向外部函数的this,我们只能这样:

    var a = 0;
    function foo() {
        let that = this; //指向obj
        console.log(this);
        function test() {
          console.log(that); //指向obj
        }
        test();
    }
    let obj = {
        a: 1,
        foo: foo,
    };
    obj.foo();

或者使用bind/call/apply显式绑定外部函数的this:

    var a = 0;
    function foo() {
        console.log(this); //指向obj
        function test() {
          console.log(this);
        }
        test.call(obj);
    }
    let obj = {
        a: 1,
        foo: foo,
    };
    obj.foo();

箭头函数this指向不遵循上述的四种规则 独立调用对箭头函数无效

    var a = 0;
    function foo() {
        let test = () => {
        console.log(this);
    };
        return test;
    }
    let obj = {a: 1, foo: foo};
    obj.foo()();
    //  obj.foo()返回test  obj.foo()()调用test  而且是独立调用  但是this还是指向obj

隐式绑定对箭头函数无效:

    let a = 0;
    let obj1 = {
        a: 1,
        foo: () => {
          console.log(this);
        },
    };
    obj1.foo(); //指向window

显式绑定对箭头函数无效:

    var a = 0;
    function foo() {
        let test = () => {
          console.log(this);
        };
        return test;
    }
    let obj1 = {
        a: 1,
        foo: foo,
    };
    let obj2 = {
        a: 2,
        foo: foo,
    };
    obj1.foo().call(obj2);

     //obj1.foo()返回test  obj1.foo.call(obj2)把test的指向绑定到obj2上,无效,this依然指向obj1
     
     /**
         * obj1.foo().call(obj2)
         * 第一步:obj1.foo()返回test,这时foo()的this指向obj1(普通函数的隐式绑定)
         * 
         * 第二步:test.call(obj2),箭头函数的显式绑定无效,所以箭头函数中的this需要在定义的地方向上层作用域中查找,
         * 就找到foo的作用域,即第一步中this的指向obj1
         * */

引用this指向/箭头函数this指向详解

    var name = 'name';
    var a = {
        name: 111,
        b: {
            name: 222,
            say: () => {
                console.log(this.name)
            }
        }
    }
    a.b.say() // name

    class A {
        name = 111;
        say = () => {
            console.log(this.name);
        }
    }
    var b = new A()
    b.say(); // 111
    var name = 'name';
    var a = {
        name: 111,
        say: function(){
            console.log(this.name) // say于name平级, 111
            let fn = () => {
                console.log(this.name)
            };
            return fn(); // 111, this指向a
        }
    }
    a.say()