10 执行上下文视角的 this
作用域链和this是两套不同的体系,唯一的关系是在全局上下文中的this指向window对象,作用域链的最底端包含了window对象 ## this是什么 如下图所示,`this`是和执行上下文绑定的,每个执行上下文中都有一个`this`,按照执行上下文的分类,`this`也可以分为三类: - 全局执行上下文中的`this`
-
函数执行上下文中的
this
-
eval
中的this
(略过)
全局执行上下文中的this
全局执行上下文中的 this 指向 window 对象
### 函数上下文中的this 在默认情况下调用一个函数,其执行上下文中的 this 也是指向 window 对象的
有三种方法改变this
指向:
#### 1、call/apply/bind函数
通过call/apply/bind
函数 显式改变 this
指向
call
是立即执行传递this的;bind
不是立即执行的,返回的是函数的副本;
bind 的定义:bind 会创建一个新函数,当调用该函数时,bind 会调用原函数,并将其 this 关键词设置为给定的值
let bar = {
myName : " 极客邦 ",
test1 : 1
}
function foo(name, age){
this.myName = " 极客时间 " + name + age;
}
foo.call(bar, "name", "18");
foo.apply(bar, ["name", "17"]);
foo.bind(bar)("name", "16"); // 新函数,立即执行
#### 2、通过对象调用方法 - 指向对象本身
在全局环境中调用一个函数,函数内部的 this 指向的是全局变量 window。
通过一个对象来调用其内部的一个方法,该方法的执行上下文中的 this 指向对象本身。
通过下方代码可以验证:通过 myObj
对象调用 showThis
方法 –> 最终输出的this
值是指向myObj
的
var myObj = {
name : " 极客时间 ",
showThis: function(){
console.log(this) // this -> myObj
}
}
myObj.showThis()
原因:JS执行引擎在执行 myObj.showThis()
时,实际上是将其转化成 call
函数执行,代码如:
myObj.showThis.call(myObj);
#### 3、通过构造函数设置 通过 new 关键字构建了一个新对象,并且构造函数中的 this 其实就是新对象本身
function CreateObj(){
this.name = " 极客时间 "
}
var myObj = new CreateObj()
this 的缺陷
this 没有作用域的限制
1. 嵌套函数中的 this 不会从外层函数中继承
var myObj = {
name : " 极客时间 ",
showThis: function(){
console.log(this) // showThis 中的 this -> myObj
function bar(){
console.log(this)
} // bar 中的 this -> window
bar()
}
}
myObj.showThis()
解决方案1:把 this 保存为一个 self 变量,再利用变量的作用域机制传递给嵌套函数
本质:把 this 体系转换为了作用域的体系
解决方案2:箭头函数 -> 不会创建自身的执行上下文,取决于外部函数
—> 箭头函数中的this指向定义时当前周围的作用域(词法环境)
2. 普通函数中的 this 默认指向全局对象 window
这样会打破数据的边界,造成一些误操作
-
解决方案1
如果要让函数执行上下文中的 this 指向某个对象,最好的方式是通过 call 方法来 显示调用。
-
解决方案2
通过设置 JavaScript 的严格模式来解决。在严格模式下,默认执行一个函数,其函数的执行上下文中的 this 值是
undefined