我问这个问题是因为我和我的同事对编码风格存在争议,因为他更喜欢箭头功能声明:
const sum = (a, b) => a + b;
我更喜欢旧式的独立功能声明:
function sum(a, b) {
return a + b;
}
我的观点是旧式代码更具可读性,您可以更清楚地区分函数和变量声明。他的观点是带箭头功能的代码运行得更快。
当您使用旧式独立功能声明而不是箭头功能时,您是否了解实际性能损失(第8版)?这种惩罚真的存在吗?
答案 0 :(得分:65)
V8开发者在这里。箭头函数(大多数)只是"语法糖"用于传统的函数声明。没有性能差异。
答案 1 :(得分:5)
以下显示:
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>
答案 2 :(得分:1)
在我的实验中,我发现箭头函数的运行速度比普通JS函数快。 这是react中的一个小片段,使用箭头和正常功能。我发现使用箭头功能的组件的运行速度比具有普通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'))
如果您的意见不同,请告诉我
答案 3 :(得分:1)
我认为类属性中的箭头函数可能会导致一些性能问题。 这是一个示例:
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,您会注意到 setColor 和 getColor 是为每个实例创建的全新,并且每个新副本都放置在每个实例上,而函数printCarColor驻留在原型上。
如果您希望每个实例都有一千个实例能够进行固定上下文的方法引用,那么您将需要一千个单独的方法(而不是一个共享的方法),当然,您将必须存储每个实例实例本身上的那数千种独立方法中的任何一种,从而击败了单个共享原型的全部要点。
答案 4 :(得分:0)
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 $节点test_plus_i.js
fat [0,931986419]
箭头[0,960479009]
bash-3.2 $节点test_zero.js
fat [0,479557888]
箭头[0,478563661]
bash-3.2 $节点--version
v12.8.0
bash-3.2 $
因此您可以看到函数调用开销没有区别。
答案 5 :(得分:0)
箭头函数只是一个函数表达式。以下是相等的:
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
关键字时使用它们。
至少在性能上没有太大的差异。