涉及面试题:如何正确判断 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)