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...)