一、this指向的绑定规则
1.默认绑定
通过函数名()直接进行函数调用,如:fn()
//例1
function foo(){
console.log('foo',this)//window
}
foo()
//例2
function foo1(){
console.log('foo1',this)//window
foo() //window
}
foo1()
//例3
const obj = {
name:'aaa',
fn:function(){
console.log('fn',this)
}
}
const bar = obj.fn
bar() //window
2.隐式绑定
通过 .函数名() 进行函数调用,如:obj.fn()
//例1
const obj = {
name:'aaa',
fn:function(){
console.log('fn',this)
}
}
obj.fn() //obj
//例2
const obj2 = {
name:'obj2',
bar:obj.fn
}
obj2.bar() //obj2
3.显示绑定
通过call、apply、bind函数进行函数调用
function foo(num1,num2){
console.log(num1,num2,this)
}
const obj = {
name:'obj'
}
//1.call
foo.call(obj,20,30) //obj
//2.apply
foo.apply(obj,[2,3]) //obj
//3.bind 会生成一个新的函数
function fn(){
console.log(this)
}
const newFn = fn.bind('aaa')
newFn() //aaa
call和apply的区别在于传参方式不同。
foo.call(obj,20,30)
foo.apply(obj,[2,3])
4.通过new关键字进行绑定
通过一个new关键字调用一个函数(构造器),this是在调用这个构造器时创建的对象
function Person(name,age){
console.log(this) // {}
this.name = name
this.age = age
console.log(this) // {name: 'www', age: 22}
}
const p1 = new Person('www',22)
5.其他
//1.setTimeout
setTimeout(function(){
console.log(this) //window
},10)
//2.点击事件
this:被点击的元素标签
//3.数组的forEach、map、filter、find,可以传入第二个参数进行显示绑定
const arr = [2,1,9]
arr.forEach((item) => {
console.log(item,this) //window
})
arr.map((item) => {
console.log(item,this) //abccc
},'abccc')
6.特殊绑定规则
6-1.忽略显示绑定
function foo(){
console.log(this)
}
foo.call(null) //window
foo.apply(undefined) //window
6-2. 间接函数引用
const obj1 = {
name:'111',
foo:function(){
console.log(this)
}
}
const obj2 = {
name:"222"
}
obj2.fn = obj1.foo
obj2.fn() //obj2
(obj2.fn = obj1.foo)() //window独立的函数调用,有运算符
6-3.箭头函数不绑定this,根据外层作用域决定
二、this绑定规则的优先级
- 默认规则优先级最低
- 显示绑定高于隐式绑定
- new绑定高于隐式绑定
- new关键字不能和apply、call一起使用
- new绑定高于显示bind绑定
常见面试题
1、
2、
3、
4、