深入理解JS:执行上下文中的this(二)
目录
- 序言
- Function.prototype.bind() 方法
- 箭头函数
- 参考
1.序言
在 深入理解JS:执行上下文中的this(一) 中,我们主要深入分析全局环境和函数环境中函数调用的 this,还留下 bind 方法以及箭头函数的 this 尚未分析,因此我们将在这篇文章进行讲解。
2.Function.prototype.bind() 方法
bind() 方法将会创建返回一个新的函数。在 bind() 被调用时,这个新函数的 this 将被指定为 bind() 的第一个参数,而其余参数将作为新函数的参数,供调用时使用。
ES5 引入了 bind 方法来设置函数的 this 值,而不用考虑函数如何被调用的。
这里给出一种 bind() 的实现算法:
var slice = Array.prototype.slice;
Function.prototype.bind = function() {
var thatFunc = this, thatArg = arguments[0];
var args = slice.call(arguments, 1);
if (typeof thatFunc !== 'function') {
throw new TypeError('Function.prototype.bind called on incompatible ' + thatFunc);
}
return function(){
var funcArgs = args.concat(slice.call(arguments))
return thatFunc.apply(thatArg, funcArgs);
};
};
注:上述代码并没有完全按照ES5规范实现,只是作为一种实现参考,更加完善的解决方案可以参考 function-bind
但不论哪种实现,其实质上都是通过使用类似 Function.prototype.apply(thisArg, argArray)
方法来实现指定调用函数 this 的。
3.箭头函数
箭头函数表达式的语法比函数表达式更简洁,并且没有自己的 this,arguments,super 或 new.target。它很适合用作匿名函数,并且不能用作构造函数(为什么呢?详情点击查看)。
ES6 引入了支持 this 词法解析的箭头函数(它在闭合的执行环境内设置 this 的值)。
如何理解箭头函数在闭合的执行环境内设置 this 的值?
简单理解,箭头函数不会创建自己的 this,它的 this 与封闭词法环境的 this 保持一致,即如果箭头函数在全局环境中,那么它的 this 就指向全局对象,如果箭头函数在某一个函数中,那么它的 this 就指向所在函数的 this。
我们来看几个示例:
(1)全局环境
var global = this
var foo = () => { return this }
var value = 1
var bar = {
value: 2,
getValueByArrowFunc: () => {
return this.value
},
getValue: function (){
return this.value
},
}
console.log(foo() === global) // true
// 箭头函数 this => global
console.log(bar.getValueByArrowFunc()) // 1
// 普通函数 this => bar
console.log(bar.getValue()) // 2
(2)函数环境
ES6的语法:
function foo() {
this.value = 1
// 箭头函数表达式
var arr = () => {
console.log(this.value)
}
arr()
}
转化为ES5:
function foo() {
var _this = this;
this.value = 1;
// 转化为普通函数表达式
var arr = function arr() {
console.log(_this.value);
};
arr();
}
对比转化前后的代码可以看出:箭头函数会转化为一个普通函数,通过一个临时变量 _this 来传递,它之前的 this 就是所在函数的 this
(3)call() 、 apply() 或 bind() 方法
var global = this
var foo = {
bar: () => {
return this
}
}
var obj = { value : 1 }
console.log(foo.bar() === global) // true
console.log(foo.bar.call(obj) === global) // true
console.log(foo.bar.apply(obj) === global) // true
var bind = foo.bar.bind(obj)
console.log(bind() === global) // true
由于箭头函数不会创建自己的 this,那么通过 call() 、 apply() 或 bind() 方法调用一个箭头函数时,只能传递参数,第一个参数会被忽略。
4.参考
this 关键字 - JavaScript | MDN - Mozilla
Function.prototype.bind() - JavaScript - MDN - Mozilla
深入理解JS:执行上下文中的this(二)的更多相关文章
- 从一道看似简单的面试题重新理解JS执行机制与定时器
壹 ❀ 引 最近在看前端进阶的系列专栏,碰巧看到了几篇关于JS事件执行机制的面试文章,因为我在之前一篇 JS执行机制详解,定时器时间间隔的真正含义 博文中也有记录JS执行机制,所以正好用于作为测试自 ...
- 深入理解JS 执行细节
javascript从定义到执行,JS引擎在实现层做了很多初始化工作,因此在学习JS引擎工作机制之前,我们需要引入几个相关的概念:执行环境栈.全局对象.执行环境.变量对象.活动对象.作用域和作用域链等 ...
- 深入理解JS执行细节(写的很精辟)
来源于:http://www.cnblogs.com/onepixel/p/5090799.html javascript从定义到执行,JS引擎在实现层做了很多初始化工作,因此在学习JS引擎工作机制之 ...
- 深入理解js——执行上下文
什么是"执行上下文"?暂且不下定义,先看一段代码: 第一句报错,a未定义,很正常.第二句.第三句输出都是undefined,说明浏览器在执行console.log(a)时,已经知道 ...
- 深入学习JS执行--创建执行上下文(变量对象,作用域链,this)
一.介绍 本篇继上一篇深入理解js执行--单线程的JS,这次我们来深入了解js执行过程中的执行上下文. 本篇涉及到的名词:预执行,执行上下文,变量对象,活动对象,作用域链,this等 二.预执行 在上 ...
- JS执行机制详解,定时器时间间隔的真正含义
壹 ❀ 引 通过结果倒推过程是我们常用的思考模式,我在上一篇学习promise笔记中,有少量关于promise执行顺序的例子,通过倒推,我成功让自己对于js执行机制的理解一塌糊涂,js事件机制,事件 ...
- 深入理解JS:执行上下文中的this(一)
目录 执行上下文与执行上下文栈 this 全局环境 函数环境 总结 参考 1.执行上下文与执行上下文栈 (1)什么是执行上下文? 在 JavaScript 代码运行时,解释执行全局代码.调用函数或使用 ...
- js的基础(平民理解的执行上下文/调用堆栈/内存栈/值类型/引用类型)
与以前的切图比较,现在的前端开发对js的要求似乎越来越高,在开发中,我们不仅仅是要知道如何运用现有的框架(react/vue/ng), 而且我们对一些基础的知识的依赖越来越大. 现在我们就用平民的方法 ...
- 10分钟理解JS引擎的执行机制
首先,请牢记2点: (1) JS是单线程语言 (2) JS的Event Loop是JS的执行机制.深入了解JS的执行,就等于深入了解JS里的event loop 1.灵魂三问 (1) JS为什么是单线 ...
随机推荐
- 图论--最短路-- Dijkstra模板(目前见到的最好用的)
之前的我那个板子,老是卡内存,不知道为什么,我看别人过的那个题都是结构体,我就开始对自己板子做了修改,然后他奶奶的就过了,而且速度也提高了,内存也小了.(自从用了这个板子,隔壁小孩馋哭了)也不知道为啥 ...
- POJ2421 Constructing Roads 最小生成树
修路 时限: 2000MS 内存限制: 65536K 提交总数: 31810 接受: 14215 描述 有N个村庄,编号从1到N,您应该修建一些道路,使每两个村庄可以相互连接.我们说两个村庄A ...
- Unity 游戏框架搭建 2019 (四十二、四十三) MonoBehaviour 简化 & 定时功能
MonoBehaviour 简化 在前两篇,我们完成了第九个示例.为了完善第九个示例,我们复习了类的继承,又学习了泛型和 params 关键字. 我们已经接触了类的继承了.接触继承之前,把类仅仅当做是 ...
- C. Journey bfs 拓扑排序+dp
C. Journey 补今天早训 这个是一个dp,开始我以为是一个图论,然后就写了一个dij和网络流,然后mle了,不过我觉得如果空间开的足够的,应该也是可以过的. 然后看了题解说是一个dp,这个dp ...
- 2249: Altruistic Amphibians 01背包的应用 + lh的简单图论 图转树求lca
第一个 写了两个比较简单的数论题目,就是整除理论的两个题目,第一个题目比较蠢,第二个稍微要动一点脑筋 Codeforces Round #347 (Div. 2) – A. Complicated G ...
- Oracle的pl/sql变量类型
pl/sql定义 sql是结构化查询语言.sql是不是一个编程语言?编程语言一般都能够声明变量,写条件判断,循环.sql不具备这些特征,所有sql不是一门编程语言.我们在实际的开发中,有这种需要,把s ...
- nginx源码安装方法
nginx源码安装方法 安装方法如下 1.安装nginx必要的源码依赖软件包. yum -y install gcc gcc-c++ automake pcre pcre-devel zlib zli ...
- [hdu5392 Infoplane in Tina Town]置换的最小循环长度,最小公倍数取模,输入挂
题意:给一个置换,求最小循环长度对p取模的结果 思路:一个置换可以写成若干循环的乘积,最小循环长度为每个循环长度的最小公倍数.求最小公倍数对p取模的结果可以对每个数因式分解,将最小公倍数表示成质数幂的 ...
- 《学习笔记》.NET Core API搭建
1.创建 ASP.NET Core Web程序,记住取消HTTPS配置 2.此时一个简单的.NET Core API 架子搭建好了,细心的人可以发现Properties下面不是CS文件,确是launc ...
- java经典问题 byte b=1、b=b+1、b+=1
直接问题: 首先 byte的范围 [-128,127] byte 类型可以自动转为int类型 int类型不能自动转为byte类型. 超过byte的范围,就会变成int类型了 byte b=1:正确, ...