Difference between undefined object assignment and deletion

I read "JavaScript Ninja Secrets" and came across an encoding 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) working fine, I understand that samurai still has a link to the function referenced by ninja.yell , which delete deleted.

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

Can someone explain what is happening under the hood?

I thought that if you assign ninja be undefined , a new link will be created and linked to ninja , the original link still exists, and since samurai still has a link to this function, garbage collection will not come and will delete it in memory.

+5
source share
4 answers

I checked @mrid and @Amadan's answers and thought for a bit, I think I understood this and came up with a simpler answer, and my explanation in my question is not entirely true.

If I uncomment the first commented line,

 var ninja = {}; 

I assign a ninja to an empty object, and therefore I try to run "samurai.yell (4);", I get an error. The reason is that the samurai is trying to find the ninja through his "chain of visibility" (that is, some closing magic that she finds, but when she tries to find if the ninja has the yell property, it disappeared, so the error is. Although the samurai still contains a link to this anonymous function (which implies that it can still run this function), when this anonymous function tries to run ninja.yell() , it will no longer be able to find it, therefore an error.

A way to fix this, of course, use this ,

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

Another way is to use the function name of the function,

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

And everything should work.

If I uncomment the second commented line,

 delete ninja; 

I actually do nothing. delete is intended only to β€œdelete” the properties of an object (you can never delete anything in Javascript, garbage handlers), it returns true if the operation was successful, otherwise false. Therefore, "delete" does not work on ninja , so simply speaking, I am not doing anything extra for ninja when I uncomment "delete ninja;", it still works as usual.

Therefore, you can forget everything that I said about the "link" and "delete" in my question, they are not relevant and do not correspond to reality.

0
source

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 called ninja

next line samurai.yell(4); will fail because ninja has been overridden and the new object has no function called yell associated with it.

Explanation:

At the beginning of ninja there is

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

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

When you change the value to

 ninja = {}; 

The old value (together with the function) is erased and overwritten with the new value.

Therefore when you call

 samurai.yell(4); 

He goes to { yell: ninja.yell }; , and since the new ninja does not have a yell function, it throws an error

+3
source

As I said in the comments, 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 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 
+3
source

Yes, you got it right, but the real reason for this is the GC mechanics.

They pass a link to the function itself, ninja.yell. This is due to the garbage collection mechanism - until all links are saved, this function will not be collected.

In this particular case, we grab the link to ninja.yell , and even if we delete the object that originally contains this function, it will not be garbage collection.

Basically, this behavior is undesirable, so people usually shun the delete .

0
source

Source: https://habr.com/ru/post/1260634/


All Articles