上一章我们讨论过this对象四种绑定规则,这次我们来讨论下关于四种绑定规则之间的优先级顺序
首先,默认绑定肯定是优先级最低的
那么隐式和显式之间谁的优先级更高呢?
function fun() {
console.log(this.name);
}
var obj1 = {
name: "隐式",
fun: fun
}
var obj2 = {
name: "显式"
}
obj1.fun.call(obj2); //显式
由上面的例子可以得出 优先级顺序中显式是大于隐式的
接下来要比较的是隐式和new的优先级
function fun() {
console.log(this.name);
}
var obj1 = {
name: "隐式",
fun: fun
}
var obj2 = new obj1.fun(); //undefined
从上面的例子可以看出,obj1.fun()中的this指向的是由new新建的对象而不是obj1
因此优先级顺序中 new大于隐式
接下来要比较的是new和显式,但是由于new函数无法跟apply或call一起使用,所以我们需要借助一下硬绑定
function fun() {
console.log(this.name);
}
var obj1 = {
name: "显式"
}
var bar = fun.bind(obj1);
var obj2 = new bar(); //undefined
因此优先级顺序为new大于显式
(事实上new修改this时会判断硬绑定函数是否被new调用,如果是的话就会使用新创建的this替换硬绑定的this)
因此结果是
优先级顺序: new > 显式 > 隐式 >默认
然而有些情况可能会与预想的有偏差
1.当显式绑定的对象为 null 或者undefined时,这些对象会被忽略,实际应用的是默认规则
当需要对一个接受多个参数的函数转换为一个接受单一参数的函数时,会出现这种情况
如 fun(a,b,v){..} 转化为 fun.apply(null,[a,b,c])
在ES6中可以用...来代替apply(...)进行转化
如fun(...[1,2])等同于fun(1,2)
但是需要进行柯里化(预先设置一些参数)时还是会需要bind()
如var foo=fun.bind(null,1) , foo(2,3,)等同于 fun(1,2,3)
但是这么做会带来一些不可预计的后果(比如修改全局变量)
因此一种更安全的做法是传入一个特殊的DMZ对象(demilitarized zone, 非军事区) ø(option+o,表示空集)
用法:Object.create(null)和{}很像,但是并不会创建Object.prototype这个委托,所以比{}更空
var ø = Object.create(null);
foo.apply(ø,[1,2,3]);
2.间接引用
简单地说,就是类似于 (obj1.foo=obj2.foo)这种情况,由于这时候的返回值是foo()而不是obj1.foo或者obj2.foo,因此也会应用默认绑定
ES6中箭头函数的this词法
箭头函数中的this不适用this的四种标准规则,而是根据外层作用域来决定this
function fun() {
//返回一个箭头函数
return() => {//this继承自foo()
console.log(this.name);
}
}
var obj1 = {
name: "obj1"
}
var obj2 = {
name: "obj2"
}
var foo = fun.call(obj1);
foo(); //obj1
foo.call(obj2); //obj1
fun()内部的箭头函数会捕捉调用时foo()的this
而箭头函数的绑定无法被修改.(new也不行!)