执行上下文当中包含了
- 变量环境
- 词法环境
- outer
- this
this 是和执行上下文绑定的
作用域链 和 this是两套不同的系统,它们之间基本没太多联系。
执行上下文分为三种:
- 全局执行上下文,
- 函数执行上下文,
- eval执行上下文(开发绝大多数情况都不会使用eval函数)
this也分为三种:
- 全局执行上下文的this
- 函数执行上下文的this
- eval执行上下文的this
一. 全局执行上下文的this
<script type="text/javascript">
console.log('window:', this)
</script>
执行上面代码可以看到打印出的是 window对象
这也是 this 和 作用域链的唯一交点,作用域链的最底端包含了 window 对象,全局执行上下文中的 this 也是指向 window 对象
二. 函数执行上下文的this
<script type="text/javascript">
function foo(){
console.log('在foo函数打印的this', this)
}
foo()
</script>
执行上面代码可以看到打印出的还是 window对象
但其实我们想要的效果是打印 foo函数的this,就需要改变this指向了,有下面几种方法
1.使用call,apply,bind
使用语法
函数方法.apply(thisArg, [argsArray])
函数方法.call(thisArg, args1, args2...)
函数方法.bind(thisArg)(args1, args2...) 创建了一个新函数,必须手动调用
<script type="text/javascript">
let bar1 = {
name1: 'zhangsan'
}
function foo1(){
let name1 = 'lisi'
console.log('this', this)
console.log("my name is "+ this.name1)
}
foo1.call(bar1)
</script>
执行上面代码,发现打印的是 bar1的this,说明this已经被改变指向于bar1
2.通过对象调用方法设置
<script type="text/javascript">
let name2 = 'lisi'
let bar2 = {
name2: 'zhangsan',
say2 () {
console.log("this: ",this);
console.log("my name is "+ this.name2)
}
}
bar2.say2()
</script>
执行上面代码,发现打印的是 bar2的this,说明this已经被改变指向于bar2
在全局环境中调用一个函数,函数内部的 this 指向的是全局变量 window。
通过一个对象来调用其内部的一个方法,该方法的执行上下文中的 this 指向对象本身。
3.通过构造函数中设置
<script type="text/javascript">
let name3 = 'lisi'
function people () {}
people.prototype={
name: "zhangsan",
say ( ) {
console.log("this: ",this);
console.log("my name is "+ this.name)
}
}
var Tom = new people();
Tom.say();
</script>
执行上面代码,发现打印的是 people的this,说明this已经被改变指向于people
this 的设计缺陷以及应对方案
1.普通函数中的 this 默认指向全局对象 window
解决思路: 使用call,apply,bind修改this指向
2. 嵌套函数中的 this 不会从外层函数中继承
<script>
let num = 1
var myObj = {
showThis: function () {
console.log('showThis打印的this:', this)
let num = 2
function bar(){
console.log('num:', num)
console.log('bar打印的this:', this)
}
bar()
}
}
myObj.showThis()
</script>
执行上方代码,可以看到打印出的效果为
- showThis打印的this 是指向于myObj
- bar打印的this 是指向于window
- bar打印的num是2, 侧面证明了 作用域链 和 this 基本没有关联
此时我们想要的是 bar的this 与 showThis的this 都指向于myObj
- 把 this 保存为一个 变量,再利用变量的作用域机制传递给嵌套函数。
- 把嵌套函数改为箭头函数,因为箭头函数没有自己的执行上下文,所以它会继承调用函数中的 this。