一张图放在前面
默认绑定
独立函数调用时遵循默认绑定的原则。一般情况下若无其他规则出现则默认将this绑定到全局对象上。1
2
3
4
5
6function foo(){
	var a = 3;
	console.log(this.a)
}
var a = 2;
foo()	// 2
隐式绑定
若调用位置有上下文对象就遵循隐式绑定(如example.foo())1
2
3
4
5
6
7
8function foo(){
	console.log(this.a)
}
var obj = {a:2,  foo:foo}
var a = 'global'
obj.foo()		// 2
var bar = obj.foo
bar()		// 'global
如图。之前我们直接调用foo函数时因为其具有上下文对象,所以正确打印,this此时正指向此对象(obj)。
可是之后的bar为什么又无法正确打印出对应的结果呢?
首先我们看,题目中用一个变量bar存储了obj.foo。所以为完成此赋值操作引擎会对obj.foo进行RHS查找,并找出其对应的键foo。继而再对值foo进行RHS查找,得到foo函数。
可是此时对其进行调用时,由于无上下文对象(bar本身的调用并不是靠”.“出来的)所以就造成了隐式丢失。故采取默认绑定规则,绑定在全局的a上。
或者我们换一种说法:bar引用的时foo函数本身。因而此时的bar其实是一个不带任何修饰的函数调用,自然采取默认绑定规则。
Ps:隐式丢失后会默认绑定在window上
1  | var a = "global";  | 
这题怎么解决
上面我们讲到了,隐式绑定的规则说通俗一点就是必须用”.“操作符将其函数与相应对象绑定。所以我们改成这样就可以啦1
2
3
4
5
6
7
8function foo(){
	console.log(this.a)
}
var obj = {a:2,  foo:foo}
var a = 'global'
obj.foo()		// 2
var bar = obj
bar.foo()		    // 2
此例中前半部分都一样。一直进行RHS查找,直到将obj的调用地址赋给bar。也就是说bar此时具有了一个obj的引用。在此后通过.操作符操作时就不会再发生上面所说的隐式丢失了.
原理
对象属性引用链只有上一层或者说最后一层再调用位置中起作用
参数传递所引起的隐式丢失
1  | function foo(){  | 
我们分析一下。作为参数传递进dooFoo的obj.foo,引擎会对其进行RHS搜索。不信我们删掉foo看一下
喏,这个ReferenceError的报错就能充分说明问题了。
不成功的
RHS引用会导致抛出ReferenceError异常。不成功的
LHS引用会导致自动隐式地创建一个全局变量(非严格模式下)。该变量使用LHS引用的目标作为标识符,或者抛 出ReferenceError异常(严格模式下)。
既然是RHS那么我们会得到一个foo函数的引用。但是此引用是脱离了上下文的,自然会发生隐式丢失。
JavaScript的内置库函数也一样,所以少用这种传入参数的方式,容易造成隐式丢失
显式绑定
隐式绑定这种由JavaScript内部机制造成的宫斗剧一般的勾心斗角显然不适合我这种单纯的boy。而正好有另一种绑定方式,简单粗暴易懂,让人一眼看出this作用域。
apply、call
在用此方法之前我建议好兄弟们去看一下这俩函数的相关内容1
2
3
4
5function foo(){
	console,log(a)
}
var obj = {a: 2}
foo.call(obj)	// 2
但是显式绑定仍然无法解决丢失绑定问题
硬绑定
创建一个可以重复使用的辅助函数
1  | function foo(something){  | 
如图,我们每次在bind函数上将传入的函数硬性绑定在其对象上,如此一来无论如何调用bar,都会手动在obj上调用fn
Function.prototype.bind
1  | function foo(something){  | 
bind()会返回一个硬编码的新函数,它会把你指定的参数设置为this的上下文并调用原始函数
API调用参数指定this
一些函数会提供一个可选参数作为你的“上下文”,以达到确保回调函数使用指定this的目的1
2
3
4
5function foo(el){
	console.log(el, this.id)
}
var obj = {id:'awesome'}
[1, 2, 3].forEach(foo, obj)
new绑定
写在前面
JavaScript中没有构造函数,只有对函数的构造调用
发生函数的构造调用时,自动执行以下操作
- 创建一个全新的对象
 - 此对象会被执行
 [[prototype]]链接- 此新对象会绑定到函数调用的
 this- 执行此函数代码
 - 若函数无返回值,则自动返回这个新对象
 
 1
2
3
4
5
6 function fun(){
this.a = 1
this.b = 2
}
var instance = new fun()
console.log(instance.a)
箭头函数
箭头函数的this指向就可以理解为传统面向对象语言的this啦。它会根据外层的作用域来决定this,即取决于外层的函数作用域或全局作用域,且箭头函数的绑定无法修改
今天的总结就到这里啦