取消引用变量的闭包有用吗?

发布于 2024-12-18 07:15:25 字数 816 浏览 3 评论 0原文

我不确定取消引用变量是否或何时有用(以提高性能)。

var x = a.b.c.d[some_key].f;
while (loop) {
    do_something_with(x);
}

似乎比

while (loop) {
    do_somthing_with(a.b.c.d[some_key].f);
}

Is that need or is this returned by smart JavaScript 引擎更好?

但我真正的问题是我是否应该这样做,例如在图书馆里。

(function() {
    var slice = Array.prototype.slice;

    Function.prototype.x = function x() {
        var args = slice.call(arguments, 0);
        ...
    };
})();

或者只是

Function.prototype.x = function x() {
    var args = Array.prototype.slice.call(arguments, 0);
    ...
};

引擎无法自动改进这一点,因为它不知道 Array.prototype.slice 是否会在运行时发生变化。

那么:创建一个闭包来创建对切片函数的本地引用是否会使脚本更快?或者额外的闭包范围是否使其比访问 Array 属性“prototype”的属性“slice”慢?

I'm not sure whether or when it is useful (to improve performance) to dereference variables.

var x = a.b.c.d[some_key].f;
while (loop) {
    do_something_with(x);
}

seems to be better than

while (loop) {
    do_somthing_with(a.b.c.d[some_key].f);
}

Is that needed or is this done automagically by smart JavaScript engines?

But my actual question is whether I should do this, for example, in a library.

(function() {
    var slice = Array.prototype.slice;

    Function.prototype.x = function x() {
        var args = slice.call(arguments, 0);
        ...
    };
})();

or just

Function.prototype.x = function x() {
    var args = Array.prototype.slice.call(arguments, 0);
    ...
};

The engine can't improve this automatically because it doesn't know whether Array.prototype.slice might change during the run time.

So: does creating a closure for creating the local reference to the slice function make the script faster? Or does the additional closure scope make it slower than accessing the property "slice" of the property "prototype" of Array?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

若水微香 2024-12-25 07:15:25

出于此目的,“取消引用”实际上是一个令人困惑的词。事实并非如此,您只是在局部变量中缓存一些属性/方法。实际上,无论您是为了访问随机对象上的某些属性/方法还是使用 Array.prototype.slice 来访问这些属性/方法,都没有什么区别。一旦您多次访问这些深度嵌套的属性,它就变得很有意义

老实说,“现代”浏览器确实对访问进行了很多优化。所有现代 js 引擎都使用内部查找表来访问属性。但是,您仍然希望缓存那些深层嵌套的内容,因为在较旧的引擎中,它将一路向下遍历所有涉及的对象来解决它。

使用本地缓存引用的另一个原因是,即使是现代 js 引擎也不会在使用某种显式或隐式 eval 机制后立即使用哈希查找。

特别是 Internet Explorer <9 和 Firefox 3.5 在(原型)链中每增加一步都会导致严重的性能损失。


需要注意的是:不建议对对象方法使用本地缓存(就像使用 slice 方法一样)。许多对象使用 this 来确定调用它们的上下文。将方法存储在局部变量中会导致 this 绑定到全局对象null
因此,请始终确保使用 method.call 调用此类方法来手动设置上下文。

"Dereferencing" is actually a confusing word for that purpose. Its not that, you just cache some property/method in a local variable. It actually makes no difference whether you do it to access some property/method on a random object or do it with Array.prototype.slice. It makes a lot of sense as soon as you access those deeply nested properties more than once.

Tbh, "modern" browsers do optimize the access quite a lot. All modern js engines uses internal look-up tables to accessed properties. However, you still want to cache those deeply nested stuff since in older engines, it would go the whole way down through all involved objects to resolve it.

One more reason to use local cached references is, that even modern js engines won't use a hash-lookup as soon as some kind of explicit or implicit eval mechanism is used.

Especially Internet Explorer <9 and Firefox 3.5 incur a terrible performance penalty with each additional step into a (prototype) chain.


One word of caution: it is not very recommended to use local caching for object methods (like you do with the slice method). Many objects use this to determine the context in which they are beeing called. Storing a method in a local variable causes this to be bound to global object or null.
So always make sure to call such a method with method.call to set the context manually.

落花随流水 2024-12-25 07:15:25

如果您打算多次访问某个属性,请考虑将其分配给局部变量。然而,对于现代 JavaScript 引擎来说,这种微优化的影响很小,最重要的是编写能够表达您意图的代码。

If you intend to access a property more than once, consider assigning it to a local variable. However, for modern javascript engines such micro-optimisations will make very little difference, the most important thing thing is to write code that expresses your intent.

睫毛溺水了 2024-12-25 07:15:25

对于这个特定问题,您无论如何都希望有一个实用函数:

function toArray( arrayLike ) {
    return Array.prototype.slice.call( arrayLike );
}

...或者如果您关心性能:

var toArray = (function () {
    var slice = Array.prototype.slice;

    return function ( arrayLike ) {
        return slice.call( arrayLike );
    };
})();

您不希望在整个代码中使用 slice.call 构造。 ..

For this particular issue, you want to have a utility function for that anyway:

function toArray( arrayLike ) {
    return Array.prototype.slice.call( arrayLike );
}

... or if you care about performance:

var toArray = (function () {
    var slice = Array.prototype.slice;

    return function ( arrayLike ) {
        return slice.call( arrayLike );
    };
})();

You don't want to have that slice.call construct all over your code...

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文