dmj16 dmj16 - 1 month ago 8
Javascript Question

Javascript apply() not working with var in bracket notation

I want to invoke a function using apply(), but when I pass a var with bracket notation, it does not work any more. Why this does not work? thanks

window.video['play'] = OK
window.video.play = OK
obj[p[i]] = not OK <= something like this I'd like to use


var obj = window;
var prop = 'video.play';

var p = prop.split('.');
for (var i = 0; i < p.length; i++) {
obj = obj[p[i]];
}

var orig = obj; // problem here with obj: window.video['play'] = OK, but obj[p[i]] = not OK
obj = function() {
var ar = Array.prototype.slice.call(arguments);
console.log(ar); // not work!
orig.apply(this, ar);
};


almost the same, but this works:

var orig = window.video.play;
window.video.play = function() {
var ar = Array.prototype.slice.call(arguments);
console.log(ar); // work!
orig.apply(this, ar);
};

Answer

tld;dr: If you want to change the value of video.play, then you have to explicitly assign to it. Only because obj has the same value as video.play doesn't mean that assigning to obj will change the value of video.play.


obj is a variable. Assigning a new value to a variable does not magically assign the new value to another variable or property. Lets get some ASCII art.

Lets start with

var foo = {
  fn: function() {
    console.log(foo);
  },
};

This creates the following object structure in memory:

                         +--------------+                     
+----+-----------+       |  Object#123  |                     
|foo |  ref:123 *+------>+------+-------+     +--------------+
+----+-----------+       | fn   |   *---+---->| Function#456 |
                         +------+-------+     +--------------+

If we assign the function to another variable, e.g.

var bar = foo.fn;

then bar directly points to the function object.

                        +--------------+                      
                        |  Object#123  |                      
                    +--->------+-------+      +--------------+
                    |   | fn   |    *--+----->| Function#456 |
+----+-----------+  |   +------+-------+      +--------------+
|foo |  ref:123 *+--+                                 ^       
+----+-----------+                                    |       
|bar |  ref:456 *+------------------------------------+       
+----+-----------+                                            

Now, assigning a new value bar will do just that: It will make bar point to another value, but it won't have any impact on foo or foo.fn:

bar = function() {
  console.log('bar');
};

As you can see, foo.fn still points to the original function:

                         +--------------+                     
                         |  Object#123  |                     
                    +--->+------+-------+     +--------------+
                    |    | fn   |   *---+---->| Function#456 |
+----+-----------+  |    +------+-------+     +--------------+
|foo |  ref:123 *+--+                                         
+----+-----------+       +--------------+                     
|bar |  ref:789 *+------>| Function#789 |                     
+----+-----------+       +--------------+