涉及面試題:如何正確判斷 this?箭頭函數的 this 是什麼?先記住了一句話
this取什麼值是在函數執行時候確定的,而不是在函數定義時候確定的!
場景一:作爲普通函數
function foo(){
console.log(this)
}
foo()
對於直接調用 foo
來說,不管 foo
函數被放在了什麼地方,this
一定是 window
場景二:作爲對象去調用:
const obj = {
a: 2,
foo: foo
}
obj.foo()
對於 obj.foo()
來說,我們只需要記住,誰調用了函數,誰就是 this
,所以在這個場景下 foo
函數中的 this
就是 obj
對象
注意setTimeout的用法
ES5:ES5中setTimeout的函數時作爲回調函數調用的,是掛載到window上的,所以this是指向window的。
const zhangsan = {
name: '張三',
sayHi() {
console.log(this)
},
wait() {
setTimeout(function(){
// this === window
console.log(this)
}, 100)
}
}
ES6:ES6中的箭頭函數自身是沒有作用域的,他的作用域來源它的上一級。
const zhangsan = {
name: '張三',
sayHi() {
console.log(this)
},
wait() {
setTimeout(() => {
// 這個this是指向zhangsan這個對象的
console.log(this)
}, 100);
}
}
場景三:作爲對象實例調用
const c = new foo()
對於 new
的方式來說,this
被永遠綁定在了 c
上面,不會被任何方式改變 this
場景四:作爲call apply bind
fn.call({ x: 100 }) //this指向{ x : 100 }
const f2 = fn.bind({ x:200 })
f2() // this指向{x: 200}
bind會更改this的指向,如果有多個bind鏈式調用的話,this也只是指向bind的第一個中對象。
場景五:箭頭函數中的 this
function a() {
return () => {
return () => {
console.log(this)
}
}
}
console.log(a()()())
首先箭頭函數其實是沒有 this
的,箭頭函數中的 this
只取決包裹箭頭函數的第一個普通函數的 this
。在這個例子中,因爲包裹箭頭函數的第一個普通函數是 a
,所以此時的 this
是 window
。另外對箭頭函數使用 bind
這類函數是無效的。
this的優先級:
new
的方式優先級最高,接下來是 bind
這些函數,然後是 obj.foo()
這種調用方式,最後是 foo
這種調用方式,同時,箭頭函數的 this
一旦被綁定,就不會再被任何方式所改變。
看一個例子:
var name = 'global'
var obj = {
name: 'local',
foo: function(){
this.name = 'foo';
}.bind(window)
}
var bar = new obj.foo();
setTimeout(function(){
console.log(window.name)
}, 0);
console.log(bar.name)//因爲bar的優先級高於bind,所以this並不會指向window
var bar3 = bar2 = bar;
bar2.name = 'foo2';
console.log(bar3.name)