深入理解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为什么是单线 ...
随机推荐
- Linked List-2
三.编码技巧 1.遍历链表 先将head指针赋值给一个局部变量current: //return the number of nodes in a list (while-loop version) ...
- 数学--数论--随机算法--Pollard Rho 大数分解算法 (带输出版本)
RhoPollard Rho是一个著名的大数质因数分解算法,它的实现基于一个神奇的算法:MillerRabinMillerRabin素数测试. 操作流程 首先,我们先用MillerRabinMille ...
- Python基础03 id
id id(x)对应变量x所引用对象的内存地址.可以把id(x)看成变量x的身份标识. is 有时在编程中需要与变量的身份标识打交道,但不是通过 id 函数,而是 is 操作符. The operat ...
- HDU1176(正推DP)
时间和位置都可以决定这一秒捡到的馅饼数 不妨设\(dp[i][j]\)为在\(i\)秒\(j\)位置的最大收益 那么\(dp[0][5]=0\),dp数组的其他部分置成-1代表不能转移 那么对于第\( ...
- A - ACM Computer Factory POJ - 3436 网络流
A - ACM Computer Factory POJ - 3436 As you know, all the computers used for ACM contests must be ide ...
- Synchronized 和 ReentrantLock (Lock )的区别
原始构成 Synchronized 是关键字,属于JVM层面,底层是通过 monitorenter 和 monitorexit 完成,依赖于 monitor 对象来完成.由于 wait/notify ...
- PHP导出excel文件之权限字段筛选导出
因为导出excel时要过滤掉不是自身权限内的数据,权限有专门的字段,所以导出的数据要具体考量,数据库权限字段是MMId,因为登录的时候MMId已存入SESSION,所以导出的时候只要判断是否在此SES ...
- STM32 Cube之旅-尝试新的开发方式
尝试使用Cube进行一些开发学习,这里对此做一个梗概,先有一个全面的了解. 文章目录 Cube全家桶 CubeMX CubeIDE CubeProg 结语 Cube全家桶 曾几何时,ST刚推出Cube ...
- redis 集群安装
redis集群安装 1.下载redis源码 2.解压并进入解压后的文件夹redis内 3.make,生成一系列的文件(mkreleasehdr.sh, redis-benchmark, redis-c ...
- Gitlab升级记
一: 验证gitlab备份是否可用 这里所使用的操作系统环境全部都基于Cetnos7, 防火墙以及selinux全部关闭. 1. 另外找一台机器,安装与服务器版本相同的gitlab,根据原服务器数据的 ...