JavaScript this
this 是什么?
this 是 JavaScript 中一个特殊变量,它指的是一个执行上下文对象。他的值在运行时确定。
this 指向什么?
this 的指向可大致分为 2 种情况,函数内(直接包含)和函数外。
函数内
在函数内,又可以大致分为:函数作为构造函数执行,函数作为普通函数执行,函数作为对象方法执行。
函数作为构造函数执行
this 指向通过 new 创建的新对象,该对象的 __proto__ 指向构造函数的原型对象。
javascript
function Fn() {
console.log("constructor this:", this); // this 指向通过 new 创建的新对象,该对象的 __proto__ 指向 Fn.prototype(即新对象是 Fn 的实例)
}
new Fn();函数作为普通函数执行
函数直接被调用的时候,this 绑定到全局对象。
javascript
function fn() {
console.log("fn() called this:", this); // 非严格模式下 this 绑定到全局对象
}
function foo() {
"use strict";
console.log("foo() called this:", this); // 严格模式下 this 为 undefined
}
fn();
foo();函数作为对象方法执行
javascript
function fn() {
console.log("ojb.fn() called this:", this);
}
var obj = {
fn: fn,
};
obj.fn();函数外
全局作用域
- 严格模式下 this 指向 undefined
- 非严格模式下 this 指向 在全局作用域下指向全局对象(浏览器中是 window,Node.js 中是 global),相当于 全局对象.函数()。
html
<script>
console.log("global this:", this); // window (全局对象)
</script>
<script>
"use strict";
console.log("global this:", this); // undefined
</script>模块作用域
模块作用域其顶层 this 固定为 undefined,一般模块作用域中都是严格模式。
html
<script type="module">
console.log("module this:", this); // undefined
</script>eval() 作用域
eval() 函数执行动态代码,动态代码在非严格模式下会污染当前作用域,动态代码能访问作用域链中的变量,在严格模式 eval() 会创建一个独立的局部作用域,无法访问外层作用域链上的变量,只能访问全局作用域的变量。
eval 内 this:继承调用时的外层 this,而非固定值。
html
<script>
var obj = {};
eval("console.log('eval() this:', this)"); // this 绑定到全局对象
function fn() {
eval("console.log('eval() this:', this)"); // this 为 obj
("use strict");
eval("console.log('eval() this:', this)"); // this 为 obj
}
obj.fn = fn;
obj.fn();
</script>其他注意事项
指定函数中的 this 指向
函数中 this 可以通过 call、apply、bind 方法显示指定。call、apply 本质上是返回了一个新的函数。
javascript
function fn() {
console.log(this.name);
}
const obj = { name: "指定的 this" };
fn.call(obj); // 输出 "指定的 this"(call 传单个参数)
fn.apply(obj); // 输出 "指定的 this"(apply 传数组参数)
const boundFn = fn.bind(obj);
boundFn(); // 输出 "指定的 this"(bind 返回新函数,永久绑定)箭头函数中的 this 指向
箭头函数是一个纯粹的函数,它不存在自身的 this,它的 this 绑定到创建它的外层作用域中的 this,外层作用域没有自身的 this 的,则向上查找,直到找到为止。
html
<script>
var fn = () => {
console.log("this:", this); // this 指向全局对象
};
fn();
var obj = {
fn: function () {
var fn = () => {
console.log("this:", this); // this 绑定到函数作用域中的this
};
fn();
},
};
obj.fn();
</script>
<script type="module">
var fn = () => {
console.log("this:", this); // this 指向模块作用域中的this(undefined)
};
fn();
</script>