My JavaScript book is out! Don't miss the opportunity to upgrade your beginner or average dev skills.
Showing posts with label new. Show all posts
Showing posts with label new. Show all posts

Saturday, August 20, 2011

Overloading the in operator

In all its "sillyness", the CoffeeShit project gave me a hint about the possibilities of an overloaded in operator.

The Cross Language Ambiguity

In JavaScript, the in operator checks if a property is present where the property is the name rather than its value.

"name" in {name:"WebReflection"}; // true

However, I bet at least once in our JS programming life we have done something like this, expecting a true rather than false.

4 in [3, 4, 5]; // false
// Array [3, 4, 5] has no *index* 4


The Python Way

In Python, as example, last operation is perfectly valid!

"b" in ("a", "b", "c") #True
4 in [3, 4, 5] # True
The behavior of Python in operator is indeed more friendly in certain situations.

value in VS value.in()

What if we pollute the Object.prototype with an in method that is not enumerable and sealed? No for/in loops problems, neither cross browsers issues since if it's possible in our target environment, we do it, otherwise we don't do it ... a fair compromise?


Rules

  • if the target object is an Array, check if value is contained in the Array ( equivalent of -1 < target.indexOf(value) )

  • if the target object is an Object, check if value is contained in one of its properties ( equivalent of for/in { if(object[key] === value) return true; } ).
    I don't think nested objects should be checked as well and right now these are not ( same as native Array#indexOf ... if it's an array of arrays internal arrays values are ignored and that's how it should be for consistency reason )

  • if the target object is a typeof "string", check if value is a subset of the target ( equivalent of -1 < target.indexOf(value) ).
    The Python logic on empty string is preserved since in JavaScript "whateverStringEvenEmpty".indexOf("") is always 0

  • if the target property is a typeof "number", check if value is a divisor of the target ( as example, (3).in(15) === true since 15 can be divided by 3)
I didn't came out with other "sugarish cases" but feel free to propose some.

Compatibility

The "curious fact" is that in ES5 there is no restrictions on an IdentifierName.
This is indeed different from an Identifier, where in latter ReservedWord is not allowed.
"... bla, bla bla ..." ... right, the human friendly version of what I've just said is that obj.in, obj.class, obj.for etc etc are all accepted identifiers names.
Accordingly, to understand if the current browser is ES5 specs compliant we could do something like this:

try {
var ES5 = !!Function("[].try");
} catch(ES5) {
ES5 = !ES5;
}

alert(ES5); // true or false
Back in topic, IE9 and updated Chrome, Firefox, Webkit, or Safari are all compatible with this syntax.

New Possibilities

Do you like Ruby syntax?

// Ruby like instances creation (safe version)
Function.prototype.new = function (
anonymous, // recycled function
instance, // created instance
result // did you know if you
// use "new function"
// and "function" returns
// an object the created
// instance is lost
// and RAM/CPU polluted
// for no reason?
// don't "new" if not necessary!
) {
return function factory() {

// assign prototype
anonymous.prototype = this.prototype;

// create the instance inheriting prototype
instance = new anonymous;

// call the constructor
result = this.apply(instance, arguments);

// if constructor returned an object
return typeof result == "object" ?
// return it or return instance
// if result is null
result || instance
:
// return instance
// in all other cases
instance
;
};
}(function(){});

// example
function Person(name) {
this.name = name;
}

var me = Person.new("WebReflection");
alert([
me instanceof Person, // true
me.name === "WebReflection" // true
].join("\n"));

Details on bad usage of new a part, this is actually how I would use this method to boost up performances.

// Ruby like instances creation (fast version)
Function.prototype.new = function (anonymous, instance) {
return function factory() {
anonymous.prototype = this.prototype;
instance = new anonymous;
this.apply(instance, arguments);
return instance;
};
}(function(){});

cool?

Do Not Pollute Native Prototypes

It does not matter how cool and "how much it makes sense", it is always considered a bad practices to pollute global, native, constructors prototypes.
However, since in ES5 we have new possibilities, I would say that if everybody agrees on some specific case ... why not?
for/in loops can now be safe and some ReservedWord can be the most semantic name to represent a procedure as demonstrated in this post.
Another quick example?

// after Function.prototype.new
// after Person function declaration
Object.defineProperty(Object.prototype, "class", {
enumerable: !1,
configurable: !1,
get: function () {
return this.__proto__.constructor;
}
});

var me = Person.new("WebReflection");

// create instance out of an instance
var you = me.class.new("Developer");

alert([
you instanceof Person, // true
you.name === "Developer" // true
].join("\n"));

I can already see Prototype3000 farmework coming out with all these magic tricks in place :D
Have fun with ES5 ;)

Sunday, March 28, 2010

new Constructor VS Object.create

just a quick post about ES5 Object.create performances. While in More ES5 Friendly Patterns paragraph I have described how to use new ES5 features to create instances in a better way, I have never tested directly performances against classic ES3 pattern.

The Benchmark Logic

Pretty simple, create a new object with a "privileged property" plus an inherited one. The test prototype looks like this object:

var proto = {toString:function () {
return this.name;
}}

The assumption is that somehow the object should be able to return it's name, which is not shared via prototype.

ES3 Game

I hope I don't have to explain this piece of code:

function F(name) {
this.name = name;
}
F.prototype = proto;

To test above classical pattern, all we need is to confirm this behavior:

var o = new F("instance");
alert(String(o) === "instance");


ES5 Game

Using an updated browser, it should be possible to replicate ES3 behavior via this piece of code:

var o = Object.create(proto, {
name: {
value:"object"
}
});

Right, Object.create comes with much more power than a simple property assignment, but here we are testing a basic task just to analyze what's the outcome, right? Just to be sure about the result:

alert(String(o) === "object");


Optimized ES5 Game

What can we do to improve performances? Avoid global scope look up, the Object constructor, plus use a static/fixed property to cheat the test:

var fixed = {
name: {
value: "static"
}
};

var create = Object.create;

var o = create(proto, fixed);

// the assertion
alert(String(o) === "static");


The Benchmark

Let's put these patterns together inside a closure, execute them 100000 times, retrieving elapsed time.

setTimeout(function () {

var proto = {toString:function () {
return this.name;
}};

var fixed = {
name: {
value: "static"
}
};

function F(name) {
this.name = name;
}
F.prototype = proto;

var o;

for(var i = 100000, instance = new Date; i--;) {
o = new F("instance");
}
instance -= new Date;

for(var i = 100000, object = new Date; i--;) {
o = Object.create(proto, {
name: {
value:"object"
}
});
}
object -= new Date;

for(var create = Object.create,
i = 100000, static = new Date; i--;
) {
o = create(proto, fixed);
}
static -= new Date;

alert([instance, object, static].join("\n").replace(/-/g,"ms: "));

}, 1000);


The Result

Based on Atom N270 nad testing via Chrome 5 for devs, this is what I read in the alert:

ms: 7
ms: 2325
ms: 2218

The first result goes up to 54ms, reaching 5ms, the second one is pretty much stable while the latest one goes down 'till 1987 ms ...

Conclusion

new Constructor seems to be the best option for those cases where the initialize/init/construct method needs to somehow setup the created instance. Only if we need special Object.create features it is worth it to use it, but if we base a whole framework over Object.create, considering eventually emulations for old browsers, this framework will be inevitably slower than older code. This means that as example a classic Point class option, should still be exactly like this:

function Point(x, y, z) {
this.x = x;
this.y = y;
this.z = z;
}

or eventually like the next one, if we don't need chained methods, neither new before each call:

function Point(x, y, z) {
return {x:x, y:y, z:z};
}

by my good old AStar algorithm time, the fastest option ever!

Tuesday, March 16, 2010

Anonymous Style

When a function is to be invoked immediately, the entire invocation expression should be wrapped in parens so that it is clear that the value being produced is the result of the function and not the function itself.

I have already commented the popular JavaScript Code Convention article, but latest cited sentence is probably the only one I have never been sure about.

Why Bother

Actually, I have always found the expression:

var something = function(){

// do stuff
// return something

}(); // invoke
kinda enough to invoke inline a function expression.
Somebody argued that above style is ambiguous.
Since an inline invoke could be performed against a massive function body, the point is that we may need to scroll 'till the end of the function expression to know if it has been executed or not.
In my opinion, whenever there is a function expression, we should always check the end of this function or we'll never be sure about the assigned value.
Fair enough, even if the function could not be necessary invoked:

var something = function(){

// do stuff
// return or not

}.bind(this);
expressions are usually wrapped in any case regardless what's up at the end.

Still ... Why Bother

The most common implementation of this code convention we can find almost everywhere, included my shared code, is this one:

var something = (function(){

// do stuff
// return something

})(); // invoke

What is actually wrong with this implementation?
Let's simply imagine the function returns a function:

var something = (function(){
return function(){
return 123;
};
})();

Now, let's imagine that we would like to execute runtime the returned function, since we know that expression will return one:

var something = (function(){
return function(){
return 123;
};
})()(); // <= WTF?

I am pretty sure that ()() at the end of a runtime invoked expression, will bring us back to origins, where "we had to check 'till the end of the function", at least to understand what is going on ...
In few words, and as I have said, the scroll 'till the end of whatever function should be mandatory, if the code is not our one, and we would like to understand what this code actually does.

Non Ambiguously Speaking

If we follow Mr D. suggestion, we could say that this strategy will be rarely ambiguous.
To spot a wrap is definitively more easy than spot a potential typo, as 4 brackets could suggest:

var something = (function(){
return function(){
return 123;
};
}());
With latter snippet we can certainly say with a quick look that something refers the value returned by the invoked expression. It's wrapped, it must be an invoke rather than a function assignment, and it could be whatever value.
The instant we add other brackets, we are obviously dealing with the returned value:

var something = (function(){
return function(){
return 123;
};
}())(); // invoke the returned value

In other words we are able to split the inline invoked expression, with the rest of the logic, but still scrolling through the end!


Moreover

The usage of brackets makes the assignment superfluous:

// first case analyzed without brackets
(function(){

// do stuff

}());
In this case we are clearly creating a closure to avoid global space pollution and to perform some useful operation.
Since this is basically what we can find almost everywhere in many different libraries or piece of libraries, and since we have some shortcut to instantly reach the end of a file, why should we put the inline invoke outside the operation?

// first case analyzed without brackets
(function(){

// do stuff

})();
The sequence of )() could suggest that something happened before and somehow it constrict us to check if there are other 2 round brackets before those spotted at the end.
Furthermore, if we have an expression this is what we could write:

var something;

// other code

(something = function(){

// do stuff

})();
Again, unless we did mean that operation, maybe to avoid IE problems with named function expressions, those brackets outside the "wrap" could truly be considered ambiguous: was I trying to assign the expression result or the function itself?

something = (function(){

// do stuff
// return stuff

}());
There we have again a clear statement of what we were planning to do, isn't it?

Anonymous Assignment

We could think about some common pattern we can consider less error prone, and less ambiguous ... the first one is the classic assignment, performed for prototype properties, to avoid IE problems, or simply assign callbacks:

something = function(){};


Inline Invoke

We may agree that next one is the bets way to make an inline invoke non ambiguous:

something = (function(){}());

Same is if we are not returning anything, so that the expression will be called simply because we need a closure:

(function(){}());


Inline Constructor

This is not truly such common technique, but there is a massive difference if we use brackets or not.

var a = new (function(){
return Array;
}());
// true
alert(a instanceof Array);


var a = new function(){
return Array;
}();
// false
alert(a instanceof Array);
// a is actually the Array constructor
alert(a === Array);

The usage of new before an expression is something more suitable for ternary operator:

var o = new (typeof null !== "object" ? Object : String);

not particularly suitable for inline constructor concept.
This simply means, in my opinion, that if we meant to use the function as a Singleton, we should never put brackets around:

var Singleton = new function () {
var secret = "Singleton Baby!";
this.constructor = Object;
this.toString = function () {
return secret;
};
};

alert(Singleton);
// Singleton Baby!


As Summary

Earlier, I found the initial advice kinda redundant or superfluous, but I must admit it could make sense specially in weird cases, and this is why I have personally started to adopt it without feeling less readable at all.
Is there any other case where we could try to avoid expression ambiguity?

Thursday, May 21, 2009

google caja, what's wrong with "new" ?

In JavaScript we mainly have two type of variables:

  • primitives (string, number, boolean, null or undefined)

  • object related (Array, Object, Function, unknown for IE)


Due to this difference, a primitive string and a new String are two different worlds:

var s1 = "abc";
var s2 = new String("abc");

s1 instanceof String; // false
s2 instanceof String; // true


The nature of primitive constructor is to return a typeof constructor, but if we use new in front of the same constructor, it will obviously return an instance of that constructor.

This is the nature of javascript, summarized in this snippet:

function I1(){
return 1;
};

function I2(){};

var i1 = new I1();
var i2 = new I2();

In both cases, o1 and i2 will be respectively an instanceof I1, and I2.
In few words, if a function is caled via new, the assigned value will be an instance o the constructor itself or, if it returns an instanceof Something, the instanceof something value.

function I3(){
return new I2();
};
var iPretendsToBe3 = new I3();

iPretendsToBe3 instanceof I3; // false
iPretendsToBe3 instanceof I2; // true



The same happens with Array, Function, and Object constructors.
These kind of variables are considered objects, for the simple reason you can add runtime a property, without losing it:

var s = "abc";
var o = Object("abc"); // returns a new String

s.test = true;
o.test = true;

s.test; // undefined
o.test; // true


When we use the Object function, we will obtain an object, instanceof passed argument.
Indeed, using latest example, o instanceof String will be true.

If A Function Returns An Instance Of Something, "new" Is Redundant


While if a function returns a primitive value (string, number, boolean, undefined, unknown for IE) this value will be simply lost the moment we will use new in front of that function.

function sum(a, b){
return a + b;
};
var o = new sum();

o instanceof sum; // true

Obviously, if we call sum without the keyword "new", the function will return the sum of argument a plus argument b.

Due to this duality JavaScript functions feature, when we perform a new Array, Object, or Function, we are doing something a bit redundant, because the constructor itself will always return an instance of called constructor.

Array() instanceof Array; //true
new Array() instanceof Array; //true

Function() instanceof Function; //true
new Function() instanceof Function; //true


In the specific Function case, it is like thie scenario:

function Test(){
return function anonymous(){};
};

var f1 = Test();
var f2 = new Test();


In both cases, new or not new, the returned instance wlll be the anonymous function, which has priority over the new keyword.
Accordingly, f2 will be virtually an instanceof Test constructor between the call and the return anonymous space, something completely useless.

In my good old ActionScript memories, there were cases where the usage of Array() was not suggested because using new Array() you could have created more Arrays (I am talking about thousands of iteraction and AS1 or AS2).
Well, unless somebody demonstrate that JavaScript engines are that buggy, there is not a single reason to prefer new Function (same is for new Object and new Array) over the simple native function call.

All this post is about an interesting one opened in jQuery developer list, where at the end of the day, jQuery had to implement a common mistake/bad practice.

As summary, google-caja, please revisit some spec because this one, as example, does not make much sense :(