JavaScript中this的绑定规则主要分为4种,在上篇中我们主要讲解这个,在下篇中我会写些其他的内容,如有纰漏欢迎指出。
1.默认绑定
function foo(){ console.log(this.a) }
var a = 'global'
foo() // global
注意:由于strict mode下这种调用风格this是undefined 所以会报错
2.隐式绑定
function foo(){ console.log(this.a) }
var o = {
a: 1,
foo: foo
}
o.foo() //1
这种绑定有隐式绑定丢失问题
var bar = o.foo()
var a = 'global'
bar() //global'
原因是bar直接指向了foo函数,所以这样调用其实适用于默认绑定规则
同理回调
function doFoo(fn){
fn()
}
doFoo(o1.foo)
doFoo() //global
其实参数fn就是一个变量
同理setTimeout等就是这种情况
还有一种对象连续调用的,看最近的一个
var o1 = {
a:'o1',
foo:foo
}
var o2 = {
a: 'o2',
o1: o1,
foo:foo
}
o1.foo() //o1
o2.foo() //o2
var a = 'global'
o2.o1.foo() //o1
var bar = o1.foo
bar() //o1
3.显示绑定
就是利用call和apply
这里有两个小知识点
(1)当call和apply第一个参数传进去的是数字,字符串,boolean等基础数据类型里面的this会变成相应的包装类,new Number() , new String() 等
(2)硬绑定:
function bind(fn, obj) {
return function (){
fn.apply(obj, argument)
}
}
var newFn = fn.bind(o)
forEach也可以执行回调函数的this指向
function showId(num){
console.log(this.id + num)
}
var ids =
[1,2,3].forEach(showId, ids)
4.new绑定
对于函数的构造调用
会执行下面四个步骤
(1)创建一个全新的对象
(2)这个新对象会被执行原形连接
(3)这个新对象会绑定到函数调用的this
(4)如果函数没有返回其他对象,那么new表达式中的函数调用会自动返回这个新对象
优先级
先说结论:(1)默认优先级最低(2)显式绑定的优先级高于隐式绑定 (3)new优先级比隐式绑定高(4)显示绑定优先级高于new
对应的印证代码:
(1)略
(2)
function foo(){
console.log(this.a)
}
var o = {
a:1,
foo:foo
}
o.foo.call() //2
(3)
function foo(num){
this.a = num
}
var o1 = {
foo:foo
}
var o2 = {
}
o1.foo(2)
console.log(o1.a) //2
o1.foo.call(o2,3)
console.log(o2.a)//3
var bar = new o1.foo(4)
console.log(o1.a)//2
console.log(bar.a)//4
(4)
function foo(num){
this.a = num
}
var o = {}
var bar = foo.bind(o)
bar(2)
var o1 = new bar(3)
console.log(o.a)//2
console.log(o1.a)//3
被忽略的this
我们常常会把null和undefined传入call、apply或者bind,这样实际使用的是默认绑定
function foo(num){
this.a = num
}
var a = 2
foo.call(null,3)
console.log(a)//3
这样做可能导致修改全局变量,而且bug相对隐蔽,所以谨慎使用
---参考资料《你不知道的JavaScript》
领取专属 10元无门槛券
私享最新 技术干货