js中的this指向

this指向问题

在我们研究this指向问题的时候,我们只需要知道判断this时,那个对象调用它,它就指向谁;否则就指向全局对象window,牢记这一点,我们就能很好的解决this指向问题。

1.普通函数调用

当普通函数调用时,this没啥特殊意外,就是指向全局对象window。

        let name = "Mick";
        function f(){
            console.log(this); //window
            console.log(this.name); // 'undefine' 相当于window.name
        }
        f();

上面代码中,因为函数f,没有人调用它所以f就会指向全局对象window,可能你会疑惑为什么this.name不会输出Mick,但是你仔细看一下,name定义的方式时let,不属于window对象,所以。(在这里我们需要注意一下,在es6中,新规定var,function声明的全局变量,仍然属于顶级对象的属性;使用let,const,class声明的全局变量不再属于顶层对象的属性

2.对象函数调用

这个我们只需记住一点,谁调用它,this就指向谁

        var name = 'window'
        let obj1 = {
            name: 'obj',
            sayHi: function()  {
                console.log(this.name)
            },
            sayFoo: function () {
                return function(){
                    console.log(this.name)
                }
            }
        }
        obj1.sayHi(); //"obj"
        obj1.sayFoo()(); //"window"
        let f = obj1.sayHi;
        f(); //"window"

上面代码中,obj1.sayHi()的输出结果,想必我们都能理解,但是f()和obj1.sayFoo()()的输出结果,可能大家就会感到很疑惑了把,为什么都是window呢,而不是obj呢,这里我们就得想起那句很重要的话了,谁调用它,this就指向谁,否则就指向window。当我们把这句话理解了,那上面的输出结果我们就会很好理解了。

在obj1.sayFoo()()这个语句中,我们可以看到,obj1调用了sayFoo()这个函数,那么为什么不输出obj呢?这里我们就得知道,sayFoo()的确是指向obj1这个对象的,但是sayFoo()这个函数会返回一个匿名函数,所以obj1.sayFoo()()这个语句就等价于了一个匿名函数f(),但是这个函数没有人调用它,所以说这里的this.name才会是window。

那么f()就和上面是一样的道理,在上述语句中,我们是将obj1.sayHi这个函数的表达式,赋值给了f,此时的f就相当于是一个新的函数,其值为function() { console.log(this.name) },当我们执行函数f的时候,会发现没有人调用它,所以它的this指向就会指向全局window,看到这里我想对象调用这个就不会难到大家了把。

3.箭头函数调用

这个我们就得注意了,箭头函数比较特殊,它是没有this指向的。箭头函数的this指向是继承外面的环境的,我们在研究它的this指向的时候,需要取往他的父级找,箭头函数的this指向它的父级的指向。

        var name = 'window'
        let obj1 = {
            Ithis:this,
            name: 'obj',
            sayHi: ()=>  {
                console.log(this.name)
            },
            sayFoo:  ()=> {
                return ()=>{
                    console.log(this.name)
                }
            },
            sayHello: function(){
                return ()=>{
                    console.log(this.name);
                }
            }
        }
        console.log(obj1.Ithis); //window对象
        obj1.sayHi(); //"window"
        obj1.sayFoo()();//"window"
        obj1.sayHello()();//"obj"

上述代码中,obj1.sayHi()执行时,sayHi指向了obj1但是由于sayHI是一个箭头函数,所以它的this指向就是obj1的this指向,但是obj1的this是window对象,所以说会输出window。

对于obj1.sayFoo()()这个语句,首先sayFoo函数返回一个匿名的箭头函数,该匿名箭头函数this指向的就是sayFoo函数的this,而sayFoo也是一个箭头函数,所以它的this指向window,所以返回的匿名的箭头函数this指向window

obj1.sayHello()(),首先sayHello会返回一个匿名箭头函数,该函数指向的是sayHello的this,而sayHello函数是一个普通函数,并且obj1调用了它,所以会输出obj。

4. call、apply、bind

call、apply、bind可以改变函数内部的this指向,但由于箭头函数自身没有this,所以call、apply、bind对箭头函数是不起作用的

var name = 'window'
let obj3 = {
  name: 'obj',
  sayHi: () => {
    console.log(this.name)
  },
  sayFoo: function () {
    console.log(this.name)
  }
}
let obj4 = {
  name: 'other'
}
obj3.sayHi.call(obj4) // window,call对箭头函数不起作用
obj3.sayFoo.call(obj4) // other,call可以改变函数内部的this到指定变量

关于this指向的问题,我就谈就到这里,希望对大家有所帮助。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值