Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Difference between assigning an object to undefined and delete

I was reading Secrets of the JavaScript Ninja and came across a coding example:

var ninja = {
    yell: function(n){
        return n > 0 ? ninja.yell(n-1) + "a" : "hiy";
    }
};

var samurai = { yell: ninja.yell };
//var ninja = {};
//delete ninja;
samurai.yell(4);

If I uncomment the second commented line, samurai.yell(4) runs fine, I understand it as samurai still has its reference to the function originally referenced by ninja.yell, which delete removed.

However, if I run the first commented line instead, samurai.yell(4) will give an error.

Can someone explain what's happening under the hood?

I thought if you assign ninja to be undefined, a new reference will be created and linked to ninja, the original reference is still there, and since samurai still has a reference to the function, garbage collection won't come along and delete it in memory.

like image 846
kevguy Avatar asked Dec 01 '16 10:12

kevguy


2 Answers

When you write

var ninja = {
yell: function(n){
    return n > 0 ? ninja.yell(n-1) + "a" : "hiy";
}
};

var samurai = { yell: ninja.yell };
var ninja = {};
//delete ninja;
samurai.yell(4);

var ninja = {}; will declare a variable named ninja

the next line samurai.yell(4); will throw an error since ninja has been re-defined and the new object does not have any function named yell associated with it.

Explanation :

In the beginning, ninja is

var ninja = {
    yell: function(n){
        return n > 0 ? ninja.yell(n-1) + "a" : "hiy";
    }
};

Here ninja has a function yell inside it which can be called.

When you change it's value to

ninja = {};

The old value ( along with the function ) gets erased and overwritten with the new value.

Therefore, when you call

samurai.yell(4);

It goes to { yell: ninja.yell }; and since the new ninja doesn't have yell function, it throws an error

like image 163
mrid Avatar answered Nov 14 '22 22:11

mrid


As I said in comments, it's all about how closures work:

var bar = 1;
var foo = function() { console.log(bar); } // closes over `bar`
foo(); // closed-over `bar` reference: 1
bar = 2;
foo(); // closed-over `bar` reference reflects the update: 2
delete bar;
foo(); // closed-over `bar` still references the same location,
       // even when current context no longer has it

You don't often see examples with delete, but it is this very mechanism that makes them useful as a replacement for private variables:

var foo = (function() {
  var bar = 1;
  return function() {
    console.log(bar);
  };
})();

foo();            // closed-over `bar`: 1 - even though:
console.log(bar); // Uncaught ReferenceError, as
                  // `bar` is not available in local context
like image 24
Amadan Avatar answered Nov 14 '22 23:11

Amadan