要讲普通函数的this就不得不讲执行时的作用域和作用域链,要讲箭头函数的this就不得不说词法作用域。这里主讲词法作用域。
词法作用域可以动态更改:使用eval()函数,传入字符串,但是在严格模式下eval有自己的词法作用域,意味着无法更改所在的作用域。(还有其他方法,总的来说要避免动态生成代码)
大量使用eval和with会使代码运行的很慢,引擎不能静态对其进行优化,也就是所有的优化可能都是无效的。
this:在不同情况下含义不同,分别是构造函数、上下文(默认绑定为全局对象)、严格模式、call(apply、bind)调用。
普通函数的this
// 1. 普通函数的this指向调用者,
// 2. 或者没有调用者则是全局对象
var id = '全局对象id'
function foo2() {
console.log(this)// [object Window]
function foo() {
var id = '函数内部的id';
setTimeout(function () {
console.log('普通函数this.id:', this.id); //全局对象id
console.log('普通函数作用域链的id:', id) //函数内部的id
}, 1000)
//setTimeout的调用者为 全局对象 window
console.log(this)// [object Window]
setTimeout(() => {
console.log(this)// [object Window]
console.log('箭头函数this.id:', this.id);//全局对象id
console.log('箭头函数作用域链的id:', id);//函数内部的id
}, 100)
}
foo()
}
foo2()
由此代码可以看出处于同一个外层函数内,无论嵌套多少层,对于箭头函数来说,都是该外层函数所处的作用域,即父级作用域(希望能深刻理解作用域)
箭头函数的this
//对象里的箭头函数的this
var count = 2;
function test() {
var count = 3;
console.log(this) // window
var obj = {
count: 0,
cool: () => {
if (this.count > 1) {
//------------------------------------
var bbb = () => {
console.log(this) // window
var ccc = () => {
console.log(this) // window
}
ccc()
}
console.log(this) // window
bbb()
//------------------------------------
function bbb2() {
console.log(this) // window
function aaa() {
console.log(this) // window
}
aaa()
}
console.log(this) // window
bbb2()
}
}
};
obj.cool()
}
test()
这些例子想说明的是,他总是在寻找最外层的作用域,而俗称理解的“父级作用域”,让我又深思作用域的概念。 其实箭头函数的this,就是为了解决下面这个代码:
var self = this;
所以,弄不明白的话,会用就好了,接下来再去深究一下作用域的概念。
- 默认绑定为全局对象:
- 一个总结图(call分类那里是call和apply,写错了)
bind是创建一个新函数,对新的这个进行重新绑定是不行的,但是对于原来的是可以的,如果不保存bind后的函数,就凭空消失掉啦,没有任何影响。