箭头函数是否比 v8中的普通独立函数声明更快(性能更好,更轻) ?

我之所以问这个问题,是因为我和我的同事在编码风格方面存在争议,因为他更喜欢用箭头函数声明:

const sum = (a, b) => a + b;

我更喜欢旧式的独立函数声明:

function sum(a, b) {
return a + b;
}

我的观点是,旧式的代码更具可读性,而且可以更清楚地区分函数声明和变量声明。他的观点是,带箭头函数的代码只是运行得更快。

当您使用旧式的独立函数声明而不是箭头函数时,您是否了解实际的性能损失(在 v8中) ?这种惩罚真的存在吗?

26461 次浏览

下列资料显示:

  1. 第一个去是要罚款的(不管是传统的还是肥胖的)
  2. 在 Chrome 中没有明显的区别

function goFat() {
for (var i = 0; i < 1000000; i++) {
var v = ()=>{};
v();
}
}


function goTraditional() {
for (var i = 0; i < 1000000; i++) {
var v = function() {};
v();
}


}


function race() {
var start = performance.now();
goTraditional();
console.log('Traditional elapsed: ' + (performance.now() - start));
start = performance.now();
goFat()
console.log('Fat elapsed: ' + (performance.now() - start));
start = performance.now();
goTraditional();
console.log('Traditional elapsed: ' + (performance.now() - start));
start = performance.now();
goFat()
console.log('Fat elapsed: ' + (performance.now() - start));
console.log('------');
}
<button onclick="race()">RACE!</button>

这里是 V8开发人员。箭头函数(大部分)只是传统函数声明的“语法糖”。没有性能差异。

在我的 exp 中,我发现箭头函数比普通的 JS 函数运行得更快。 下面是一个使用箭头和普通函数的反应小片段。我发现使用箭头函数的组件比使用普通 js 函数的组件运行得快一些。

Https://codepen.io/lokeshpathrabe/pen/qgzadx

class Fun extends React.Component {


constructor(props){
super(props);
this.state = {start: new Date().getTime(),
end: new Date().getTime(),
number: 0};
console.log('Function start: ', this.state.start);
const fun = function(me){
let n = me.state.number
me.setState({
...me.state, end: new Date().getTime(), number: ++n
})
}
this.interval = setInterval(fun, 1, this);
}


stop(){
clearInterval(this.interval);
}


componentDidUpdate(){
if((this.state.end - this.state.start) > 5000){
console.log('Function end: ', this.state.end);
clearInterval(this.interval)
}
}


render() {
return (
<div>
<h2>Counter with Function {this.state.number}</h2>
</div>
)
}
}


class Arrow extends React.Component {


constructor(props){
super(props);
this.state = {start: new Date().getTime(),
end: new Date().getTime(),
number: 0};
console.log('Arrow start: ', this.state.start);
this.interval = setInterval(()=>{
let n = this.state.number
this.setState({
...this.state, end: new Date().getTime(), number: ++n
})
}, 1);
}


stop(){
clearInterval(this.interval);
}


componentDidUpdate(){
if((this.state.end - this.state.start) > 5000){
console.log('Arrow end: ', this.state.end);
clearInterval(this.interval)
}
}


render() {
return (
<div>
<h2>Counter with Arrow {this.state.number}</h2>
</div>
)
}
}


class HOC extends React.Component {


render() {


return (<div>
<h1>The one reaching higher count wins</h1>
<Arrow/>
<Fun/>
</div>);
}
}


ReactDOM.render(<HOC />, document.getElementById('react-content'))

如果你有不同意见,请告诉我

Nodejs 有两个例子:

function testFat(a, b) {
return a + b;
}


let testArrow = (a, b) => a + b;


let t1 = process.hrtime();
let tmp1 = 0;
for (let i = 0; i < 1000000000; ++i) {
tmp1 = testFat(tmp1, i);
}
var fatTime = process.hrtime(t1);
console.log('fat', fatTime);


let t2 = process.hrtime();
let tmp2 = 0;
for (let i = 0; i < 1000000000; ++i) {
tmp2 = testArrow(tmp2, i);
}
var arrowTime = process.hrtime(t2);
console.log('arrow', arrowTime);
function testFat() {
return 0;
}


let testArrow = () => 0;


let t1 = process.hrtime();
for (let i = 0; i < 1000000000; ++i) {
testFat();
}
var fatTime = process.hrtime(t1);
console.log('fat', fatTime);


let t2 = process.hrtime();
for (let i = 0; i < 1000000000; ++i) {
testArrow();
}
var arrowTime = process.hrtime(t2);
console.log('arrow', arrowTime);```

结果如下:

Bash-3.2 $node test _ plus _ i. js

脂肪[0,931986419]

箭头[0,960479009]

Bash-3.2 $node test _ zero. js

脂肪[0,479557888]

箭头[0,478563661]

Bash-3.2 $node —— version

V12.8.0

Bash-3.2 $

所以您可以看到,函数调用开销没有差别。

我认为类属性中的箭头函数可能会导致一些性能问题。 这里有一个例子:

class Car {
setColor = (color) => { this.color = color; }


constructor() {
this.color = '';
this.getColor = () => { return this.color; };
}


printCarColor() {
console.log(this.color);
}
}
var c = new Car();
console.log(c);

如果我们看一下变量 c,您会注意到函数 SetColorGetColor为每个实例创建全新的,每个新副本放在每个实例上,而函数 printCarColor 驻留在原型上。

如果你想要1000个实例中的每一个都能够产生固定上下文方法引用,那么你就需要1000个独立的方法(而不是一个共享的) ,当然,那么你就必须把这1000个独立的方法中的每一个都存储在实例本身上,从而破坏了单个共享原型的全部意义。

箭头函数只是一个函数表达式,下面是相等的:

const foo = (a, b) => a + b // foo = an anonymous function
const foo = function(a, b) { return a + b; }
const foo = new Function("a", "b", "return a + b")

可悬挂功能声明:

function foo(a, b) { return a + b; }

箭头函数不能用作生成器函数,如:

function* foo(a, b) {
yield a;
yield b;
}

当函数需要 this关键字时,考虑使用它们。


至少在性能上没有太大的差异。

我在 jsben.ch 中做了一个短期基准测试。我运行了很多次似乎箭头函数在大多数情况下只比普通函数快一点点。甚至有一两次正常功能的速度更快... ... 看起来这种差别是微不足道的。所以简而言之——如果你不需要介意 背景或者 这个,只要使用对你来说更好看的就行了;)

Https://jsben.ch/kjxpt

const a = (b, c) => b+c;


a(1,2);

VS

function a(b,c){
return b+c;
}


a(1,2);

enter image description here

在这里我同意 JMRK 的的回答,但是在强化 鲁安的的回答。

值得注意的是,在 ES6类中使用箭头函数时,它只是 没有的“语法糖”。

类中的箭头函数并不存在于原型中,而是作为每个对象的成员创建,每次实例化该对象的类时都创建这些函数。

例如,这门课:

class ArrowFunctionMember {
i = 0;


test = () => {
this.i += 1;
}
}

这相当于做:

class ArrowFunctionMemberEquivalent {
i = 0;


constructor () {
this.test = function () {
this.i += 1;
}
}
}

在第二个示例中更容易发现正在发生的事情——当类被实例化时,test函数的一个实例被创建,这会导致更大的内存消耗(并且实例化本身会更慢) ,这取决于创建了多少个对象。

下面是我做的一个 测试,用来说明具有箭头函数成员的类与具有普通函数成员的类的实例化速度之间的性能差异。

因此,如果您没有从具有箭头函数成员的类中创建很多对象,那么性能差异可能是可以忽略不计的。但是,如果要创建大量对象,那么可以考虑使用常规成员函数,这样就可以利用 JavaScript 对象使用的原型共享。