题目练习:
题目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是十分动态的
- 这里要注意了,虽然是在全局范围调用girl对象的special方法,但这里还是会用隐式绑定的规则,因为this指向实际调用该方法的对象,也就是gril对象调用的该方法,即使函数在全局里面声明还是不影响的,因此
题目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,这里的t
this.name
就应该是huang, - 但是,这里的对象b的detail方法赋值给了c,这里的变量c才是真正的调用者,这里可以把对象b的detail方法看做是一个普通的函数,赋值给了变量c,就相当于函数表达式了,这个函数产生了一个动作,这个动作给了变量c用了而已,已经和对象b没有什么关系了,然后变量c执行了这个动作,此时这个c就是一个函数,而且在全局范围内定义的函数,和函数a一样,指向window对象的name属性,也就是zhousjuan
- 这里的函数c实际上是一个变量名,这个函数c是由函数b的detail方法给赋值的,这里的this发生了隐式绑定,指向调用他的变量对象b,这里的t
-
执行
b.a()
==》对象b的a方法- 我们可以看到b里面根本就没有a方法,但是我们往下看,就可以看到
b.a=a
- 这一行实际上就是给我们的对象b定义了一个a属性,然后用a来进行赋值,
- 我们通观全局,就可以看到我们的前面已经声明了函数a,因此这里实际上是给对象b定义了一个方法a
- 即使用的是全局定义函数,这个函数就好比一个动作一样,这个动作被用在对象b里面,因此这里的this就是指向调用他的b,所以是huang
- 我们可以看到b里面根本就没有a方法,但是我们往下看,就可以看到
-
执行
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
-