this指向问题研究

294 阅读2分钟

this指向问题

一、this是什么?

  • this是JavaScript中定义的一个关键字,是指向调用该this的对象的,简单来说this 就是你调用 一个函数时,传入的 context(当前调用函数的环境对象),this的指向在函数定义的时候是确定不了的,只有函数执行的时候才能确定this到底指向谁,实际上this的最终指向的是那个调用它的对象
  1. this永远指向一个对象;
  2. this的指向完全取决于函数调用的位置

二、示例

  1. 哪个对象调用方法,this就指向哪个对象
    var o = {
        a:10,
        b:{
            a:12,
            fn:function(){
                console.log(this.a); //12
            }
        }
    }
    o.b.fn(); //fn方法最终是由b调用的,所以当前的this指向b,所以打印的a值为b作用域的值
    
  2. 直接调用的函数,this 指向的是全局 window 对象
    function a(){
        var user = "abc";
        console.log(this.user); //undefined
        console.log(this); //Window
    }
    a();  //等价于 window.a(), 所以this指向的是window
    
  3. 构造函数的this
    function Fn(){
        this.user = "111";
    }
    var a = new Fn();
    console.log(a.user); //构造函数里this指向的是指向生成的对象实例,所以打印结果为111 
    
  4. 其他场景
    //严格模式的this
    function demo() {
    	'use strict';
    	alert(this); // undefined
    }
    demo();//严格模式下 this指向undefined
    
    //定时器中的this
    setTimeout(function() {
    	alert(this); // this -> 指向window
    },500)
    

四、如何改变this指向

  1. 箭头函数
  • 不管在什么情况下,箭头函数的this跟外层function的this一致,外层function的this指向谁,箭头函数的this就指向谁,如果外层不是function则指向window
    //这里是外部作用域 this指向window,即最终console中的this指向window
    let person1 = {
        name:'lisi',
        age:10,
        say:()=>{
            //这里是外部作用域,因为本身又是箭头函数,继续向上找
            setTimeout(() => {
                console.log(this);  //this指向外部作用域中this
            });
        }
    }
    person1.say();   //输出window
    let obj1 = {
    	name:'111',
    	foo: function() {
    		setTimeout(()=>{
    		  console.log(this);  // obj2
    		}, 1000);
    	},
    }
    obj1.foo();// obj1
    
  1. call 修改this指向

    function a(){
    	console.log('name:'+this.name) // name:obj1
    	console.log(arguments)
    }
    var obj1 = {
      name:'obj1'
    }
    a.call(obj1,1,2,3)  //this指向为obj1对象
    
  2. apply修改this指向

    function b(){
    	console.log('name:'+this.name) // name:obj2
    	console.log(arguments)
    }
    var obj2 = {
      name:'obj2'
    }
    b.apply(obj2,[1,2,3])  //this指向为obj2对象
    
  3. bind修改this指向

    function c(){
    	console.log('name:'+this.name) // name:obj3
    	console.log(arguments)
    }
    var obj3 = {
      name:'obj3'
    }
    c.bind(obj3,[1,2,3])()  //this指向为obj3对象
    

    call 、bind 、 apply 区别: 这三个函数的第一个参数都是 this 的指向对象,第二个参数差别为call 的参数是直接放进去的,第二第三第 n 个参数全都用逗号分隔,直接放到后面 fun.call(this,'1','2','3' )。 apply 的所有参数都必须放在一个数组里面传进去 fun.apply(this,[1,2,3])。 bind 除了返回是函数以外fun.apply(this,[1,2,3])(),它 的参数和 call 一样。