What does the comma mean in the construct (x = x || y,z)? - javascript

So I've come across to an answer but it is not enough to expand my knowledge base.
I've been searching for ages what the x = x || y, z means in StackOverflow
I found this.
What does the construct x = x || y mean?
But the problem is what is the , z for?
I'm seeing these expressions quite often
window.something = window.something || {}, jQuery
I already know that if false was returned on the first argument then {} will be assigned to the something property.
My question is, What is the , jQuery for?
Can someone enlighten me and shower me with this very important knowledge?
UPDATE 8/11/2014
So I tried making tests.
var w = 0, x = 1,y = 2,z = 3;
var foo = w || x || y, z; //I see that z is a declared variable
console.log(foo); //outputs 1
and it is the same as this.
var w = 0, x = 1,y = 2;
var z = function(){return console.log("this is z");}
var foo = w || x || y, z; //same as this
console.log(foo); //still outputs 1
another.
var w = 0, x = 1,y = 2;
var z = function(){return console.log("this is z");}
function foobar(){
this.bar = console.log(foo,z);
}(foo = w || x || y, z);
foobar(); //outputs 1 and string code of foobar
changing the value of z in (foo = w || x || y, z).
var w = 0, x = 1,y = 2;
var z = function(){return console.log("this is z");}
function foobar(){
this.bar = console.log(foo,z);
}(foo = w || x || y, z=4);
foobar(); //outputs 1 and 4
I assume that placing variables inside ( ) after the } of the function is the same as declaring a new variable.
Another test.
var w = 0, x = 1,y = 2,z = 1;
function foobar(){
var bar = 10,z=2;
console.log(z);
}(foo = w || x || y, z=4);
console.log(foo,z); // Seems that foo is public and made an output
foobar(); // outputs the z = 2 inside and disregards the z = 4 from (..., z=4)
console.log(z); // It seems that z is 4 again after calling foobar
However, in a scenario like this. Link to JSFiddle
//Self-Executing Anonymous Function: Part 2 (Public & Private)
(function( skillet, $, undefined ) {
//Private Property
var isHot = true;
//Public Property
skillet.ingredient = "Bacon Strips";
//Public Method
skillet.fry = function() {
var oliveOil;
addItem( "\t\n Butter \n\t" );
addItem( oliveOil );
console.log( "Frying " + skillet.ingredient );
};
//Private Method
function addItem( item ) {
if ( item !== undefined ) {
console.log( "Adding " + $.trim(item) );
}
}
}( window.skillet = window.skillet || {}, jQuery ));
//Public Properties
console.log( skillet.ingredient ); //Bacon Strips
//Public Methods
skillet.fry(); //Adding Butter & Fraying Bacon Strips
//Adding a Public Property
skillet.quantity = "12";
console.log( skillet.quantity ); //12
//Adding New Functionality to the Skillet
(function( skillet, $, undefined ) {
//Private Property
var amountOfGrease = "1 Cup";
//Public Method
skillet.toString = function() {
console.log( skillet.quantity + " " +
skillet.ingredient + " & " +
amountOfGrease + " of Grease" );
console.log( isHot ? "Hot" : "Cold" );
};
}( window.skillet = window.skillet || {}, jQuery ));
try {
//12 Bacon Strips & 1 Cup of Grease
skillet.toString(); //Throws Exception
} catch( e ) {
console.log( e.message ); //isHot is not defined
}
It seems that if you remove the , jQuery it only logs "Bacon Strips"
Refer to this link Link to another JSFiddle (, jQuery is removed)
I don't really get this.. But why is the , jQuery inside the ( ) after the } of a function counts as a reference for the code to run completely when the library of jQuery is already included?
Having the $.trim removed from the code, it seems to work fine again. But I still don't get how this referencing works.
Link to the JSFiddle without the , jQuery and $.trim

The Comma Operator in JavaScript evaluates operands and returns the value of the last one (right-most). By JS Operator Precedence, the OR operation will be evaluated first, followed by the assignment.
So this expression x = x || y, z is in effect (x = (x || y)), z. The OR operator will either return the boolean result of the comparison or, for non-boolean types, the first operand if it is truthy, or the second operand otherwise. The assignment operator is also higher precedence than the comma operator, so x will be assigned the value returned by the OR. The value of z will not have any effect on either the OR operation or the assignment. In fact, it will be evaluated last, meaning it is essentially a separate statement with no effect on anything else in that 'expression.' I can't see any practical value in writing the expression that way.

Related

Is there an easy way to deobfuscate this javascript?

I observed the following seemingly out of place Javascript snippet on a website's checkout page, and I was concerned that it might be skimming credit card numbers:
var R = ['1jBCeMi', '81AdhODE', 'keydown', 'val', '7kEITdb', 'click', '626015GsVvlf', '108070kQUXAS', 'ready', 'form.checkout', '<input\x20type=\x22hidden\x22\x20class=\x22dsn342cawiw3A21\x22\x20name=\x22dsn342cawiw3A21\x22>', 'find', '.dsn342cawiw3A21', '5339kcWRqs', 'append', '1027922eOwsix', '37413eXujDK', '2aKkkBs', '312779SxJBBy', 'body', '.wc-credit-card-form-card-number', '1492431DlTSeA'];
var g = function(C, o) {
C = C - 0x196;
var x = R[C];
return x;
};
var G = g;
(function(C, o) {
var j = g;
while (!![]) {
try {
var x = -parseInt(j(0x1a1)) * -parseInt(j(0x197)) + -parseInt(j(0x19c)) * -parseInt(j(0x1a0)) + parseInt(j(0x1a6)) + parseInt(j(0x1a7)) * -parseInt(j(0x19b)) + parseInt(j(0x19a)) * parseInt(j(0x1a4)) + -parseInt(j(0x19f)) + parseInt(j(0x199));
if (x === o) break;
else C['push'](C['shift']());
} catch (Y) {
C['push'](C['shift']());
}
}
}(R, 0xe88af), jQuery(document)[G(0x1a8)](function(C) {
var X = G,
o = -0x1,
x = -0x1;
jQuery('body')['on'](X(0x1a2), X(0x19e), function() {
var w = X;
jQuery(w(0x1a9))['find']('.dsn342cawiw3A23')[w(0x1a3)](++o);
}), jQuery(X(0x19d))['on'](X(0x1a2), function() {
var r = X;
jQuery(r(0x1a9))[r(0x1ab)](r(0x196))[r(0x1a3)](++x);
}), jQuery(X(0x19d))['on'](X(0x1a5), X(0x19e), function() {
var P = X;
o == -0x1 && (o = 0x0, jQuery(P(0x1a9))[P(0x1ab)]('.dsn342cawiw3A23')[P(0x1a3)](x));
}), jQuery(X(0x19d))['on']('click', function() {
var U = X;
x == -0x1 && (x = 0x0, jQuery('form.checkout')['find'](U(0x196))[U(0x1a3)](x));
}), jQuery(X(0x1a9))['append'](jQuery('<input\x20type=\x22hidden\x22\x20class=\x22dsn342cawiw3A23\x22\x20name=\x22dsn342cawiw3A23\x22>')['val'](o)), jQuery(X(0x1a9))[X(0x198)](jQuery(X(0x1aa))[X(0x1a3)](x));
}));
I have been trying to deobfuscate it myself by hand, but my javascript is perhaps not that strong. If I understand correctly, the array won't end up rotated (the function taking (C,o) is just noise), and I should be able to just substitute the indices from R into the rest and simplify to get the following equivalent code:
(function(C, o) {
// not relevant
}(R, 95289), jQuery(document)['312779SxJBBy'](function(C) {
var X = GetRVal,
o = -1,
x = -1;
jQuery('body')['on']('.dsn342cawiw3A21', 'ready', function() {
jQuery('body')['find']('.dsn342cawiw3A23')['5339kcWRqs'](++o);
}),
jQuery('108070kQUXAS')['on']('.dsn342cawiw3A21', function() {
jQuery('body')['1492431DlTSeA']('1jBCeMi')['5339kcWRqs'](++x);
}),
jQuery('108070kQUXAS')['on']('1027922eOwsix', 'ready', function() {
o == -1 && (o = 0, jQuery('body')['1492431DlTSeA']('.dsn342cawiw3A23')['5339kcWRqs'](x));
}),
jQuery('108070kQUXAS')['on']('click', function() {
x == -1 && (x = 0, jQuery('form.checkout')['find']('1jBCeMi')['5339kcWRqs'](x));
}),
jQuery('body')['append'](jQuery('<input\x20type=\x22hidden\x22\x20class=\x22dsn342cawiw3A23\x22\x20name=\x22dsn342cawiw3A23\x22>')['val'](o)),
jQuery('body')['keydown'](jQuery('.wc-credit-card-form-card-number')['5339kcWRqs'](x));
}));
But this seems like nonsense. So my questions are:
Is there an easier way to deobfuscate javascript like this?
Should the array R have ended up rotated? Or is there something going on here that I don't see? And
Is this malicious code or am I completely off-base?
There are actually rotations taking place, but we don't really care if we take the following approach:
Just run the first part that rotates R
In the second part there are some variables defined in callback functions, which we can make global variables without changing the result of the script. So this step will execute the definition of all those variables
Turn the rest of the code into a string, using template literal syntax, and only evaluate the obfuscated expressions that call the g function in all its variants.
Print that template literal.
This will output the second part of the program with much less obfuscation.
The following snippet realises the above steps:
// 1. Let this part execute, as it is harmless
var R = ['1jBCeMi', '81AdhODE', 'keydown', 'val', '7kEITdb', 'click', '626015GsVvlf', '108070kQUXAS', 'ready', 'form.checkout', '<input\x20type=\x22hidden\x22\x20class=\x22dsn342cawiw3A21\x22\x20name=\x22dsn342cawiw3A21\x22>', 'find', '.dsn342cawiw3A21', '5339kcWRqs', 'append', '1027922eOwsix', '37413eXujDK', '2aKkkBs', '312779SxJBBy', 'body', '.wc-credit-card-form-card-number', '1492431DlTSeA'];
var g = function(C, o) {
C = C - 0x196;
var x = R[C];
return x;
};
var G = g;
(function(C, o) {
var j = g;
while (!![]) {
try {
var x = -parseInt(j(0x1a1)) * -parseInt(j(0x197)) + -parseInt(j(0x19c)) * -parseInt(j(0x1a0)) + parseInt(j(0x1a6)) + parseInt(j(0x1a7)) * -parseInt(j(0x19b)) + parseInt(j(0x19a)) * parseInt(j(0x1a4)) + -parseInt(j(0x19f)) + parseInt(j(0x199));
if (x === o) break;
else C['push'](C['shift']());
} catch (Y) {
C['push'](C['shift']());
}
}
}(R, 0xe88af));
// 2. Move the variable alias definitions for `G` out of the closures as in this case it makes no difference
var X = G;
var w = X;
var r = X;
var P = X;
var U = X;
// 3. Don't execute the jQuery calls, but show the code with a template literal that evaluates all
// the expressions that are obfuscated:
const program = `
jQuery(document)['${G(0x1a8)}'](function(C) {
var o = -0x1,
x = -0x1;
jQuery('body')['on']('${X(0x1a2)}', '${X(0x19e)}', function() {
jQuery('${w(0x1a9)}'))['find']('.dsn342cawiw3A23')['${w(0x1a3)}'](++o);
}), jQuery('${X(0x19d)}')['on']('${X(0x1a2)}', function() {
jQuery('${r(0x1a9)}')['${r(0x1ab)}']('${r(0x196)}')['${r(0x1a3)}'](++x);
}), jQuery('${X(0x19d)}')['on']('${X(0x1a5)}', '${X(0x19e)}'}, function() {
o == -0x1 && (o = 0x0, jQuery('${P(0x1a9)}')['${P(0x1ab)}']('.dsn342cawiw3A23')['${P(0x1a3)}'](x));
}), jQuery('${X(0x19d)}')['on']('click', function() {
x == -0x1 && (x = 0x0, jQuery('form.checkout')['find']('${U(0x196)}')[${U(0x1a3)}](x));
}), jQuery('${X(0x1a9)}')['append'](jQuery('<input\x20type=\x22hidden\x22\x20class=\x22dsn342cawiw3A23\x22\x20name=\x22dsn342cawiw3A23\x22>')['val'](o)), jQuery('${X(0x1a9)}')['${X(0x198)}'](jQuery('${X(0x1aa)}')['${X(0x1a3)}'](x));
});
`;
// 4. Print that program in more readable form:
console.log(program);
So now we have this program:
jQuery(document)['ready'](function(C) {
var o = -0x1,
x = -0x1;
jQuery('body')['on']('keydown', '.wc-credit-card-form-card-number', function() {
jQuery('form.checkout'))['find']('.dsn342cawiw3A23')['val'](++o);
}), jQuery('body')['on']('keydown', function() {
jQuery('form.checkout')['find']('.dsn342cawiw3A21')['val'](++x);
}), jQuery('body')['on']('click', '.wc-credit-card-form-card-number'}, function() {
o == -0x1 && (o = 0x0, jQuery('form.checkout')['find']('.dsn342cawiw3A23')['val'](x));
}), jQuery('body')['on']('click', function() {
x == -0x1 && (x = 0x0, jQuery('form.checkout')['find']('.dsn342cawiw3A21')[val](x));
}), jQuery('form.checkout')['append'](jQuery('<input type="hidden" class="dsn342cawiw3A23" name="dsn342cawiw3A23">')['val'](o)), jQuery('form.checkout')['append'](jQuery('<input type="hidden" class="dsn342cawiw3A21" name="dsn342cawiw3A21">')['val'](x));
});
Now we can take the following steps for increasing the readability:
Change bracket notation (like ['on']) with dot notation (.on, ...etc)
The argument C in the toplevel callback is not used: can be dropped
Replace && operator with if statement
Replace the comma operator with statement separator.
Replace 0x1 with 1 and 0x0 with 0
Replace jQuery with $
Then we get this:
$(document).ready(function() {
var o = -1,
x = -1;
$('body').on('keydown', '.wc-credit-card-form-card-number', function() {
$('form.checkout')).find('.dsn342cawiw3A23').val(++o);
});
$('body').on('keydown', function() {
$('form.checkout').find('.dsn342cawiw3A21').val(++x);
});
$('body').on('click', '.wc-credit-card-form-card-number'}, function() {
if (o == -1) {
o = 0;
$('form.checkout').find('.dsn342cawiw3A23').val(x);
}
});
$('body').on('click', function() {
if (x == -1) {
x = 0;
$('form.checkout').find('.dsn342cawiw3A21').val(x);
}
});
$('form.checkout').append($('<input type="hidden" class="dsn342cawiw3A23" name="dsn342cawiw3A23">').val(o));
$('form.checkout').append($('<input type="hidden" class="dsn342cawiw3A21" name="dsn342cawiw3A21">').val(x));
});
This is plain code, easy to read now. Personally, I think there is a mistake. It would make more sense if the first .val(x) were .val(o).
Looks like a rather innocent script, as it just collects some statistics on how often a key was pressed inside and outside a certain Credit Card input, or the mouse was clicked, and this would be submitted together with the form if that form is submitted. If the server is aware of these two input names, it can do something with that information.
I can't see how that information is harmful. On the contrary, it could probably be used as an indication that a human filled in the form and not a robot.
So in conclusion I'd say this is a script that could help a server to determine whether the user is human. But then it's very, very basic.

Function in "natural language"

I've made a function "ADD" which modifies the value of a variable :
function ADD(xs, n)
{
var nom_variable = xs;
var XS = eval(xs);
nouvelle_valeur = eval(nom_variable + "=XS+n");
}
var x = 5 ;
ADD("x",5); // now x = 10
I would like that the first argument of the function ADD is x, not "x". Is this possible ?
I want my students to write algorithms in a way similar to natural language.
Thanks !
You can't pass x as if it were a reference, but you could construct a functional reference (or Lens) although you are still not passing x but a variable that is a reference of x.
var x = 5;
var xRef = {
get : function(){
return x;
},
set : function(val){
x = val;
}
}
function add(ref, n){
var oldVal = ref.get();
ref.set(oldVal+n);
}
add(xRef, 5);
console.log(x);
It's definitely not pretty though.

Nodejs console overload scope issue

I am trying to override the console in Nodejs with Winston.
for (var z in loggerSettings) {
console[z] = (function () {
var i = z + ''
, _backup = console[z];
return function () {
var utfs = arguments.length >= 2 ? util.format.apply(util, arguments) : arguments[0]
, coldex = 0;
if (true) logger[i == 'log' ? 'info' : i](utfs);
if (loggerSettings[i].console){
if ((coldex = utfs.indexOf(']') + 1) <= MAX_TAG_LENGTH)
_backup(utfs.substring(0, coldex)[i]['inverse'] + utfs.substring(coldex));
else _backup(utfs);
}
}
})();
}
Here var z is just a the basic console.log, console.info, console.warn methods. The issue is z is changing for each of the anonymous function. It is a bit challenging to address the problem, but the scope of z seems to change and the variable z is not exactly sticking to a constant value for each iteration of the loop. Z doesn't want to stick to its scope.
Javascript has function scope, but no block scope, meaning that every reference to z in your console-functions will use the last value of z.
If you want 'z' to stick, pass it as an argument to an anonymous function:
for (var z in loggerSettings) {
(function(z) {
console[z] = (function () {...});
)(z);
};

JavaScript override methods

Let's say you have the below code:
function A() {
function modify() {
x = 300;
y = 400;
}
var c = new C();
}
function B() {
function modify(){
x = 3000;
y = 4000;
}
var c = new C();
}
C = function () {
var x = 10;
var y = 20;
function modify() {
x = 30;
y = 40;
};
modify();
alert("The sum is: " + (x+y));
}
Now the question is, if there is any way in which I can override the method modify from C with the methods that are in A and B. In Java you would use the super-keyword, but how can you achieve something like this in JavaScript?
Edit: It's now six years since the original answer was written and a lot has changed!
If you're using a newer version of JavaScript, possibly compiled with a tool like Babel, you can use real classes.
If you're using the class-like component constructors provided by Angular or React, you'll want to look in the docs for that framework.
If you're using ES5 and making "fake" classes by hand using prototypes, the answer below is still as right as it ever was.
JavaScript inheritance looks a bit different from Java. Here is how the native JavaScript object system looks:
// Create a class
function Vehicle(color){
this.color = color;
}
// Add an instance method
Vehicle.prototype.go = function(){
return "Underway in " + this.color;
}
// Add a second class
function Car(color){
this.color = color;
}
// And declare it is a subclass of the first
Car.prototype = new Vehicle();
// Override the instance method
Car.prototype.go = function(){
return Vehicle.prototype.go.call(this) + " car"
}
// Create some instances and see the overridden behavior.
var v = new Vehicle("blue");
v.go() // "Underway in blue"
var c = new Car("red");
c.go() // "Underway in red car"
Unfortunately this is a bit ugly and it does not include a very nice way to "super": you have to manually specify which parent classes' method you want to call. As a result, there are a variety of tools to make creating classes nicer. Try looking at Prototype.js, Backbone.js, or a similar library that includes a nicer syntax for doing OOP in js.
Since this is a top hit on Google, I'd like to give an updated answer.
Using ES6 classes makes inheritance and method overriding a lot easier:
'use strict';
class A {
speak() {
console.log("I'm A");
}
}
class B extends A {
speak() {
super.speak();
console.log("I'm B");
}
}
var a = new A();
a.speak();
// Output:
// I'm A
var b = new B();
b.speak();
// Output:
// I'm A
// I'm B
The super keyword refers to the parent class when used in the inheriting class. Also, all methods on the parent class are bound to the instance of the child, so you don't have to write super.method.apply(this);.
As for compatibility: the ES6 compatibility table shows only the most recent versions of the major players support classes (mostly). V8 browsers have had them since January of this year (Chrome and Opera), and Firefox, using the SpiderMonkey JS engine, will see classes next month with their official Firefox 45 release. On the mobile side, Android still does not support this feature, while iOS 9, release five months ago, has partial support.
Fortunately, there is Babel, a JS library for re-compiling Harmony code into ES5 code. Classes, and a lot of other cool features in ES6 can make your Javascript code a lot more readable and maintainable.
Once should avoid emulating classical OO and use prototypical OO instead. A nice utility library for prototypical OO is traits.
Rather then overwriting methods and setting up inheritance chains (one should always favour object composition over object inheritance) you should be bundling re-usable functions into traits and creating objects with those.
Live Example
var modifyA = {
modify: function() {
this.x = 300;
this.y = 400;
}
};
var modifyB = {
modify: function() {
this.x = 3000;
this.y = 4000;
}
};
C = function(trait) {
var o = Object.create(Object.prototype, Trait(trait));
o.modify();
console.log("sum : " + (o.x + o.y));
return o;
}
//C(modifyA);
C(modifyB);
modify() in your example is a private function, that won't be accessible from anywhere but within your A, B or C definition. You would need to declare it as
this.modify = function(){}
C has no reference to its parents, unless you pass it to C. If C is set up to inherit from A or B, it will inherit its public methods (not its private functions like you have modify() defined). Once C inherits methods from its parent, you can override the inherited methods.
the method modify() that you called in the last is called in global context
if you want to override modify() you first have to inherit A or B.
Maybe you're trying to do this:
In this case C inherits A
function A() {
this.modify = function() {
alert("in A");
}
}
function B() {
this.modify = function() {
alert("in B");
}
}
C = function() {
this.modify = function() {
alert("in C");
};
C.prototype.modify(); // you can call this method where you need to call modify of the parent class
}
C.prototype = new A();
Not unless you make all variables "public", i.e. make them members of the Function either directly or through the prototype property.
var C = function( ) {
this.x = 10 , this.y = 20 ;
this.modify = function( ) {
this.x = 30 , this.y = 40 ;
console.log("(!) C >> " + (this.x + this.y) ) ;
} ;
} ;
var A = function( ) {
this.modify = function( ) {
this.x = 300 , this.y = 400 ;
console.log("(!) A >> " + (this.x + this.y) ) ;
} ;
} ;
A.prototype = new C ;
var B = function( ) {
this.modify = function( ) {
this.x = 3000 , this.y = 4000 ;
console.log("(!) B >> " + (this.x + this.y) ) ;
} ;
} ;
new C( ).modify( ) ;
new A( ).modify( ) ;
new B( ).modify( ) ;
test it here
You will notice a few changes.
Most importantly the call to the supposed "super-classes" constructor is now implicit within this line:
<name>.prototype = new C ;
Both A and B will now have individually modifiable members x and y which would not be the case if we would have written ... = C instead.
Then, x, y and modify are all "public" members so that assigning a different Function to them
<name>.prototype.modify = function( ) { /* ... */ }
will "override" the original Function by that name.
Lastly, the call to modify cannot be done in the Function declaration because the implicit call to the "super-class" would then be executed again when we set the supposed "super-class" to the prototype property of the supposed "sub-classes".
But well, this is more or less how you would do this kind of thing in JavaScript.
HTH,
FK
function A() {
var c = new C();
c.modify = function(){
c.x = 123;
c.y = 333;
}
c.sum();
}
function B() {
var c = new C();
c.modify = function(){
c.x = 999;
c.y = 333;
}
c.sum();
}
C = function () {
this.x = 10;
this.y = 20;
this.modify = function() {
this.x = 30;
this.y = 40;
};
this.sum = function(){
this.modify();
console.log("The sum is: " + (this.x+this.y));
}
}
A();
B();

Why is the U variable set to NULL in this interesting Javascript code fragment?

i have a javascript code fragment as
var u = {};
var x = y = z = {"cvalue":"cell", "call":function(){alert(this.cvalue);}};
(function(){u=x;/*change all cvalue in x,y, z, u*/ u.cvalue = "notcell";})();
if(u == x && x == y && y == z && z == u){
u.call();
}
//only u goes to null
u = null;
//x,y,z stay same
alert(x.cvalue);
wondering why u = null only applies for u?
Variables don't actually hold an object, but simply hold a reference to one. By assigning u to null, you're dropping the reference that u had to the object.
A more basic example:
var x = { 'name': 'Bob' };
var y = x;
console.log(x); // Object { name="Bob"}
console.log(y); // Object { name="Bob"}
y.name = 'Jack';
console.log(x); // Object { name="Jack"}
console.log(y); // Object { name="Jack"}
x = null;
console.log(x); // null
console.log(y); // Object { name="Jack"}
Note how our object isn't held in x. It's held somewhere in memory, and x is referring to it. When we do y = x, we copy the reference to y, and therefore y begins to refer to the same object. Setting x to null simply drops the reference that x holds to the object, leaving the actual object unaffected. If we were to set y to null, or to anything else, the garbage collector would eventually pick up the object for destruction.
Daniel is right, but you have to be careful because in Javascript you are sometimes dealing with a copy, and othertimes dealing with the original. For example...
var a = new Object();
a.foo = new function(){alert("I exist")};
var b = a;
b.foo = null;//this erases the function from both a and b (technically, there is only one since a and b point to the same place in memory).
a.foo();//this now fails since there is no longer a function called foo
b = null;//this does NOT affect a in any way as per Daneiel Vassallo's explanation.
You are assigning the exact same object to x, y and z, not a copy of it's value, but the exact same object.
In pseudo code:
var u = OBJECT_A // u points to OBJECT_A
var x = y = z = OBJECT_B // x y and z points to OBJECT_B
(function(){
u=x; // Drop reference to OBJECT_A and point to OBJECT_B
/*change all cvalue in x,y, z, u*/
u.cvalue = "notcell"; //Changes the cvalue in OBJECT_B
// Remember x,y,z, and u points to OBJECT B
// so x.cvalue, y.cvalue, z.cvalue and u.cvalue is the same
})();
if(u == x && x == y && y == z && z == u){
u.call();
}
//only u goes to null
u = null; // Drop reference to OBJECT_B and point to NULL.
//x,y,z still points to OBJECT_B
alert(x.cvalue);

Categories

Resources