上篇文章中:bind\call\apply、构造函数、箭头函数中的this指向(二),我们通过call、apply、bind方式对this指向进行绑定称为显式绑定,而根据调用关系确定this的指向称为隐式绑定。
那么显式绑定和隐式绑定的优先级谁更高呢?让我们看看今天的实例
this优先级
示例1
function foo(a) {
console.log(this.a)
}
const obj1 = {
a: 1,
foo: foo
}
const obj2 = {
a: 2,
foo: foo
}
obj1.foo.call(obj2) // ?
obj2.foo.call(obj1) // ?
上面的代码将分别输出2、1,也就是call、apply的显式绑定的优先级要更高。
示例2
function foo (a) {
this.a = a
}
const obj1 = {}
let bar = foo.bind(obj1)
bar(2)
console.log(obj1.a) // ?
上面的代码先通过bind将foo函数中的this绑定到obj1对象,然后返回新的函数bar,执行bar(2)后,由于this绑定的对象为obj1,所以obj1.a为2。所以这道题目将输出2
。
示例3
function foo (a) {
this.a = a
}
const obj1 = {}
let bar = foo.bind(obj1)
let baz = new bar(3)
console.log(baz.a) // ?
这道题目的输出为3
。
当使用bar作为构造函数调用时,bar本身是foo函数通过bind将函数内this绑定为obj1对象,但当我们使用new操作符调用时,返回的实例已经和obj1解绑了。也就是说,new操作修改了bind绑定的this指向,所以new的绑定this优先级要比bind绑定的更高。
示例4
function foo () {
return a => {
console.log(this.a)
}
}
const obj1 = {
a: 2
}
const obj2 = {
a: 3
}
const bar = foo.call(obj1)
console.log(bar.call(obj2))
上面的这道题又结合了箭头函数,所以看起来可能会有一些绕,没关系,我们来一步步的来梳理。
首先foo.call(obj1)
将foo函数内的this绑定为obj1对象,然后返回的是一个箭头函数bar。
重点来了,箭头函数bar中的this是外层函数foo内的this指向决定的。
然后bar.call(obj2)尝试去修改箭头函数bar内的this指向,这里要记住箭头函数的this指向无法被修改。
所以箭头函数内的this指向仍是foo函数内的this也就是,被call修改成的obj1对象。
所以这道题目将输出2
。
记住:
在箭头函数中,this的指向是由外层函数或者全局作用域来决定。箭头函数的this指向无法被修改。
示例5
var a = 123
const foo = () => a => {
console.log(this.a)
}
const obj1 = {
a: 2
}
const obj2 = {
a: 3
}
let bar = foo.call(obj1)
console.log(bar.call(obj2)) // ?
这道题目考察的也是箭头函数的this指向问题。
根据箭头函数的特性
在箭头函数中,this的指向是由外层函数或者全局作用域来决定。箭头函数的this指向无法被修改。
上面的两次call函数都是无法修改箭头函数内的this指向。根据箭头函数的特性,是由其外层函数的作用域this决定。所以箭头函数bar中的this.a
就会向上层去函数作用域去寻找,它的上层是箭头函数foo,所以还要向上层进行寻找,再上层就是全局作用域,所以最终this指向为window,在全局作用域中有一个变量a为123。
所以这道题将输出123
。
示例6
这道题和上面的一样,只是将变量a的声明方式从var
变成了const
,那么结果是什么呢?
const a = 123
const foo = () => a => {
console.log(this.a)
}
const obj1 = {
a: 2
}
const obj2 = {
a: 3
}
let bar = foo.call(obj1)
console.log(bar.call(obj2)) // ?
答案是undefined
,因为const或者let声明的变量不会被挂载到window对象上。所以this指向window对象时,也找不到a变量。
通过今天的这六个实例,相信大家对this指向的理解,又更上一层楼了。
欢迎我的公众号【小帅的编程笔记】,让我们在前端的路上越走越远