this指向问题
普通函数中的this
非严格模式 this -> window
1 | |
严格模式 this -> undefined
1 | |
call,apply,bind中的this
情况1:this -> Window
a.call()a.call(undefined)a.call(null)
1
2
3
4
5
6function a() {
console.log(this);
}
// a.call(); // Window
// a.call(undefined) // Window
a.call(null) // Window情况2:传什么,this就是什么
1
2
3
4
5
6
7function a() {
console.log(this)
}
// a.apply("abc"); // String {'abc'}
// a.call(123); // Number {123}
const fn = a.bind({x: 1});
fn(); // {x: 1}
定时器中的this
情况1:定时器 + function this->Window
这种情况下的this始终指向Window
1
2
3
4
5
6
7
8
9
10
11setTimeout(function() {
console.log(this) // Window
}, 100)
function fn() {
setTimeout(function() {
console.log(this)
}, 100)
}
// fn() // Window
fn.call({x: 100}) // Window情况2:定时器 + 箭头函数 this->上层作用于的this
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21setTimeout(() => {
console.log(this) // Window
}, 100)
// 普通函数的this是Window
function fn() {
console.log(this) // Window
setTimeout(() => {
console.log(this) // Window
}, 100)
}
fn()
// 箭头函数定时器的this,指向上层作用于的this
function fn() {
console.log(this) // {x: 100}
setTimeout(() => {
console.log(this) // {x: 100}
}, 100)
}
fn.call({x: 100})1
2
3
4
5
6
7
8
9class obj{
fn() {
setTimeout(() => {
console.log(this) // obj {}
},100)
}
}
const o = new obj()
o.fn()
箭头函数中的this
情况1:有function作用域的,this是上层作用域的this
1
2
3
4
5
6
7class obj {
say = ()=> {
console.log(this) // obj {say: ƒ}
}
}
const o = new obj()
o.say()情况2:没有function作用域的,this是Window
1
2
3
4
5
6const obj = {
say: ()=> {
console.log(this) // Window
}
}
obj.say();1
2
3
4
5
6
7
8const btn = document.getElementById("btn");
// btn.onclick = function() {
// console.log(this) // <button id="btn">test</button>
// }
btn.onclick = ()=> {
console.log(this) // Window
}
apply ,call , bind的区别
apply和call
call() 与apply()只有一个区别,就是 call() 方法接受的是一个参数列表,而 apply() 方法接受的是一个包含多个参数的数组。 call(); 传递参数类型 直接返回调用结果.
call和apply的唯一区别就是,call需要一个个的传可选参数,而apply只需要传一个数组的可选参数。
普通函数的this默认指向Window。所以下面输出==undefined 作者: undefined.==
1 | |
bind
call和apply都是一次性使用的方法 – 如果你调用带有this上下文的方法,它将含有此上下文,但是原始的函数依旧没改变。
有时候,你可能需要重复地使用方法来调用另一个对象的上下文,所以,在这种场景下你应该使用bind方法来创建一个显示调用this的全新函数。
1 | |
在这个例子中,每次你调用newSummary,它都会返回绑定它的原始this值。尝试绑定一个新的this上下文将会失败。因此,你始终可以信任绑定的函数来返回你期待的this值。
1 | |
比较
相同点:
三者都是用来改变函数的上下文,也就是this指向的。
不同点:
fn.bind: 不会立即调用,而是返回一个绑定后的新函数。
fn.call:立即调用,返回函数执行结果,this指向第一个参数,后面可有多个参数,并且这些都是fn函数的参数。
fn.apply:立即调用,返回函数的执行结果,this指向第一个参数,第二个参数是个数组,这个数组里内容是fn函数的参数。
应用场景
需要立即调用使用
call/apply要传递的参数不多,则可以使用
fn.call(thisObj, arg1, arg2 ...)要传递的参数很多,则可以用数组将参数整理好调用
fn.apply(thisObj, [arg1, arg2 ...])不需要立即执行,而是想生成一个新的函数长期绑定某个函数给某个对象使用,使用
const newFn = fn.bind(thisObj); newFn(arg1, arg2...)