A use for javascript's weird object behavior
Matthew Martin
12/03/2014 08:40:00 AM
Tweetable
Here's one use for aliases. Suppose we have a function inside a class like this
function myClass(){
this.property1;
function setProperty1(){
this.property1="some value";
}
}
var myObject=new myClass();
The aim in the code above is to create an object called myObject with a property called myObject.property1, that is assigned the value "some value" value by the private method setProperty1 inside the class, which is something that might arise in real life if, for example, you want the class to depend on user input in some way. The problem is that the above code doesn't work. The this keyword tells the program to operate on the immediate "owner" of the object. Thus, this.property1;
function setProperty1(){
this.property1="some value";
}
}
var myObject=new myClass();
function myClass(){
this.property1;
}
var myObject=new myClass();
creates an empty property attached to myObject while this.property1;
}
var myObject=new myClass();
function setProperty1(){
this.property1="some value";
}
attempts to attach a property to the method setProperty1() inside of myObject, not to myObject itself. this.property1="some value";
}
The way out of this is to use an alias, like so:
function myClass(){
this.property1;
var that=this;
function setProperty1(){
that.property1="some value";
}
}
var myObject=new myClass();
Inside of the class but outside the method in the class, we've created a private variable called that (my choice of name is convention, but the name can be anything you choose--that is not a javascript keyword), and set it equal to this, which is the javascript keyword telling the computer to operate on the object's owner, myObject. Thus when we call the constructor it creates a private variable inside the object and sets it equal to the object itself--but remember, javascript does not copy objects, so this private variable merely points to myObject. The result is that the method inside myObject now understands that it is supposed to set myObject.property1 and not myObject.setProperty1().property1.this.property1;
var that=this;
function setProperty1(){
that.property1="some value";
}
}
var myObject=new myClass();
So, there you go. This weird fact about javascript has at least one use. Still, seems like this could be designed better.
In Java you would use Object.clone() to make a proper copy, in python you would use copy.copy(), or copy.deepcopy() if you want all sub-objects to be copied as well.
The reason it does shallow copying and copying of references by default is not semantic: it's about performance. Objects can get very big, you don't want to copy them if just handing out a reference to the same object will do.
These days, having many references to a thing and not having a clear image of when it can change, is recognized as a common source of bugs. Functional languages like Haskell try to do away with mutability entirely, and you get a more math-like way of thinking of things, where if a = 1 it won't ever later be 2.
I guess that was the goal of the R designers too, to make things less surprising for people from a math/statistics background. But the way they did it is pretty unusual.