为什么重复子对象导航比使用简写变量更快?

Why is repeated sub-object navigation faster than using a short-hand variable?

本文关键字:变量 对象 导航 为什么      更新时间:2023-09-26

对不起,我不知道如何正确地表达这个问题,但问题是:

var o = {
    my: {
        very: {
            deep: {
                sub: {
                    fn(x) {
                        return x + 1;
                    }
                }
            }
        }
    }
};
var n = 0;
//without short-hand function
var timeStart = performance.now();
for (var i = 0; i < 5000000; i++) {
    n += o.my.very.deep.sub.fn(i);
}
var timeEnd = performance.now();
console.log(timeEnd - timeStart);
n = 0;
//with short-hand function
var fn = o.my.very.deep.sub.fn;
timeStart = performance.now();
for (var i = 0; i < 5000000; i++) {
    n += fn(i);
}
timeEnd = performance.now();
console.log(timeEnd - timeStart);

问题是:为什么第一个循环中的代码快了5-7%(当在全局作用域中执行时),尽管它必须重复地向下执行子对象,而在第二个循环中,它使用简写的fn代替?

PS:如果你发现一个更好的题目,请随意编辑。

var o = {
    my: {
        very: {
            deep: {
                sub: {
                    fn(x) {
                        return x + 1;
                    }
                }
            }
        }
    }
};
var n = 0;
//without short-hand function
var timeStart = performance.now();;
for (var i = 0; i < 5000000; i++) {
    n += o.my.very.deep.sub.fn(i);
}
var timeEnd = performance.now();;
console.log(timeEnd - timeStart);
n = 0;
//with short-hand function
var fn = o.my.very.deep.sub.fn;
timeStart = performance.now();
for (var i = 0; i < 5000000; i++) {
    n += fn(i);
}
timeEnd = performance.now();
console.log(timeEnd - timeStart);

运行这个(注意使用performance.now()而不是Date),两者之间的差异似乎非常小。在一些运行中,第一个实现将(非常非常轻微地)领先,在一些运行中则是后者。如果没有一个独立的测试环境,它可能是最好的,但是,从本质上讲,这个级别的测试将向您显示,这两种方法之间几乎没有区别。

第二个更快,因为您不需要在每次迭代中进行属性查找。

在第一个中,你说go to 0然后my然后very然后deep然后sub然后每次迭代执行函数o.my.very.deep.sub.fn(i)

但在第二个你缓存fnvar fn = o.my.very.deep.sub.fn;在顶部现在它不需要做查找fn在每次迭代,避免额外的工作

像v8这样的引擎为优化做了内联缓存,它们甚至可能不会为每次迭代做动态查找,但这完全取决于实现。检查这个以了解v8是如何实现它的。快速属性访问也是v8优化属性访问的方式,但要点是

V8通常对你的代码非常乐观,并试图提高速度尽量往上爬。但有时它所做的假设无效(隐藏类不是预期的)。在这种情况下,V8将用完全未优化的代码替换内联缓存快速路径代码代码。