深入理解this机制系列第三篇——箭头函数
前面的话
this机制与函数调用有关,而作用域则与函数定义有关。有没有什么是可以将this机制和作用域联系起来的呢?本文将介绍ES6新增的内容——箭头函数
痛点
对于闭包的痛点在于,闭包的this默认绑定到window对象,但又常常需要访问嵌套函数的this,所以常常在嵌套函数中使用var that = this,然后在闭包中使用that替代this,使用作用域查找的方法来找到嵌套函数的this值
var a = 0;
function foo(){
function test(){
console.log(this.a);
}
return test;
};
var obj = {
a : 2,
foo:foo
}
obj.foo()();//
var a = 0;
function foo(){
var that = this;
function test(){
console.log(that.a);
}
return test;
};
var obj = {
a : 2,
foo:foo
}
obj.foo()();//
解决
而箭头函数的出现就可以很好的解决该问题。箭头函数根据当前的词法作用域而不是根据this机制顺序来决定this,所以,箭头函数会继承外层函数调用的this绑定,而无论this绑定到什么
var test = () => {
console.log(this.a);
}
//形式上等价于
var test = function(){
console.log(this.a);
}
//实质上等价于
function fn(){
var that = this;
var test = function(){
console.log(that.a);
}
}
var a = 0;
function foo(){
var test = () => {
console.log(this.a);
}
return test;
};
var obj = {
a : 2,
foo:foo
}
obj.foo()();//
基本用法
ES6允许使用“箭头”(=>)定义函数,一般称为胖箭头
var f = v => v;
console.log(f(1));//
//等同于
var f = function(v) {
return v;
};
console.log(f(1));//
如果箭头函数不需要参数或需要多个参数,就使用一个圆括号代表参数部分
var f = () => 5;
// 等同于
var f = function () { return 5 }; var sum = (num1, num2) => num1 + num2;
// 等同于
var sum = function(num1, num2) {
return num1 + num2;
};
如果箭头函数的代码块部分多于一条语句,就要使用大括号将它们括起来
var sum = (num1, num2) => {
var restult = num1 + num2;
return result;
}
由于大括号被解释为代码块,所以如果箭头函数直接返回一个对象,必须在对象外面加上括号
var getTempItem = id => ({ id: id, name: "Temp" });
回调函数
箭头函数最常用于回调函数,如事件处理器或定时器中
function foo() {
setTimeout(() => {
console.log( this.a );
},100);
}
var obj = {
a: 2
};
foo.call( obj ); //
//等价于
function foo() {
var that = this;
setTimeout( function(){
console.log( that.a );
}, 100 );
}
var obj = {
a: 2
};
foo.call( obj ); //
注意事项
【1】this在箭头函数中被绑定,4种绑定规则中的无论哪种都无法改变其绑定
var a = 0;
function foo(){
var test = () => {
console.log(this.a);
}
return test;
};
var obj1 = {
a : 1,
foo:foo
}
var obj2 = {
a : 2,
foo:foo
}
obj1.foo()();//
var bar = foo.call(obj1);
//由于上一条语句已经把this绑定到obj1上,且无法修改。所以本条语句call(obj2)无效,返回的值是obj1.a的值1
bar.call(obj2);//
【2】箭头函数不可以当作构造函数,也就是不可以使用new命令,否则会报错
var foo = () =>{return 1;}
foo();//
var obj = new foo();//Uncaught TypeError: foo is not a constructor
【3】箭头函数中不存在arguments对象
var foo = () =>{
console.log(arguments);//Uncaught ReferenceError: arguments is not defined
return 1;
}
foo();
最后
虽然箭头函数可以把作用域和this机制联系起来,但是却容易混淆,使代码难以维护。应该在作用域和this机制中二选一,否则它们就真的汇成一锅粥了。或者只使用词法作用域,或者只使用this机制,必要时使用bind()。尽量避免使用that=this和箭头函数
this机制系列介绍完了。最重要的还是第一篇this机制的绑定原则,第二篇this机制的优先级属于要点,而本篇则是拓展部分。如有不妥之处,欢迎交流
以上
深入理解this机制系列第三篇——箭头函数的更多相关文章
- 深入理解javascript作用域系列第三篇——声明提升(hoisting)
× 目录 [1]变量 [2]函数 [3]优先 前面的话 一般认为,javascript代码在执行时是由上到下一行一行执行的.但实际上这并不完全正确,主要是因为声明提升的存在.本文是深入理解javasc ...
- 深入理解javascript作用域系列第三篇
前面的话 一般认为,javascript代码在执行时是由上到下一行一行执行的.但实际上这并不完全正确,主要是因为声明提升的存在.本文是深入理解javascript作用域系列第三篇——声明提升(hois ...
- 深入理解DOM事件机制系列第三篇——事件对象
× 目录 [1]获取 [2]事件类型 [3]事件目标[4]事件代理[5]事件冒泡[6]事件流[7]默认行为 前面的话 在触发DOM上的某个事件时,会产生一个事件对象event,这个对象中包含着所有与事 ...
- 深入理解javascript对象系列第三篇——神秘的属性描述符
× 目录 [1]类型 [2]方法 [3]详述[4]状态 前面的话 对于操作系统中的文件,我们可以驾轻就熟将其设置为只读.隐藏.系统文件或普通文件.于对象来说,属性描述符提供类似的功能,用来描述对象的值 ...
- 深入理解javascript函数系列第三篇——属性和方法
× 目录 [1]属性 [2]方法 前面的话 函数是javascript中的特殊的对象,可以拥有属性和方法,就像普通的对象拥有属性和方法一样.甚至可以用Function()构造函数来创建新的函数对象.本 ...
- 深入理解javascript函数系列第三篇
前面的话 函数是javascript中特殊的对象,可以拥有属性和方法,就像普通的对象拥有属性和方法一样.甚至可以用Function()构造函数来创建新的函数对象.本文是深入理解javascript函数 ...
- javascript面向对象系列第三篇——实现继承的3种形式
× 目录 [1]原型继承 [2]伪类继承 [3]组合继承 前面的话 学习如何创建对象是理解面向对象编程的第一步,第二步是理解继承.本文是javascript面向对象系列第三篇——实现继承的3种形式 [ ...
- Webpack系列-第三篇流程杂记
系列文章 Webpack系列-第一篇基础杂记 Webpack系列-第二篇插件机制杂记 Webpack系列-第三篇流程杂记 前言 本文章个人理解, 只是为了理清webpack流程, 没有关注内部过多细节 ...
- 深入理解javascript作用域系列第四篇——块作用域
× 目录 [1]let [2]const [3]try 前面的话 尽管函数作用域是最常见的作用域单元,也是现行大多数javascript最普遍的设计方法,但其他类型的作用域单元也是存在的,并且通过使用 ...
随机推荐
- WP8解析XML格式文件
DOTA2 WebAPI请求返回的格式有两种,一种是XML,一种是JSON,默认是返回JSON格式,如果要返回XML格式的话,需要在加上format=xml. 这里举一个简单的解析XML格式的例子(更 ...
- asp.net中用cookie记住密码上次不用登陆
------最佳解决方案--------------------写入CookieResponse.Cookies["UserName"].Value = "用户名&quo ...
- AMD与CMD(转载)
JavaSript模块化 在了解AMD,CMD规范前,还是需要先来简单地了解下什么是模块化,模块化开发? 模块化是指在解决某一个复杂问题或者一系列的杂糅问题时,依照一种分类的思维把问题 ...
- JS中原型链继承
当我们通过构造函数A来实现一项功能的时候,而构造函数B中需要用到构造函数A中的属性或者方法,如果我们对B中的属性或者方法进行重写就会出现冗杂的代码,同时写出来也很是麻烦.而在js中每个函数都有个原型, ...
- JAVA实现AES 解密报错Input length must be multiple of 16 when decrypting with padded cipher
加密代码 /**解密 * @param content 待解密内容 * @param password 解密密钥 * @return */ public static byte[] decrypt(b ...
- JavaScript 数组
JavaScript 数组 简介:数组是值的有序集合,JavaScript在同一个数组中可以存放多种类型的元素,而且是长度也是可以动态调整的,可以随着数据增加或减少自动对数组长度做更改. 一:创建数组 ...
- 自定义 TableViewCell 的分割线
刚开始自定义 tableViewCell 的时候,用的是直接在 cell 上加一张 imageView 的方法,如果在点击 cell 的时候有页面的跳转,这样做没什么问题,但是,如果在点击 cell ...
- txt文本变成html
file_name = 'x.txt' f = open(file_name,'r') file_result = 'x.html' str_head = " LINE CI UTIL&qu ...
- 应用程序无法正常启动0xc0150002(windows server 2003)
windows server 2003运行一个程序时出现 "应用程序无法正常启动0xc0150002"的错误提示; 解决方案: 下载地址:http://www.microsoft. ...
- 最近碰到的一些 SSL 问题记录
最近碰到一些 SSL 的小问题,特记录下. 我们有个 Java 实现的 SSL TCP 服务端,为客户端(PC.Android 和 iOS)提供 SSL 接入连接服务.最近有用户反馈其手机上 App ...