#前端面试题#js-this指向问题

题目练习:

题目1:

function a(){
	function b(){
        console.log(this)
        function c(){
            "use strict"
            console.log(this)
        }
        c()
    }
    b()
}
a()

分析:这里有三个函数,这三个函数一个内嵌着一个,

  • 先从全局来看,哪里执行了函数,可以看到我们最下面的a()执行了,那么我们到函数a,里面进行查看
  • 函数a里面有一个函数b的声明和函数b的执行
  • 然后,我们进入函数b里面,函数b里面输出this,这里的this并没有明确指明调用的对象,因此会使用默认绑定,也就是window全局对象
  • 我们往下看,这里有函数c的声明和函数c的执行,但是这里注明了严格模式,严格模式回比较特殊,输出的this值回变成undefined
  • 因此,最后window和undefined会被输出显示出来
  • 这道题考察大家的是默认绑定的概念

题目2:

var name='zhousujuan'

function special(){
    console.log('name:'+this.name)
}

var girl={
    name:'hong',
    detail:function(){
        console.log('name:'+this.name);
    },
    woman:{
        name:'zhou',
        detail:function(){
            console.log('name:'+this.name)
        },
    },
    special:special,
}

girl.detail()
girl.woman.detail()
girl.special()

分析:

  • 首先顶部声明了变量name,并且赋值
  • 还有声明的函数special
  • 声明并且给girl这个变量赋值,
  • 这里开始执行gril.detail(),这是要执行girl下面的detail方法,当对象方法被调用的时候会发生隐式绑定,this指向调用改方法的对象,也就是girl对象,而girl对象里面有一个name属性是hong,所以这里的this.name就是hong,所以说这里的输出就是hong
  • 继续看看,下面要执行的函数girl.woman.detail(),这是要执行gril对象下面的women对象的detail方法,
    • 这里虽然是对象里面的里面,但并不影响我们的分析,this依旧指向调用该方法的对象
    • 实际上调用该方法的是woman对象的detail方法,而不是girl对象的detail方法,所以这里就是zhou
  • 这里开始执行girl.special(),这是要执行girl的specila方法,我们看看这个special这个属性,后面还有special值,这后面的special是一个函数,因为我们要执行的是对象的方法,因此我们看到最开始的时候,我们有一个special()函数已经声明了,因此在这里special将会执行最开始声明的函数
    • 这里要注意了,虽然是在全局范围调用girl对象的special方法,但这里还是会用隐式绑定的规则,因为this指向实际调用该方法的对象,也就是gril对象调用的该方法,即使函数在全局里面声明还是不影响的,因此gril.special()会输出,girl对象里面的属性hong
    • 这里的specila属性,只是借用了这个special函数来完成一次输出而已,因此实际上this是十分动态的

题目3:

var name='zhousujuan'
function a(){
    var name='baibai'
    console.log(this.name)
}
function d(i){
    return i();
}

var b={
    name:'huang',
    detail:function(){
       console.log(this.name)
    },
    bibi:function(){
        return function(){
            console.log(this.name)
        };
    },
}

var c=b.detail
b.a=a
var e=b.bibi()
a()
c()
b.a()
d(b.detail)
e()

分析:

  • 首先顶部声明了一个变量name,并赋值

  • 随后声明函数a,d

  • 声明变量b,并赋值

  • 我们查看代码,看看哪里先执行调用,找到a(),那我们到函数a

    • 虽然我们可以看到函数a里面有局部变量name,这里和全局的name是同名的
    • 但是我们是在全的范围内调用a的,这里就会发生默认绑定,默认绑定会指向window
    • 这里有一个小知识点:如果在全局范围内定义变量,那么这个变量也是属于window的,也就是说我们这里的zhousujuan是属于window的,既然window里面有这个name属性,那么函数a就会就会精确的指向window里面的name属性
  • 接下来是调用函数c,找到函数c,===》var c=b.detail

    • 这里的函数c实际上是一个变量名,这个函数c是由函数b的detail方法给赋值的,这里的this发生了隐式绑定,指向调用他的变量对象b,这里的tthis.name就应该是huang,
    • 但是,这里的对象b的detail方法赋值给了c,这里的变量c才是真正的调用者,这里可以把对象b的detail方法看做是一个普通的函数,赋值给了变量c,就相当于函数表达式了,这个函数产生了一个动作,这个动作给了变量c用了而已,已经和对象b没有什么关系了,然后变量c执行了这个动作,此时这个c就是一个函数,而且在全局范围内定义的函数,和函数a一样,指向window对象的name属性,也就是zhousjuan
  • 执行b.a()==》对象b的a方法

    • 我们可以看到b里面根本就没有a方法,但是我们往下看,就可以看到b.a=a
    • 这一行实际上就是给我们的对象b定义了一个a属性,然后用a来进行赋值,
    • 我们通观全局,就可以看到我们的前面已经声明了函数a,因此这里实际上是给对象b定义了一个方法a
    • 即使用的是全局定义函数,这个函数就好比一个动作一样,这个动作被用在对象b里面,因此这里的this就是指向调用他的b,所以是huang
  • 执行d(b.detail)==》我们可以看见这个函数d已经在全局声明了,函数d有一个形参i,函数里面直接执行这个形参i,可以看出这里的形参i是一个函数

    • 然后函数d实际接收了函数b的detail方法,虽然啊看着this好像是要指向对象d,但是实际上b的detail方法相当于一个值被用在函数d里面,而实际执行的是全局范围的函数d,因此这里也是指向window里面的name属性,也是zhousujuan
  • 执行e()》找到上面变量e==》var e=b.bibi()

    • 这里的函数e实际上是一个变量名,这个函数e是由函数b的bibi方法给赋值并且执行的,

    • 看看bibi()这个方法里面有什么,发现是一个闭包

      • b.bibi
      f(){
          return function(){
              console.log(this.name)
          };
      
      }
      
      • b.bibi()
      f(){
      	console.log(this.name)
      }
      

      实际上是把这个函数赋值给了变量e,那么现在这个e就是一个函数了,只不过这个函数接受了b.bibi执行的这个动作而已,不管这个bibi在那个对象里面,现在只是复制了bibi方法所执行的输出,而实际调用的是全局范围内的这个函数e,因此输出还是zhousujuan

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值