谈谈 js 中的 this
js 中的this是面试官经常考的问题,相信每一个开发者都对 this 有或多或少的迷惑,那么什么是 this?又如何找到 this 的指向?
this 是什么?
我们先来看看 js 规范是如何解释它的
第一处 10.1.7 对 this 的解释(译):存在与每个活动执行上下文关联的 this 值。 this 值取决于调用方和正在执行的代码类型,并由控件进入执行上下文时确定。与执行上下文关联的 this 值是不可变的。
第二处 11.1.1 译:this 关键字计算为执行上下文的这个值。
第三处 12.2.1 描述 this 也是正在运行时的上下文环境。
this 的指向
ok,以上三处,都围绕一个词:上下文环境。也就是说要看 this 的指向就是通过上下文来决定的。
下面通过几个场景来观察 this。
全局环境下的 this
- nodejs 环境
1 | console.log(this); // {} |
- 浏览器环境
全局环境下的 this,在 nodejs 中是{},实际指向的是 module.exports 这个模块作用域,,浏览器指向的是 Window。
函数内(function)中的 this
- nodejs 非严格模式下
1 | function fn() { |
- 浏览器环境 非严格模式下
- nodejs 严格模式下
1 | function fn() { |
- 浏览器环境下
非严格模式下,函数内 this 的指向
nodejs:global
浏览器:window
严格模式下,函数内 this 的指向
nodejs:undefined
浏览器:undefined
构造函数内的 this
这个也属于函数内的 this,因为内容较大,这里单独拿出来讲:
1 | function Person(name) { |
例子可以看出,当经过 new 关键字来声明一个对象时,这里的 this 实际指向的是他的实例。
改变 this 的指向(call,apply,bind)
- call
语法:function.call(thisArgs,arg1,arg2, …)
第一个参数代表 function 函数内 this 值,可选。
arg1,arg2, … 指定参数列表
1 | function Person() { |
- apply
语法:function.apply(thisArgs,[arg1,arg2, …])
第一个参数代表 function 函数内的 this 值,可选。
[arg1,arg2, …] 指定参数列表
1 | function Person() { |
- bind
语法:与 apply 语法相同
区别:bind 函数会创建一个新的函数,不会立即执行
1 | function Person() { |
call、apply、bind 均以改变 this 的指向,p 的 this 指向了 man。
####
作为对象的方法
1 | const Person = { |
当函数作为对象里的方法被调用时,它们的 this 指向的是调用该函数的对象。
**
箭头函数
函数体内的
this
对象,就是定义时所在的对象,而不是使用时所在的对象this
指向的固定化,并不是因为箭头函数内部有绑定this
的机制,实际原因是箭头函数根本没有自己的this
,导致内部的this
就是外层代码块的this
–《es6 标准入门 阮一峰》
function 函数:
1 | const fn = function () { |
箭头函数:
1 | const fn = () => { |
箭头函数没有自己的 this,它的 this 就是上层代码块的 this。
总结:
全局环境下的 this,在 nodejs 中是{},实际指向的是 module.exports 这个模块作用域,,浏览器指向的是 Window。
函数内的 this
非严格模式下,函数内 this 的指向
nodejs:global
浏览器:window
严格模式下,函数内 this 的指向
nodejs:undefined
浏览器:undefined
**
- 构造函数的 this,**new 关键字来声明的对象 this 指向的是它的实例。**
- call,apply,bind 函数改变的 this,指向的是其函数内的指定参数。
- 作为对象的方法,**它们的 this 指向的是调用该函数的对象。**
- 箭头函数的 this,箭头函数的 this 指向的是外层代码块的 this。
习题
通过几道题,看你是否真的掌握了 this。
- 运行 test2.js,说出打印结果。
① 创建 test1.js
1 | module.exports = this; |
② 创建 test2.js
1 | const t1 = require("./test1"); |
- 运行 test2.js,说出打印结果
① 创建 test1.js
1 | module.exports = function () { |
① 创建 test2.js
1 | const t1 = require("./test1"); |
- 运行以下代码,并说出打印结果
1 | const Person = { |
- 运行一下代码,说出打印结果
1 | function Person() { |
- 说出打印结果。
1 | function Person() { |