摘要:在需要动态上下文的地方不能使用箭头函数,使用构造函数创建对象时不能使用箭头函数等等。
作者:扉扉 (沪江web前端开发工程师)
本文原创翻译,有不当的地方欢迎指出。转载请指明出处。
看到你每天使用的编程语言在不断进化是一件令人开心的事情 。从错误中学习,找到更好的实现方式,创造新的语法特性,语言就这样一步一步地实现了版本更新。
这正是近几年Javascript身上发生的事情 ,ECMAScript6 引入了: 箭头函数,类以及其它特性,真的太棒了!
其中一个非常好用的箭头函数,有许多文件介绍了了这个漂亮的语法糖,还具有透明上下文的作用(原文为 context transparency), 如果你对于ES6还不熟悉,请先阅读箭头函数的一些入门文章。
凡事都有两面性,新的特性往往也会带来新的困扰, 比如对箭头函数的误用。
这篇文章通过实际使用场景带你了解在一些特定情况下到底是应该使用传统的函数,还是该使用更简洁的箭头函数。
1.在对象上定义方法在javascript中,方法可以做为一个对象的属性,当调用这个方法时, this 指向这个方法所属的对象;
1a. 对象字面量既然箭头函数只是一个语法糖,那我们来尝试一下使用箭头函数做为一个对象的方法会发生什么:
var calculate = { array: [1, 2, 3], sum: () => { console.log(this === window); // => true return this.array.reduce((result, item) => result + item); } }; console.log(this === window); // => true // Throws"TypeError: Cannot read property "reduce" of undefined" calculate.sum();
calculate.sum使用箭头函数来定义,但是调用 calculate.sum() 时出现了异常。因为当执行sum的时候上下文仍然是window,这是因为箭头函数已经绑定了window做为上下文。
执行this.array 等同于 window.array ,当然是 undefined
解决办法就是不要在对象的方法上使用箭头函数短语法,这样this关键字会在调用时决定,而不是早早绑定在闭合的上下文中, 让我们看一下具体代码:
var calculate = { array: [1, 2, 3], sum() { console.log(this === calculate); // => true return this.array.reduce((result, item) => result + item); } }; calculate.sum(); // => 6
对象原型
同样的规则也适用于给对象prototype原型上定义方法:
function MyCat(name) { this.catName = name; } MyCat.prototype.sayCatName = () => { console.log(this === window); // => true returnthis.catName; }; var cat = new MyCat("Mew"); cat.sayCatName(); // => undefined
使用传统方式即可正常工作:
function MyCat(name) { this.catName = name; } MyCat.prototype.sayCatName = function() { console.log(this === cat); // => true returnthis.catName; }; var cat = new MyCat("Mew"); cat.sayCatName(); // => "Mew"2.动态上下文中的回调函数
this是js中非常强大的特点,他让函数可以根据其调用方式动态的改变上下文,然后箭头函数直接在声明时就绑定了this对象,所以不再是动态的。
在客户端,在dom元素上绑定事件监听函数是非常普遍的行为,在dom事件被触发时,回调函数中的this指向该dom,可当我们使用箭头函数时:
button.addEventListener("click", () => { console.log(this === window); // => true this.innerHTML = "Clicked button"; });
因为这个回调的箭头函数是在全局上下文中被定义的,所以他的this是window。所以当this是由目标对象决定时,我们应该使用函数表达式:
button.addEventListener("click", function() { console.log(this === button); // => true this.innerHTML = "Clicked button"; });3.调用构造函数
当函数做为构造函数执行时 new MyFunction(),this指向新创建的对象实例:
this instanceOf MyFunction === true
需要注意的是,构造函数不能使用箭头函数,如果这样做会抛出异常。
因为使用箭头函数后this会指定闭合的当前上下文,而当函数做为构造器的时候,this又会指向生成的实例, 这个造成歧义。
var Message = (text) => { this.text = text; }; // Throws "TypeError: Message is not a constructor" var helloMessage = new Message("Hello World!");
我们都知道使用函数表达式即可正常:
var Message = function(text) { this.text = text; }; var helloMessage = new Message("Hello World!"); console.log(helloMessage.text); // => "Hello World!"4.超短的语法
箭头函数可以让语句写的非常的简洁,参数只有一个时可以省略(),函数体只有一句话可以省略{},如果返回值是一个表达式还甚至还可以省略return!
我的大学老师曾给我们布置了一道有趣的作业: 使用C语言来编写一个计算字符串长度的函数,函数要尽可能的短,这是一个很好的方法去学习一门新的语言。
不过在真实生活中,代码要被其它开发者阅读,超短的语法有时会让你的同事陷入难以理解中。上代码:
let double = multiply(2); double(3); // => 6 multiply(2, 3); // =>6
这个函数的作用就是当只有一个参数 a 时,返回接受一个参数 b 返回 a * b 的函数,接收两个参数时直接返回乘积,这个函数可以很好的工作并且看起很简洁,但是从第一眼看去并不是很好理解。
为了让这个函数更好的让人理解,我们可以为这个箭头函数加一对花括号,并加上 return 语句,或者直接使用函数表达式:
function multiply(a, b){ if (b === undefined) { return function(b){ return a * b; } } return a * b; } letdouble = multiply(2); double(3); // => 6 multiply(2, 3);// => 6
怎么样是不是好理解多了?
如何平衡简洁与易理解也是使用箭头函数需要注意的地方。
5.总结毫无疑问,箭头函数是一个很棒的特性。以前我们使用bind()函数或者需要固定上下文的地方现在使用箭头函数会让代码更加简洁。
但有一些情况下,使用箭头函数也有一些不便利。在需要动态上下文的地方不能使用箭头函数,使用构造函数创建对象时不能使用箭头函数等等。除去文中列举不适合使用的情况下,尽情地使用箭头函数吧。
原文地址:https://rainsoft.io/when-not-...
iKcamp原创新书《移动Web前端高效开发实战》已在亚马逊、京东、当当开售。
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/85113.html
摘要:前端日报精选如何优雅的编写代码深入理解内部机制专题之函数组合年月个有趣的和库最经典的前端面试题之一,你能答出什么幺蛾子中文翻译深入理解响应式原理掘金译与和交互掘金箭头函数使用禁忌技术栈耕耘助力美团点评前端进阶之路前端模块 2017-09-01 前端日报 精选 如何优雅的编写 JavaScript 代码深入理解 Node.js Stream 内部机制JavaScript专题之函数组合20...
摘要:因为箭头函数没有构造方法。因为不能一个箭头函数,所以也没必要有了。的值在这个箭头函数的整个生命周期里面都不变。你必须通过命名参数和剩余参数去获取箭头函数的参数。非箭头函数在非严格模式下面可以有重名参数。 例行声明:接下来的文字内容全部来自 Understanding ECMAScript 6,作者是Nicholas C.Zakas,也就是大名鼎鼎的Professional JavaSc...
摘要:一旦声明,常量的值不能被改变。顶层对象的属性顶层对象,浏览器中指的是对象,在中指的是对象。中新增了两个命令和,命令用于暴露出模块对外的接口,而则用于输入某一模块。 1.声明变量的关键字:const 和 let JavaScript ES6中引入了另外两个声明变量的关键字:const和let。在ES6中,我们将很少能看到var了。 const关键字 const声明一个只读的常量。一旦声明...
摘要:回顾我们先来回顾下箭头函数的基本语法。主要区别包括没有箭头函数没有,所以需要通过查找作用域链来确定的值。箭头函数并没有方法,不能被用作构造函数,如果通过的方式调用,会报错。 回顾 我们先来回顾下箭头函数的基本语法。 ES6 增加了箭头函数: let func = value => value; 相当于: let func = function (value) { return ...
阅读 1574·2021-11-24 09:39
阅读 3021·2021-11-22 15:24
阅读 3065·2021-10-26 09:51
阅读 3252·2021-10-19 11:46
阅读 2869·2019-08-30 15:44
阅读 2189·2019-08-29 15:30
阅读 2519·2019-08-29 15:05
阅读 751·2019-08-29 10:55