this指向问题总结(JavaScript )

 this指向

 

目录

01-全局环境—顶层对象window

02-构造函数—实例对象

03-对象的方法—方法运行时所在的对象

04-注意

05-call(),apply(),bind() 方法

06-箭头函数的this指向问题


  • this总是返回一个对象,它就是属性和方法当前所在的对象

  • 实质:与内存的数据结构有关,引擎会将函数单独保存到内存中,然后再将内存地址赋值给相应的变量,函数是一个单独的值,它可以在不同的环境(上下文)中执行。this的出现就是为了让它获得当前的环境

01-全局环境—顶层对象window

  • this === window // true
    ​
    function f() {
      console.log(this === window);
    }
    f() // true
    ​
    //只要在全局环境中运行,都是指向window对象

02-构造函数—实例对象

  • var Obj = function (p) {
                this.p = p
            }
           
            var o = new Obj('hi yucuiwen')
            console.log(o.p);  // hi yucuiwen
    ​
    // 在构造函数中,指向的是当前的实例对象

03-对象的方法—方法运行时所在的对象

  • 对象可以看做是存放在地址一,对象的方法可以看作是存放在地址二。从地址一去查询地址二,那么它的运行环境就是地址一,但是如果脱离地址一,直接去访问地址二,那么它的运行环境就会改变,this指向也会改变。

    var obj ={
      foo: function () {
        console.log(this);
      }
    };
    ​
    obj.foo() // obj
    ​
    // 情况一
    (obj.foo = obj.foo)() // window
    // 情况二
    (false || obj.foo)() // window
    // 情况三
    (1, obj.foo)() // window
    ​
    ​
    +++++++++++++++++++++++++++++++++++++++
    // 情况一
    (obj.foo = function () {
      console.log(this);
    })()
    // 等同于
    (function () {
      console.log(this);
    })()
    ​
    // 情况二
    (false || function () {
      console.log(this);
    })()
    ​
    // 情况三
    (1, function () {
      console.log(this);
    })()

  • 如果this所在的方法不在对象的第一层,那么this只会指向当前一层的对象,而不会指向更上面一层的对象

    var a = {
      p: 'Hello',
      b: {
        m: function() {
          console.log(this.p);
        }
      }
    };
    ​
    a.b.m() // undefined

    04-注意

    • 避免多层this,借助中间变量 that 固定this指向

    var o = {
                f1:function() {
                    console.log(this);
                   // let that =  this
    //因为这里它相当于在函数内部f1()方法下面又定义的方法 不会指向更上面一层的o,所以是window
    //解决方法:用that固定
                    var f2 = function() {
                        console.log(this);
                        //console.log(that)
                    }
                }
            }
            o.f1()   //object  // window

  • 避免数组处理方法中的this

       var o = {
                v:'hello',
                p:[11,2 ],
                f:function fn() {
                    this.p.forEach(function(item){
                        console.log(this.v+' '+item);
                    })
                }
            }
            o.f()
            // undefined 11
            // undefined 2
    // 由于数组处理方法中的参数也是函数,所以类似于多层嵌套

  • 避免回调函数中的this,因为回调函数中的this往往会改变指向

    var o = new Object();
    o.f = function () {
      console.log(this === o);
    }
    ​
    // jQuery 的写法
    $('#button').on('click', o.f);
    // false

05-call(),apply(),bind() 方法

  • 函数/方法 call/apply/bind(对象)

  • call()方法,接收的第一个参数一定是一个对象,如果是null,undefined或者空,那么则默认是window对象;如果是原始值,那么则转为其对应的object实例化对象

    • 它的主要作用是改变运行时的object指向

       var f = function () {return this;};
       console.log(f.call(5));
       function add(a,b) {
           return a+b
       }
       console.log(add.call(this,3,4));
    • 后面跟着的参数是函数的形参

    • 应用之一:调用对象的原生方法(*)

    var obj = {};
    obj.hasOwnProperty('toString') // false
    ​// 覆盖掉继承的 hasOwnProperty 方法
    obj.hasOwnProperty = function () {
      return true;
    };
    obj.hasOwnProperty('toString') // true
    ​
    Object.prototype.hasOwnProperty.call(obj, 'toString') // false
     
      
    • apply()方法,主要特点是以数组的形式传递参数

      • 应用1:数组取最大值,与数学方法联系起来 将数学上取最大值的方法运用到了数组身上  

         var a = [12,354,545,45]
            console.log(Math.max.apply(null,a));

      • 应用二:将数组中的空对象设置为undefined,以便于forEach可以遍历的到

        console.log(Array.apply(null,['a',,'b']));

      • 应用三:将类数组转化为真正的数组,但是类数组必须有length属性,要不然默认length:0

            [].slice.apply({0:1,length:1}),
         // 这种写法 是先new一个实例 然后调用原型对象上的slice方法
         // this指向是 创建的实例对象
            Array.prototype.slice.apply({0:1}),
            Array.prototype.slice.apply({0:1,length:2}),
            Array.prototype.slice.apply({length:1})
        // 这些写法 this指向都是 Array.prototype实例对象
        // 当然可以改变它们的指向
  • bind() 方法类似

    // 数组方法的实质
    

06-箭头函数的this指向问题

  • 箭头函数中 指向的是定义箭头函数的上下文

  • 它并不是没有this指向,只不过它的指向在定义时就已经确认了

    window.color = 'red'
    let o = {
        color:'blue'
    }
    let sayColor = () => {console.log(this.color);}
    sayColor()  //red
    o.sayColor = sayColor 
    o.sayColor()  //red
    对于解决异步问题十分有效
    var royalName = 'yucuiwen'
    function King() {
        this.royalName = 'Henry'
        setTimeout(() => {console.log(this.royalName)},1000)
        // setTimeout(function() {
        //     console.log(this.royalName);
        // },1000)    // yucuiwen
    }
    function Queen() {
        this.royalName = 'Elizabeth'
        setTimeout(() => {console.log(this.royalName)},1000)
    }
    new King()  //'Henry'
    new Queen()  //'Elizabeth'

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值