深入理解JavaScript的this
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了深入理解JavaScript的this,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含5037字,纯文字阅读大概需要8分钟。
内容图文
![深入理解JavaScript的this](/upload/InfoBanner/zyjiaocheng/844/484b1c3c523f4601a58a10a7cf7eb89d.jpg)
从冴羽的《JavaScript深入之从ECMAScript规范解读this》引起的思考
1.抛砖引玉
声明:本人看了冴羽一篇文章后,感觉那边文章写的很好,但是不够详细,所以在这里丰富了一下,然后也希望分享给更多的人,一起学习
javascript 的this这个关键字我相信有很多人会像我一样对他既陌生有熟悉。相信每一个学习JavaScript的前端工程师都做过这么一个事那就是到某个搜索引擎 key in ( javscript this),然后看过几个博客后感觉自己懂了this!
来来让我们看看大部分博客会怎么写:
- MDN
- Javascript 的 this 用法--阮一峰
- [译] this(他喵的)到底是什么 — 理解 JavaScript 中的 this、call、apply 和 bind -- 掘金
- The JavaScript this Keyword
.....
此外不就不列举了。
反正基本上都第一步,先告诉你一个事实『this 是在函数被调用时发生的绑定,指向上下文对象,即被调用函数所处的环境,也就是说,this 在函数内部指向了调用函数的对象。』;第二步,然后要不通过绑定方式的角度给你从new 绑定,显示绑定等多个角度告诉你this是谁,或者从函数调用情况,构造函数情况,bind调用等多个情况给你分析一波。然后不知道你会不会想我一样深深的记住调用对象是谁,this就是谁,然后把不太明白的特殊情况牢牢的记下,做个笔记什么的。然后觉得我终于弄明白this了,然后在真正使用的时候偶尔还会发生,怎么又忘记这种情况了!!!纳尼?what?脸好疼有没有?
然后在去看网上的博客,看看有没有这种情况的解释,看了冴羽大大的这篇《JavaScript深入之从ECMAScript规范解读this》文章后我觉得我可以从一个新的角度再去学习一下,让我们可以更深一步的去理解this,甚至找出一种方法,找this的时候通过“公式”去找到this的指代。
PS.在正式开始之前,本人先声明以下的文章会啰嗦一点,如果你还不是很懂this,希望你有时间去耐心的读下去,希望也可以给你一种新的认识。
2.this的前世今生
在深入了解 JavaScript 中的 this 关键字之前,有必要先退一步,看一下为什么 this 关键字很重要。this 允许复用函数时使用不同的上下文。换句话说,“this” 关键字允许在调用函数或方法时决定哪个对象应该是焦点。
2.1 this 是在函数被调用时发生的绑定,那么函数被调用的时候,JavaScript引擎都干了啥?
【ECMAScript规范 10.4.3节 进入函数代码】是这么解释的: 当控制流根据一个函数对象 F、调用者提供的 thisArg 以及调用者提供的 argumentList,进入 函数代码 的执行环境时,执行以下步骤:
- 如果函数代码是严格模式下的代码 ,设 this 绑定为 thisArg(调用者)。(严格等于调用者)
- 如果不是严格模式下的代码, 判定thisArg 是不是 null 或 undefined,是则设 this 绑定为 全局对象 。
- 否则如果 Type(thisArg) 的结果不为 Object,则设 this 绑定为 ToObject(thisArg)。
- 否则设 this 绑定为 thisArg。
- 以 F 的 [[Scope]] 内部属性为参数调用 NewDeclarativeEnvironment,并令 localEnv 为调用的结果。
- 设词法环境为 localEnv。
- 设变量环境为 localEnv。
- 令 code 为 F 的 [[Code]] 内部属性的值。
- 按 10.5 描述的方案,使用 函数代码 code 和 argumentList 执行定义绑定初始化步骤。
因为我们是研究this,所以我们着重关注前4条就可以了,简单总结一下就是:当调用函数的时候会创建函数执行上下文,在创建的过程中有一步就是创建this ,并根据是否在严格模式下,调用者是不是NUll或者undefined,调用者是不是对象决定this的指向。
2.2 我们搞清楚在调用的时候的this的指向规则,里面有个很扎眼的词 thisArg,它是什么鬼?
那我们来看看【ECMAScript规范 11.2.3节 函数调用】:
- 令 ref 为解释执行 MemberExpression 的结果 .
- 令 func 为 GetValue(ref).
- 令 argList 为解释执行 Arguments 的结果 , 产生参数值们的内部列表 (see 11.2.4).
- 如果 Type(func) is not Object ,抛出一个 TypeError 异常 .
- 如果 IsCallable(func) is false ,抛出一个 TypeError 异常 .
- 如果 Type(ref) 为 Reference,那么 如果 IsPropertyReference(ref) 为 true,那么 令 thisValue 为 GetBase(ref). 如果 Type(ref) 不是 Reference , ref 的基值是一个环境记录项,令 thisValue 为调用 GetBase(ref) 的 ImplicitThisValue 具体方法的结果
- 否则 , 假如 Type(ref) 不是 Reference. 令 thisValue 为 undefined.
- 返回调用 func 的 [[Call]] 内置方法的结果 , 传入 thisValue 作为 this 值和列表 argList 作为参数列表
这里的thisValue的值其实就是我们要找的thisArg了!!
那么根据规范我们就要先去找MemberExpression 的结果是什么了?
那我们看一看MemberExpression的语法:
- PrimaryExpression // 原始表达式 可以参见《JavaScript权威指南第四章》
- FunctionExpression // 函数定义表达式
- MemberExpression [ Expression ] // 属性访问表达式
- MemberExpression . IdentifierName // 属性访问表达式
- new MemberExpression Arguments // 对象创建表达式
原来MemberExpression 的结果就是:执行函数名部分表达式的结果(简单理解 MemberExpression 其实就是()左边的部分表达式的结果)。
下面我们要看看Reference是什么了?
Reference type:按字面翻译就是引用类型,但是它并不是我们常说的JavaScript中的引用类型,它是一个规范类型(实际并不存在),也就是说是为了解释规范某些行为而存在的,比如delete、typeof、赋值语句等。规范类型设计用于解析命名绑定的(A Reference is a resolved name binding.),它由三部分组成:
- 基 (base) 值,
- 引用名称(referenced name)
- 布尔值 严格引用 (strict reference) 标志。
基值就是属性所在的对象或者就是 EnvironmentRecord,基值是 undefined, 一个 Object, 一个 Boolean, 一个 String, 一个 Number, 一个 environment record 中的任意一个。基值是 undefined 表示此引用可以不解决一个名字的绑定(A base value of undefined indicates that the reference could not be resolved to a binding.)。
PS.最后一句话我的理解是这个引用不需要一个名字和他关联起来,比如我们创建的匿名函数,他的base应该就是undefined。
举个栗子
标签: 来源: https://blog.csdn.net/qq_29036809/article/details/86167519
内容总结
以上是互联网集市为您收集整理的深入理解JavaScript的this全部内容,希望文章能够帮你解决深入理解JavaScript的this所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。