开发者

Is using a cached "this" faster than "this" when accessing methods of the same object?

开发者 https://www.devze.com 2023-02-06 05:51 出处:网络
if I access this.something multiple times from another method, would it be faster to cache \"this\" and access something() or should I just use this.something() over and over?

if I access this.something multiple times from another method, would it be faster to cache "this" and access something() or should I just use this.something() over and over?

<script type="text/javascript">
var Foo = (function() {
    return {
        something: function() {
            // Do something
        },
        stuff: function(obj) {
            this.something(obj);
            // ...
            this.something(obj);

            /* OR should I cache this? */
            var $that = this;
            $that.something(obj);
         开发者_运维知识库   // ...
            $that.something(obj);
        }
    };
}());
</script>


Update: Check CMS' comment below for the real truth (but I don't think it changes anything regarding performance).


Approximate truth:

No, it won't make any difference. Upon execution of the function, an activation object is created and put at the beginning of the scope chain of the function (more specifically, its execution context).

The activation object has the properties this, arguments, one property for each parameter passed and for each variable declared in the function.

Hence, this and $that live in the same scope and you gain nothing from it. You only get an improvement, when you reference an object/value locally that is in a higher scope.

  +-------------------+     +-------------+
  | Execution Context |  +->| Scope Chain |
  | ----------------- |  |  | ----------- |
  | Scope chain  +----+--+  | 0    |  +---+----------+
  +-------------------+     | 1    |  +---+-...      |
                            +-------------+          |
                                                     |
                                                     |
                                                     |
                            +--------------------+   |
                            |  Activation Object |<--+
                            | ------------------ |
                            | this     |  foo    |  (if called with foo.method())
                            | arguments|[someObj]|
                            | obj      | someObj |
                            | $that    |  foo    | (undefined until assignment)
                            +--------------------+

Graphic stolen from High Performance JavaScript. It's an interesting book to read.


You'll just be pointing at a copy of a reference to an object, rather than directly to the reference to the object. I can't imagine how caching it would be faster - but hey, fire up a test framework, execute it inside a loop 10000 times and see if it makes any difference.


I don't see why a variable should be faster than this.

Something that could have been possibly faster but that I found does NOT work is to cache the whole method lookup... e.g. by doing m = object.method; ... m(x,y,z);. This is something that for example in Python works (because of the bound method concept) but that however is not available in Javascript.

The result of a method lookup in Javascript gives you more or less something like what is a method pointer of C++, in other words a function that doesn't know this and so you must provide this yourself it to be able to call it.

The only difference is that in C++ any method that's not declared static will not be callable without providing a this, while in Javascript saving the method lookup may apparently work only for methods that at runtime don't need this perform as expected.

For example var mycos = Math.cos; mycos(0.3); on chrome at least apparently works because cos doesn't need to access Math (not really that surprising after all).

You can get a closure that functionally works as a cached method...

var cachedfoo = obj.foo;
var foo = function(x, y, z) { return cachedfoo.call(obj, x, y, z); }
...
foo(1,2,3); // this is the same as obj.foo(1,2,3)

that could be useful for other reasons, but that IMO it's not going to be faster (it would probably be slower indeed)...


Only profiling will answer here. But before doing such micro-optimizations, ask yourself if you really need to.

0

精彩评论

暂无评论...
验证码 换一张
取 消