使用const加箭头函数声明函数相对于function声明函数有什么好处?
发布于 1 年前 作者 ta7sudan 1430 次浏览 来自 问答

看很多开源项目声明函数时都是用const加箭头函数

const test = () => {
  // ...
}

相比较于普通的function声明

function test() {
  // ...
}

有什么好处? 有利于编译器优化还是? 不然个人感觉function应该更加符合语义吧 补充下: this绑定这种区别就不用说了,比较关心的是对于那些没有用到this的函数,这样写的好处

26 回复

其他不知道,不需要bind(this)感觉挺爽的

代码更短,可读性更高

some_list.map(x => x*x);

对比

some_list.map(function (x) {
    return x*x;
});

@justjavac 匿名的肯定我也会这么写, 但是看很多开源项目或者库中, 一些简单的工具函数都是命名的函数, 也没有绑定this这样的需求, 也用const加箭头函数来声明而不用function声明, 不知道有没有特别的用意? 还是仅仅是个人习惯? 或者大大能不能解释下这两者, 抛开代码简短, 或规范要求等区别, 在性能上会有什么差异吗?

个人感觉,箭头函数抛弃了this后,更像是一个普通的方法,内存消耗上来看,应该会比function要少一点吧.

根据 perf.com 网站的几个 case,箭头函数有轻微的性能提升:

还有一个原因可能是为了代码风格的统一吧,所以即使没有绑定 this 的函数,也使用了箭头函数。

@justjavac image.png为啥我测的结果不一样

@243011068 我是用 Firefox 测试的。而且下面有图表:

果然,我试了 chrome 71,居然又倒退了

不过大部分库的最终发布,都是要编译为 es5 的。但是箭头函数比普通函数美太多了,写惯了箭头函数,就不想再写普通函数了。

这点差别还叫差别?放心用吧,参考过去,只要是主流,终将被优化。

@justjavac @243011068 @ugrg 感谢各位, 大概了解了, 个人感觉没有明显性能差异的情况下, 对于命名的函数还是倾向于用function声明, 这样别人读的时候可以一眼看出这是个函数…使用const变量加箭头函数的方式声明函数经常导致我第一眼看到const还以为是个变量, 仔细一看才发现是callable的…另一方面是, const加箭头函数也没少几个字符, 如果没有编辑器自定义snippets的情况下, 还得比function多敲几个字符…(毕竟通常编辑器自带function的snippet)

@ta7sudan 好巧,我也刚刚想问这个问题。。。。 不过恰恰跟你看的开源项目都使用 const 来声明函数相反,我碰巧看的一些开源库都使用 function 来声明函数, vuex: E367DE9EE6112F375B5098DE0A5AB65D.jpg

redux: B6BB3DBCEFA1A040A79C8006CB65BF59.jpg

dva: 3582B60B70D96C047314AC744935C556.jpg

我也很奇怪,如果是我自己写,一般也直接写箭头函数了,但是不知道为什么这些比较有名的开源项目都是这样的写法 @justjavac

function 才是定义函数的正确方式。

const fn = x => x * x; 对应的是 const fn = function(x) { return x * x; } 而不是 `function fn(x) { return x; }。

箭头函数适合使用在闭包或者匿名函数的场景。

const 有什么好处?

  • 不被覆盖,被重写会报错,而函数声明会安静被覆盖

函数表达式与函数声明的对比?

  • 前者需先前面写好,明确往代码前面找定义即可,后者可前可后,更灵活
  • 前者可放块Block语句中,搭配更丰富,后者不行

同是函数表达式?

  • 相比function, 箭头函数更简洁,并自带return,单个函数最多时节省14个字符(见回复2,function+return+{} vs =>
  • 箭头函数常用于函数式编程/闭包场景,特别是频繁在数组map、filter、reduce等中的使用
  • 箭头函数更易读,更为主流,浏览器会往这方向优化

@flynntsc 箭头函数声明的好处应该大部分人能了解一些,并且确实是目前的主流,写起来也很爽快。但其实说了那么多好处,很多有名的开源项目都没用 const 来声明函数是矛盾的。

在TS中箭头函数赋值还有个方便之处是可以指定函数类型,不过较少使用。 个人倾向于function声明风格:

  • 可以快速区分变量定义和函数定义
  • 利用函数声明的作用域提升功能实现先写模块逻辑后声明函数,方便打开代码文件快速了解此模块主要逻辑
const foo = sum(1, Math.random())
....
...
function sum(x, y) { .... }

文档中使用function定义,应该是更加语义化。文档是用来解释说明的,当然使用语义化的方式可以增加可读性

我觉得本质在于const。

const test = function(){}
test = function(){}

上面这两个的区别在于,使用const声明之后,test不能重新被赋值,但若使用let、var或者不写声明指令,test可以被重新赋值。

const test = function(){}
const test = () => {}

上面这两个的区别在于一个是函数,另一个是λ表达式,λ表达式没有this等成员。

另外楼主也可以自行研究一下下面这两个的区别,同样是有区别的:

test = function(){}
function test(){}

@libook 这种区别我肯定是知道的,你可以说const修饰以后不能改变指向是优点,我也可以说function的位置可以任意相对更加灵活,当然也会有人说λ可以出现在if中根据条件动态创建而function不行。 这些优点或缺点都是由特定场景决定的而并没有某一个明显优于另一个,在特定场景下肯定会有一个最合适的,比如需要this绑定那肯定大家都会用λ。 而定义一个命名的函数显然function更符合语义,所以我主要的关注点是,在没有明显好处的情况下,比如声明一个函数,也没有用到this,有没有必要牺牲语义去使用const加λ去声明一个命名函数?如果有必要那又是出于怎样的理由?这样的场景下也有很多项目没有使用function声明,仅仅是个人喜好或是为了统一风格?

@ta7sudan 我没有说const是优点。。。只是比较了两种的区别,用哪种看上下文需要,既然你都知道有什么区别,也知道不同场景下有不同的选择,那算我多言了。

//从语义上来讲
() => {}
//是相当于
function () {}
//的,都是匿名函数,所以
let test = () => {}
//和
let test = function () {}
//在语义上是等价的,只是特性上有少许区别而已,比如this的问题

我并不认同使用const加λ表达式就意味着牺牲语义,因为虽然λ本身是匿名的,但是你用了const、let、var这些指令给它起了个名字,恰好是提高了λ表达式的语义,在我看来语义上来说两者是相等的,都能一眼看出来他们叫什么(有名字)、是什么(是函数)。

那语义问题解决了,其他方面呢:

一、用const、let会应用块级作用域,我个人比较懒得去推倒和记忆代码中的所有作用域情况,所以大多情况下,使用let、const声明函数能提高编码效率,降低因为作用域带来的Bug几率,而使用function表达式来声明有可能更会导致作用域提升,比如:

var a = 1;
function a() {};
console.log(a)
//输出的是1,而不是[Function],我很懒,懒得去注意这些问题,而且代码一多就比较头疼

既然你了解原理,那一定知道,function表达式是在预编译阶段就提升作用域的,如果安排不好代码执行的先后顺序,就有可能导致问题。这个区别和用不用λ表达式没有关系,const也可以用在function表达式上:

const test = function() {
  // ...
}

这个只是我个人作为一个懒得无可救药的人的选择,如果在编码过程中习惯做即时性的作用域推到,可以忽略这个问题。

二、性能上,一个自称是V8开发者的人说箭头函数只是语法糖,不会比普通函数更快,那你其实也可以忽略这个问题。

三、编码效率上,因为function表达需要按键的次数比箭头函数多,所以,如果像我这么懒的人的话会优先使用箭头函数,只有用到this的时候才会使用function表达式。

四、我个人比较痛恨“统一风格”,因为我认为代码风格除了美观以外,更重要的是避免问题,一个好的代码风格能让我这种很懒的人不需要时刻思考这么写会不会导致这个问题、会不会导致那个问题,按风格来写就自然而然规避了大多数问题,这些问题可能是自己语法矛盾带来的问题,也可能是团队协作语法矛盾带来的问题。而很多人没有想清楚究竟为什么需要“统一风格”而盲目追求风格的统一。我不清楚你是什么样的人,对于代码风格有什么想法,想清楚了就好。

所以楼主你发现没,我所说的都是根据我个人的具体情况的选择,每种选择都没有客观上的优势,两种方案的选择真的就是因人而异,没有银弹。 一个语法选型的问题,最一开始肯定是考虑具体的编程场景,场景承载着真正和技术相关的问题,比如逻辑性、语义性、性能等,分析需要解决的是什么问题来选择最适合的语法; 当你决定不考虑场景问题的时候,那剩下的就是个人喜好的问题了,懒的人和勤快的人选择不同,习惯不同的人选择也不同,萝卜白菜还各有所爱呢,语法也一样。

@ta7sudan 多说一句,不同人看到代码的反映是有区别的,在大量代码中,有些人更容易辨认出function,有些人更容易辨认出=>,完全取决于个人习惯,这是主观的,不是客观的。所以在这个问题上你就不要纠结于到底是使用function表达式还是λ表达式了,因人而异,永远都不会有“标注答案”的。

@libook 其实我还是挺喜欢作用域提升的,毕竟不想像C89那样严格地按顺序声明下来,除非是有运行时创建函数的需求。 另一方面是不觉得const相对于function能够一眼看出标识符的作用,其实之所以有这个帖子就是我在读源码的时候看见一个标识符发现是const,再往后看几个字符看到=>才发现是函数,相较于function声明我原本可以不用看后面几个字符,让人略微有些不爽,所以才发这么个帖子来问问。以为这么写有什么我不知道的深意结果并没有。。 至于编码效率,其实在snippet下都差不多,这点前面回复提了,而考虑到function的snippet通常编辑器自带了,而const+λ则通常需要自定义,这个角度来说其实function对于懒人反而少敲几个字符。。总的来说差不多吧,看个人喜好了 其他方面其实我们的想法是一样的

回到顶部