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

Tuesday, August 21, 2012

A Safer JS Environment

Oh well, apparently I wasn't joking here and I went even further ... so here I am with a weird hack you probably never thought about before ;)

A Globally Frozen Environment

Have you ever thought about this in the global context?

Object.freeze(this);

Apparently not even browser vendors such Chrome or Safari since this condition, today, is always false: Object.isFrozen(Object.freeze(this));, and even if it works as expected after freezing.
Firefox and node.js got it right while Opera Next throws an error .. but latter a part ...

Stop Any Global Pollution

That's right, if you freeze the window or global object, guess what happens here:

Object.freeze(this);

var a = 123;
alert(this.a); // undefined
alert(a); // error: a is not defined

We cannot even by mistake create a global variable ... there's no lint that could miss that.

Moreover, if you are worried about malicious code able to change some global function or constructor, you can stop worrying with proposed freeze call: that will break instantly and any manual quick test will instantly fail rather than keep going.

What About Namespaces

Well, if global namespaces, this hack will prevent the creation of any namespace.
However, we are in RequireJS and AMD module loader era where a module is imported inline through require() or inside a callback with AMD. The only important thing, is that at least the require function must be defined before this hack is performed or even that one cannot be used.

Once we have require() things are that easy, you create your own private scope and you do your own stuff in that scope being still sure that you won't pollute the global scope plus you won't be scared about other scripts ... you have your virtual sandbox

Object.freeze(this) && function (global) {
// here all local variables you want
var
fs = require("fs"),
mymodule = require("./mymodule")
;
// do the hack you want
}(this);

// AMD style
require(["fs", "./mymodule"], function (fs, mymodule) {
// already in a closure so ...
// do the hack you want
});


Too Restrictive? Object.prototype Then!

At least we can think about freezing the Object.prototype as the very first script in any webpage so the nightmare JSLint is talking about, the slow, boring, and probably already not necessary since no recent library is extending the Object.prototype since ages, hasOwnProperty() check, does not need to be in every bloody for/in 'cause you know what? Nobody can change, add, pollute, the global Object.prototype!

Object.freeze(Object.prototype);

// everything else after

for (var key in {}) {
// screw {}.hasOwnProperty, IT'S NOT NEEDED!
}



How About Both

If you are the only owner of your scripts, if you load node.js modules, by default with the ability to screw things up in the global context, or if you use AMD where global pollution should never be necessary, you might decide that this script is your best friend.

try {
// (C) WebReflection - Mit Style License
!function(global, Object){"use strict";
// buggy in both Chrome and Safari
// always false
if (!Object.isFrozen(global)) {
var freeze = Object.freeze;
Object.getOwnPropertyNames(
global
).forEach(function (prop) {
var tmp = global[prop];
switch(typeof tmp) {
case "function":
tmp = tmp.prototype;
case "object":
if (tmp) {
// console might not be freezable
// same is for String.prototype
// if applied twice and only in Safari
try {freeze(tmp)} catch(o_O) {}
}
break;
}
});
// Opera Next has some problem here
try {freeze(global)} catch(o_O) {}
}
}(this, Object);
} catch(o_O) { /* still in IE < 9 browser ... */ }

As summary, let's write down benefits of this technique:
  1. global context is free from pollution, no missed var will work anymore so it's instantly fixed before the eventual usage of a linter
  2. for/in loops could have a massive boost over object literals since nobody can possibly change the Object.prototype
  3. ES5 enabled browsers, which means all current browsers for desktop and mobile except desktop IE < 9, will prevent greedy or outdated scripts, to make the environment less secure
  4. nobody can redefine eval or Function, used sometimes for reasons but the most insecure global functions we have in JS
  5. we are forced to think in modules, 'cause there won't be any other way to load external script or dependency
  6. the only script that needs, eventually, to be loaded, will be the require() one, which means faster bootstrap by default thanks to smaller amount of synchronous bytes required to initialized our project
  7. in node.js, we are forced to write in a function even the main program, rather than polluting global object with stuff that might disturb required modules (which is true for all require/AMD based solutions too)

What do you think?

Wednesday, November 30, 2011

Array extras and Objects

When Array extras landed in JavaScript 1.6 I had, probably together with other developers, one of those HOORRAYYY moment ...
What many libraries and frameworks out there still implement, is this sort of universal each method that supposes to be compatible with both Arrays and Objects.

A Bit Messed Up

What I have never liked that much about these each methods is that we have to know in advance in any case if the object we are passing is an Array, an ArrayLike one, or an Object.
In latter case, the callback passed as second argument will receive as second argument the key, and not the index, which simply means we cannot trust a generic callback unless this does not check per each iterated item the second argument type, or unless we don't care at all about the second argument.
In any case I always found this a bad design. If we think about events, as example, it's totally natural to expect a single argument as event object and then we can act accordingly.
This let us reuse callbacks for similar purpose and maintain a DRY code.

Need For An Object#forEach

All implementation of each, and as far as I know with the only exception of jQuery which makes things even more complicated since we generally have to completely ignore the first argument in this case, have some natural confusion inside the method.
If you take the underscore.js library, as example, you will note that there are two aliases for the each method, each itself and forEach, so it's more than clear for me that JS developers are clearly missing an Array#forEach like method in order to iterate with objects, rather than lists.
It must be also underlined that all these methods are somehow error prone: what if the object we are passing has a length property that does not necessary mean it points to the length of items stored via index as if it was an Array?
You may consider this an edge case, or an anti pattern, then you have to remember that functions in JavaScript are first class objects.
Probably all these methods will nicely fail indeed with functions, passed as objects, whenever you decide that your function can be used as object too.

var whyNot = function (obj) {
/* marvelous stuff here */
this.calls++;
return this.doStuff(obj);
};
whyNot.calls = 0;
whyNot.doStuff = function (obj) {
/* kick-ass method */
};

// the unexpected but allowed
whyNot = whyNot.bind(whyNot);

whyNot.length; // 1
whyNot[0]; // undefined

By design, the length of any function in JavaScript is read-only and means nothing, in therms of Array iteration, it simply means the number of arguments the function defined during its declaration/definition as expression.

WTF

Whenever above example makes sense or not, I am pros patterns exploration and when a common method is not compatible with all scenarios, I simply think something went wrong or is missing in the language.
Thanks gosh JS is freaking flexible and with ES5 we can define some prototype without affecting for( in ) loops but hopefully simplifying our daily basis stuff.
Remember? With underscore or others we still have to know in advance if the passed object is an Array, an ArrayLike, or a generic object ... so what would stop us to simply chose accordingly?

// Array or ArrayLike
[].forEach.call(genericArrayLike, callbackForArrays);

// generic object to iterate
{}.forEach.call(object, callbackForObjects);

An explicit choice in above case is the fastest and most reliable way we have to do things properly. A DOM collection, as well as any array or arrayLike object will use the native forEach, but we can still recycle callbacks designed to deal with value, key and objects, rather than value, index, and this is the little experiment:

Object extras

The concept of each callback is exactly the same of original, native, Array callbacks, except things are based on native functions available in all ES5 compatible desktop and basically all mobile browsers, and easy to shim with all others too old to deal with JS 1.6 or higher.



Here a couple of examples:

var o = {a:"a", b:"b", c:""};

// know if all values are strings
o.every(function (value, key, object) {
return typeof value == "string";
}); // true

// filter by content, no empty strings
var filtered = o.filter(function (value, key, object) {
return value.length;
}); // {a:"a",b:"b"} // original object preserved

// loop through all values (plus checks)
o.forEach(function (value, key, object) {
object === o; // true
this === o; // true
if (key.charAt(0) != "_") {
doSomethingWithThisValue(value);
}
}, o); // NOTE: all these methods respect Array extras signatures

// map a new object
var mapped = o.map(function (value, key, object) {
return value + 1;
}); // {a:"a1",b:"b1"} // original object preserved

// know if a value contains "a"
o.some(function (value, key, object) {
return value === "a";
}); // true

The reason reduce and reduceRight are not in the list is simple: which one would be the key to preserve, the first of the list? There is no such thing as "predefined for/in order" in JavaScript plus these methods are more Array related so out of this experiment.

As Summary

Once minified and minzipped the gist weights about 296 bytes which is ridiculous size compared with any application we are dealing with on daily basis.
Specially forEach, but probably others too, may become extremely handy and ... of course, using the Object.keys method internally, this is gonna be compatible with Arrays too but hey, the whole point was to make a clear distinction ;)


[edited]

The Misleading Signature

I don't know how many times I have spoken with jQuery developers, just because they are common, convinced that native Array#forEach was accepting the value as second argument.
I always considered inverted signatures, whatever API it is, bad for both performances, no possibility to fallback into some native method, and learning curve, where new comers learn than a generic each method must have the index as first argument.
Bear in mind whenever we loop we are most likely interested into the value of that index or key, so this value should be the first, and if you need the only one, argument passed through the procedure.
A completely ignored first argument is, once again and in my opinion, a bad design for an API: stuck without native power, teaching arguments order is not relevant.
Well, specially latter point is true if we have named arguments, but in JS nothing have been planned so far, and in ES6 the way we gonna name arguments is still under discussion.

Have fun with JS

Wednesday, October 05, 2011

bind, apply, and call trap

quick one out of ECMAScript ml

var
// used to trap function calls via bind
invoke = Function.call,
// normal use cases
bind = invoke.bind(invoke.bind),
apply = bind(invoke, invoke.apply),
call = bind(invoke, invoke)
;


What Is It

This is a way to trap native functions method in a handy way. Used in a private scope, it can address these methods once so that we can rely nobody can possibly change them out there for some script injection and only if we are sure the script has been loaded at the very beginning.

How To Use Them

Here few examples:

// secure hasOwnProperty
var hasOwnProperty = bind(invoke, {}.hasOwnProperty);
// later on
hasOwnProperty({key:1}, "key"); // true
hasOwnProperty({}, "key"); // false

// direct slice
var slice = bind(invoke, [].slice);
slice([1,2,3], 1); // 2,3
slice(arguments); // array

// direct call
call([].slice, [1,2,3], 1); // 2,3
// direct apply
apply([].slice, [1,2,3], [1]); // 2,3

// bound method
var o = {name:"WebReflection"};
o.getName = bind(
// the generic method
function () {
return this.name;
},
// the object
o
);
o.getName(); // WebReflection
That's pretty much it, except if we don't trust native Function.prototype, we should not trust anything else as well so maybe it's good to use these shortcuts just because they are handy ;)

Monday, December 27, 2010

ES5 Common Design Patterns Examples - Part 1


// Abstract Factory
/*
({}).createInstance()

(function (a, b, c) {
this.sum = a + b + c;
}).createInstance([1, 2, 3])

*/
Object.defineProperty(
// (C) WebReflection - Mit Style License
Object.prototype,
"createInstance",
{
value: (function (create) {
return function createInstance(args) {
var
self = this,
isFunction = typeof self == "function",
obj = create(isFunction ? self.prototype : self)
;
isFunction && args != null && self.apply(obj, args);
return obj;
};
}(Object.create))
}
);

// Abstract Builder
/*
var person = Object.builder({
setup: function (name) {
this.create();
this.instance.name = name;
}
});
person.setup("WebReflection");
alert(person.instance.name);
person.create();
person.instance.name = "Andrea";
alert(person.instance.name);
*/
Object.defineProperty(
// (C) WebReflection - Mit Style License
Function.prototype,
"builder",
{
value: function (methods) {
var
$create = Object.create,
self = this,
proto = self.prototype,
obj
;
return $create(methods, {
instance: {
get: function get() {
return obj;
}
},
create: {
value: function create() {
obj = $create(proto);
self.apply(obj, arguments);
}
}
});
}
}
);

// Multiton + Singleton pattern
// (via lazy initialization)
/*
function Car(){}
var car = Car.getInstance();
alert(car === Car.getInstance());
alert(car !== Car.getInstance("bmw"));
alert(Car.getInstance("bmw") === Car.getInstance("bmw"));
*/
Object.defineProperty(
// (C) WebReflection - Mit Style License
Function.prototype,
"getInstance",
{
value: function (key) {
var
create = Object.create,
instances = {},
self = this,
proto = self.prototype,
instance
;
Object.defineProperty(
self,
"getInstance",
{
value: function getInstance(key) {
return key == null ?
instance || (instance = create(proto)) :
instances.hasOwnProperty(key) ?
instances[key] :
instances[key] = create(proto)
;
}
}
);
return self.getInstance(key);
}
}
);

// Prototype
/*
var definition = {some:"thing"};
var inherited = Object.create(definition);
*/
Object.create;

// Abstract Adapter
/*
function Person() {}
Person.prototype.setName = function setName(_name) {
this._name = _name;
};

var getter = {
toString: function () {
return this._name;
}
};

var me = {};
me.adapt(Person);
me.setName("WebReflection");
me.adapt(getter);
alert(me);
*/
Object.defineProperty(
// (C) WebReflection - Mit Style License
Object.prototype,
"adapt",
{
value: (function (proto) {
return proto in {} ?
function adapt(Class) {
this[proto] = typeof Class == "function" ? Class.prototype : Class;
} :
function adapt(Class) {
var self = this;
typeof Class == "function" && Class = Class.prototype;
for (proto in Class)
self.hasOwnProperty(proto) || (self[proto] = Class[proto])
;
}
;
}("__proto__"))
}
);

// Abstract Composite
/*
function AddToBody(value) {
this.value = value;
}
AddToBody.prototype.value = "";
AddToBody.prototype.exec = function () {
document.body.appendChild(
document.createElement("p")
).innerHTML = this.value;
};

var many = AddToBody.composite();
many.push(
new AddToBody("this"),
new AddToBody("is"),
new AddToBody("a"),
new AddToBody("test")
);

this.onload = function () {
many.exec();
alert(many.value);
many.value = "everybody like this";
many.exec();
alert(many.value);
};
*/
Object.defineProperty(
// (C) WebReflection - Mit Style License
Function.prototype,
"composite",
{
value: (function (defineProperty) {
return function composite() {
function get(key) {
function retrieve(item) {
return item[key];
}
return function get() {
return map.call(this, retrieve);
};
}
function set(key) {
function assign(item) {
item[key] = this;
}
return function set(value) {
forEach.call(this, assign, value);
};
}
function wrap(method) {
function apply(item) {
method.apply(item, this);
}
return function wrap() {
forEach.call(this, apply, arguments);
};
}
var
composite = [],
forEach = composite.forEach,
map = composite.map,
proto = this.prototype,
key, value
;
for (key in proto) {
if (typeof(value = proto[key]) == "function") {
composite[key] = wrap(value);
} else {
defineProperty(
composite,
key,
{
get: get(key),
set: set(key)
}
);
}
}
return composite;
};
}(Object.defineProperty))
}
);

// Observer/Listener
/*
function hello(e) {
alert(e.type);
}
var obj = new Listener;
obj.addEvent("hello", hello);
obj.addEvent("hello", hello);
obj.fireEvent("hello");
obj.fireEvent({type:"hello"});
obj.removeEvent("hello", hello);
obj.fireEvent({type:"hello"});
*/
var Listener = (function () {
// (C) WebReflection - Mit Style License
function Listener() {
handler.value = {};
defineProperty(this, "_handler", handler);
}
function fire(callback) {
callback.call(this.target, this);
}
var
proto = Listener.prototype
defineProperty = Object.defineProperty,
handler = {
value: proto
},
empty = []
;
Object.defineProperties(
Listener.prototype,
{
addEvent: {
value: function addEvent(type, callback) {
var stack = this._handler[type] || (this._handler[type] = []);
stack.indexOf(callback) < 0 && stack.push(callback);
}
},
removeEvent: {
value: function removeEvent(type, callback) {
var
stack = this._handler[type] || empty,
i = stack.indexOf(callback)
;
-1 < i && stack.splice(i, 1);
}
},
fireEvent: {
value: function fireEvent(e) {
typeof e == "string" && (e = {type: e});
e.target = this;
(this._handler[e.type] || empty).forEach(fire, e);
}
}
}
);
return Listener;
}());

Tuesday, July 27, 2010

Constructorification

... he he, I know the title could not be worst, but after my last post about Arrayfication I have thought: "... hey, the Thing.ify(object) could be more than handy in many occasions such mixins and duck typing ...".

So, let me introduce the Function.prototype method that nobody will ever use:

Function.prototype.ify = function (o) {
for (var
self = this,
p = self.prototype,
// find a fucking way to implement this in ES3
// ... uh wait, there's no way to implement
// this in ES3 ...
// https://bugzilla.mozilla.org/show_bug.cgi?id=518663
m = Object.getOwnPropertyNames(p),
i = m.length, n; i--;
) {
// methods only
m[i] = typeof p[n = m[i]] == "function" ?
"o." + n + "=p." + n + ";" : ""
;
}
m.push("return o");
return (self.ify = Function("p",
"return function " +
(self.name || "anonymous") + "fy(o){" +
m.join("") +
"}"
)(p))(o);
};

Since the function requires a Object.getOwnPropertyNames call for its prototype in order to be able to inject it's properties and methods in whatever object, the ify method is lazily assigned.
This code makes "Function.ification" easy so that precedent post could be summarized via:

Array.ify(
document.getElementsByTagName("*")
).forEach(function (node) {
// do stuff with node
});

and be performed at light speed every other time while it won't cost at all until it's performed on whatever constructor the first time only.

Well, at least the technique may result interesting, unfortunately without ES5 it's not possible to reproduce the same behavior without knowing in advance all possible keys part of the native prototype (it's possible for user defined ones tho)

Array.prototype.slice VS Arrayfication

One of the most common operations performed on daily basis directly or indirectly via frameworks and libraries is Array.prototype.slice calls over non Array elements such HTMLCollection, NodeList, and Arguments.

Why We Perform Such Operation


The Function.prototype.apply works only with object created through the [[Class]] Array or Arguments.
In latter case we may like to avoid ES3 arguments and named arguments mess when dealing with indexes.
Finally, in most of the case we would like to perform Array operations over ArrayLike objects to filer, map, splice, change, modify, etc etc ...

The Slice Cost


Let's perform over an ArrayLike object of length 2000, 2000 slice calls (change the length if you have such powerful machine):

// create the ArrayLike object
for(var arguments = {length:2000}, i = 0; i < 2000; ++i)
arguments[i] = i;
;

// define the bench function
function testSlice(arguments) {
var t = new Date;
for (var slice = Array.prototype.slice, i = 0, length = arguments.length; i < length; ++i)
slice.call(arguments);
;
return new Date - t;
}

// test it
alert(testSlice(arguments));

The average time in my Atom N270 based Netbook is 1750 ms, and numbers are not that unreasonable.
While a list of 2000 generic values may be not that common, the number of slice.call may be definitively more than 2000 during an application life cycle. All this wasted time to simply transform a generic list into an Array? And maybe just to loop and re-loop over it to filter or change values and indexes?

Alternative One: __proto__


If we modify the __proto__ property of whatever object and in almost all browsers (not IE, of course), we can somehow "promote" the current object to Array, except for the [[Class]] that will still be the generic Object, or Arguments.
The undesired side effect is that the modified object won't find anymore in its prototype its original methods, so we can define this technique really greedy.
But what about performances?

// function to test
function testProto(arguments) {
var t = new Date;
for (var proto = Array.prototype, i = 0, length = arguments.length; i < length; ++i)
arguments.__proto__ = proto;
;
return new Date - t;
}

// the result using precedent arguments object
alert(testProto(arguments));

The average elapsed time in this case is 40 ms but we have to remember is that we are not converting the object into an Array instance, we are simply overwriting it's inherited properties and methods with those part of the Array.prototype object.
This means that push, unshift, splice, forEach, or other operations, will be accessible directly through the object (e.g. arguments.forEach( ... ))
If these methods are the reason we would like to slice the generic object, this solution is definitively preferred.

Alternative Two: Arrayfication


To avoid the undesired side effect obtained via __proto__ assignment, the removal of inherited methods, we may consider to use call or apply directly via Array.prototype.
The imminent side effect of this technique is that potentially every function may like to use one of the Array prototype methods against the same object which is always passed by reference.
A simple solution could be the one to attach directly a method to this object, so that every part of the application will be able to use, as example, a forEach call for this object, without accessing every time the Array.prototype.forEach method.

arguments.forEach = Array.prototype.forEach;
// now use forEach wherever we need
// with arguments object

Since every function may like to use one or more Array methods, how about creating a function able to attach all of them in one shot?

Array.fy = (function () {
// (C) WebReflection - Mit Style License
for (var
m = [
"pop", "push", "reverse", "shift", "sort", "splice", "unshift",
"concat", "join", "slice", "indexOf", "lastIndexOf",
"filter", "forEach", "every", "map", "some", "reduce", "reduceRight"
],
i = m.length; i--;
) {
m[i] = "o." + m[i] + "=p." + m[i];
}
m.push("return o");
return Function("p",
"return function Arrayfy(o){" + m.join(";") + "}"
)(Array.prototype);
}());

With a single call we can attach all current available Array.prototype methods once without getting rid of current inherited properties or methods.
Let's see how much does a call cost:

// test function for Array.fy
function testArrayfy(arguments) {
var t = new Date;
for (var fy = Array.fy, i = 0, length = arguments.length; i < length; ++i)
fy(arguments);
;
return new Date - t;
}

// bench
alert(testArrayfy(arguments));

The average elapsed time for this operation is 3 ms.
After a single call we can consider the generic object an Array duck, preserving its inheritance.
The greedy aspect is about possible overwrites, but I have personally never called a method forEach if this is not exactly representing the Array.forEach method.

Arrayfied Operations


The last benchmark we can do is about common Array operations over our Arrayfied object.
The first consideration to do is that slice, as every other Array operation, seems to be extremely optimized for real Array objects.
In few words if we need to transform because we need many calls to forEach, filter, map, slice, etc, the transformation via slice is probably what we are looking for.
But if we need a generic loop over a generic callback and just few times, Array.fy proposal is probably the most indicated one. Here some extra test:

// slice plus a forEach operation
function testSliceEach(arguments) {
var t = new Date;
for (var slice = Array.prototype.slice, fn = function() {}, i = 0, length = arguments.length; i < length; ++i)
slice.call(arguments).forEach(fn);
;
return new Date - t;
}

// just forEach through Arrayfied object
function testArrayfied(arguments) {
var t = new Date;
Array.fy(arguments);
for (var fn = function() {}, i = 0, length = arguments.length; i < length; ++i)
arguments.forEach(fn);
;
return new Date - t;
}

// just slice through Arrayfied object
function testArrayfiedSliced(arguments) {
var t = new Date;
Array.fy(arguments);
for (var fn = function() {}, i = 0, length = arguments.length; i < length; ++i)
arguments.slice();
;
return new Date - t;
}

// bench

alert(testSliceEach(arguments)); // 3200ms
alert(testArrayfied(arguments)); // 2400ms
alert(testArrayfiedSliced(arguments));// 1700ms

The last test is against a classic slice.call and it costs basically the same.
First and seconds demonstrate that if we slice to use native power we are actually spending more time than using native power directly.
Bear in mind that if the variable is already an Array, slice will cost much less and the average against the last test will be 1350 ms.

IE And Conclusions


I keep saying that IE should simply have normalized Array.prototype, ignoring those person that wrongly rely in for in loops over arrays when it's not necessary, and making this Array.fy portable for IE world as well since the internal proto variable is a pointer to the original Array.prototype then automatically ready for natives standard enhancements.
The nice part is that rather than see Array.prototype.something.call in every piece of code we can easily use one fast call to have them all ... so, you decide :-)

.. last minute Example ...


Just because sometimes we lack of fantasy, here a generic usage for Array.fy:

function $(selector, parentNode) {
return Array.fy((parentNode || document).querySelectorAll(selector));
}

$("div").forEach(function (div, i, nodeList) {
div.innerHTML = "Array.fy rocks!";
});


Update
just for testing/performances purpose:

Array.ify = (function () {
// (C) WebReflection - Mit Style License
for (var
m = [
"pop", "push", "reverse", "shift", "sort", "splice", "unshift",
"concat", "join", "slice", "indexOf", "lastIndexOf",
"filter", "forEach", "every", "map", "some", "reduce", "reduceRight"
],
f = [],
i = m.length; i--;
) {
f[i] = "var " + m[i] + "=p." + m[i];
m[i] = "o." + m[i] + "=" + m[i];
}
m.push("return o");
return Function("p", f.join(";") +
";return function Arrayfy(o){" + m.join(";") + "}"
)(Array.prototype);
}());

Saturday, February 20, 2010

Function.prototype.bind

Quick post about a fast Function.prototype.bind implementation.

Function.prototype.bind


function bind(context:Object[, arg1, ..., argN]):Function {
return a callback able to execute this function
passing context as reference via this
}

In few words, if we have a generic object, we don't necessary need to attach a function to create a method:

// a generic function
function name(name) {
if (name == null) return this.name;
this.name = name;
return this;
}

// a generic object
var wr = {name:"WebReflection"};

// a callback with a "trapped" object
var fn = name.bind(wr);

alert([

// wr has not been affected
wr.name, // WebReflection

// fn can always be called
fn(), // WebReflection

fn("test") === wr, // true
fn(), // test
wr.name // test

].join("\n"));

Designed to ensure the same context whatever way we decide to use the callback, included call, apply, setTimeout, DOM events, etc, Function.prototype.bind is one of the most useful/powerful JavaScript concept.
Unfortunately, this will be standard only with newer browser ...

Optimized bind for every browser


Update: as I have said I code what I need, I rarely google for simple tasks like this. Most of this code, in any case, has been readapted and tested to reach best performances, based on this proposal.

if (Function.prototype.bind == null) {

Function.prototype.bind = (function (slice){

// (C) WebReflection - Mit Style License
function bind(context) {

var self = this; // "trapped" function reference

// only if there is more than an argument
// we are interested into more complex operations
// this will speed up common bind creation
// avoiding useless slices over arguments
if (1 < arguments.length) {
// extra arguments to send by default
var $arguments = slice.call(arguments, 1);
return function () {
return self.apply(
context,
// thanks @kangax for this suggestion
arguments.length ?
// concat arguments with those received
$arguments.concat(slice.call(arguments)) :
// send just arguments, no concat, no slice
$arguments
);
};
}
// optimized callback
return function () {
// speed up when function is called without arguments
return arguments.length ? self.apply(context, arguments) : self.call(context);
};
}

// the named function
return bind;

}(Array.prototype.slice));
}


Why Bother

The concatenation optimization is something rarely present in whatever framework/library I have seen. While it makes the code a bit bigger than usual, performances will be the best for most common cases, those where optional arguments are not passed at all.
A simple test case, one of my favorites, able to solve the classic IE problem with extra arguments passed to setInterval/Timeout:

(function(){

var callback = function(time){
if (1000 < new Date - time)
return alert("1 second with a default argument");
setTimeout(callback, 15);
}.bind(null, new Date);

setTimeout(callback, 15);

}());

Saturday, January 30, 2010

[ES5] Classes As Descriptor Objects

In my latest posts I have talked about current situation for JavaScript "Classes". In Good Old And Common JS Errors I have introduced a misconception of a generic "Class" function which is usually not able to produce instanceof Class, considering Classes in JS are functions indeed.
In Better JS Classes I have explained how to write a meaningful Class factory, avoiding the _super pollution over each extended method, while in the JS _super Bullshit I have explained why the _super/parent concept does not scale with JavaScript prototypal inheritance model.

More than a dev, Mr Crockford included, agreed that in JavaScript the classical pattern does not fit/scale/produce expected results, and even worst, it could cause "disasters" during a session and slow down overall performances (and about this topic I have already said that web developers should stop to test their stuff with powerful CPU, read Macs!
Buy a bloody Atom based device as I have done and after that we can talk about the meaning of performances, right? Netbook should be able to surf without 100% of CPU usage, do you agree?)

The best part over all these years of wrong classical inheritance implementation is that with JavaScript.Next, aka ES5, the way we can define instances does not even require a function definition. Wanna know more?

Objects Extend Objects

It's that simple, we all know this is what happens in OOP Languages based over prototypal inheritance ... and since it is that simple ...

ES5 Classes As Descriptors

Or if you prefer, as definition objects. Yep! While every framework is using functions to create instances via new, in ES5 we could completely forget this pattern.

// class descriptor/definition
var MyClass = {
getValue:function () {
return this._value;
},
setValue:function (_value) {
this._value = _value;
}
};

// MyClass instance
var mc = Object.create(

// inherits from MyClass
MyClass,

// define privileged properties or methods
{
_value:{
value:"Hello ES5"
}
}
);

// Hello ES5
alert(mc.getValue());

Pretty cool, isn't it, but I am sure somebody is already arguing something like: "... and what about instanceof?"

instanceof

The instanceof operator checks if an object inherits from the implicit constructor prototype.
A common mistake is to think that instanceof is related to the function itself while it has nothing to do with it.

function A() {};
var klass = {};
A.prototype = klass;

var a = new A;

// true
alert(a instanceof A);

A.prototype = {};

// false
alert(a instanceof A);

function B(){};
B.prototype = klass;

// true
alert(a instanceof B);

Is it clear? instanceof works only with functions and only with those functions with an implicit prototype property, the default one, or specified as a generic object.

function A() {};
A.prototype = null;

var a = new A;

// throws: 'prototype' property of A is not an object
alert(a instanceof A);

To avoid above error, being JavaScript 99% dynamic, we could use a safer check, and for this example via isPrototypeOf:


function instanceOf(o, F) {
return !!F.prototype && F.prototype.isPrototypeOf(o);
};

function A() {};
var a = new A;

// true
alert(instanceOf(a, A));

Boring, slow, etc etc ... why don't we use directly our initial class description to understand if an instance is inheriting that class?

// using first example code
alert(MyClass.isPrototypeOf(mc));
// true

As alternative, we could use the global Object.getPrototypeOf method:

Object.getPrototypeOf(mc) === MyClass;

To be honest, for both easier scope resolution and semantic, I prefer the isPrototypeOf way. Furthermore, specially if the chain is deeper than 1 level, getPrototypeOf could generate false negatives while getPrototypeOf won't.

function A() {};
function B() {};
(B.prototype = new A).constructor = B;

var b = new B;

// true
alert(Object.getPrototypeOf(b) === B.prototype);

// false
alert(Object.getPrototypeOf(b) === A.prototype);

// both TRUE!
alert(B.prototype.isPrototypeOf(b));
alert(A.prototype.isPrototypeOf(b));

Accordingly, the best function to emulate an instanceOf function over objects or "classes" could be:


function inherits(o, __proto__) {
// (C) Mit Style WebReflection suggestion
return ((
typeof __proto__ === "function" ?
__proto__.prototype :
__proto__
) || {}).isPrototypeOf(o);
};

// test case
function A() {};
function B() {};
(B.prototype = new A).constructor = B;

var b = new B;

// true,true,true,true
alert([
inherits(b, A),
inherits(b, B),
inherits(b, A.prototype),
inherits(b, B.prototype)
]);


More ES5 Friendly Patterns

If we use what ES5 is bringing into JavaScript and via native execution speed, we may be interested into more "articulated" patterns to define "classes", or simply classes instances.

Object.defineProperties

First of all, as I have twitted already, please ignore that wrong suggestion about custom implementation.
The only place where all those checks could make sense is inside Object.defineProperty, and not twice in both defineProperties AND definePrperty, since if latter exists, why on earth we should try to emulate its internal checks?
If defineProperty does NOT exists, why shoud we try to emulate it without checks? I hope MDC guys will remove that nonsense from that page, I'd love to be sure developers get ES5 properly, good practices included.
Back in the topic, here there is an example:

function A(_value) {
// implicit init method
// where we define privileged proeprties/methods
Object.defineProperties(this, {
_value:{
value:_value,
// as example since it is false by default
enumerable:false
}
});

// and eventually we perform some task
};

// Class definition
Object.defineProperties(A.prototype, {
toString:{
value:function () {
return "" + this._value;
},
configurable:false
}
});

var a = new A(123);
alert(a); // 123

Does it make sense? We have more power via defineProperties and we can reuse, or share, objects across the whole library without any kind of problem.
One thing we should be ware about, is that A.prototype is always re-assignable, so if we try to define the A prototype property itself as non configurable we won't be safer anyway, it can be overwritten!

Dual Behavior: Factory Emulator


// when use strict will be enabled
// to obtain dual behavior (factory/constructor)
function A(_value) {
"use strict";
return Object.defineProperties(this || new A(_value), {
//... privileged definition
});
};


Dual Behavior Via Object.create


// Object.create way
function A(_value) {
// note that "this" may be useless, A() same of new A()
// inheritance chained in place
return Object.create(A.prototype, {
_value:{
value:_value,
enumerable:false
}
});
};

A.prototype = Object.create(A.prototype, {
toString:{
value:function () {
return "" + this._value;
},
configurable:false
}
});


Confused ???

I know I have started saying that theoretically we don't need anymore a single function to implement inheritance via ES5, but I bet those Java guys won't ever accept the fact JavaScript has no Classes and this is why I have suggested different patterns so that everybody could be happy about these ES5 features.

When Can We Start To Use These Features

Right now, in my opinion, including just one single vice versa project Object.js file, being careful about the target browser.
Unfortunately, and as usual, Internet Explorer is behind every other browser and some method cannot be perfectly emulated.
This is also why I have decided to show both defineProperties and create way, since IE defineProperties works only with DOM prototypes and global Window (or generally speaking only with natives and not with object) so that create could be used without problems, so far avoiding get/set and considering that configuration properties may not be respected.
I know this is crap, but until IE9 or the day we'll finally decide to drop this browser support, there's not that much we can do: annoying!

P.S. to test all these natively, we can use a WebKit nightly build.

Monday, January 25, 2010

The JavaScript _super Bullshit

I know you already hate the title, but that's how I called one paragraph of my precedent post: Better JavaScript Classes.

This post is mainly dedicated for both libraries authors, and those Classic OOP Developers that still think JavaScript should be used in a classic way.

_super or parent Are Problematic!

It's not just about performances, where "the magic" may need to replace, wrap, and assign runtime everything in order to make it happens, it's about inconsistencies, or infinite loops, or hard debug, or disaster prone approach as well, since as I have already said instances have nothing to do with _super/parent .... so, how are things? Thanks for asking!

Real OOP Behavior

It's the ABC, and nothing else, if we call a parent/super inside a method, this method will execute with a temporary self/this context.
This means that the instance will be still:
  1. an instanceof its Class
  2. only that method will be executed, it is possible to call other super/parent accordingly with the hierarchy
  3. if the instance Class overrides a parent method, when this will be executed via super, the invoked "extra" method will still be the one defined in the instance class and nothing else

// Classic OOP Behavior, a simple PHP 5 example
class A {
public function __construct() {
echo 'A.__construct', '<br />';

// this will call the B method indeed
$this->hello();
}
public function hello() {
echo 'A.hello()', '<br />';
}
}

class B extends A {
public function __construct() {
// parent invocation, this has nothing to do with the instance
parent::__construct();
echo 'B.__construct', '<br />';
}
public function hello() {
echo 'B.hello()', '<br />';
}
}

new A;
// A.__construct
// A.hello()

new B;
// A.__construct
// B.hello()
// B.__construct

Even if most frameworks respect above behavior, there is still somebody convinced that _super/parent is something truly simple to implement, often replacing this references runtime without taking care of multiple hierarchies, more than a super, method specific super, and on and on ...
In few words, if above behavior is respected, and the best test case is with more than 2 extended classes, we could think we are half way there ... isn't it?

John Resig on Simple JavaScript Inheritance

John called it simple, and it is simple indeed. Inheritance in JavaScript has a name: prototype chain.
John did a good job for those few bytes, the runtime replaced method is temporarily the called one, so other methods will be invoked as expected.
Everything perfect? Not really, some "tiny little problem" could occur if for some reason something goes wrong.

var A = Class.extend({
init: function () {
document.write("A.constructor<br />");
},
hello: function () {
throw new Error;
document.write("A.hello()<br />");
}
});

var B = A.extend({
init: function () {
this._super();
document.write("B.constructor<br />");
},
hello: function () {
this._super();
document.write("B.hello()<br />");
}
});

setTimeout(function () {
alert(b._super === A.prototype.hello);
// TRUE!
}, 1000);
var b = new B;
b.hello();

This is what I mean when I talk about DPP, something goes wrong? The instance will be messed up.
Don't even think about a try catch for each method invocation, this will make your application extremely slow compared with everything else.
In any case, 5 stars for its simplicity, but think before you decide to use _super in any case.

MooTools Way

Update My apologies to MooTools team. I had no time to re-test a false positive and MooTools is partially secured behind its parent call. However, my point of view about chose magic is well described at the end of this post comments, enjoy.

The Prototype Way

So we have seen already _super and parent problems, both wrongly attached into the instance, but we have not seen yet the Prototype way: the $super argument!

var A = Class.create({
initialize: function () {
document.write("A.constructor<br />");
},
hello: function () {
throw new Error;
document.write("A.hello()<br />");
}
});

var B = Class.create(A, {
initialize: function ($super) {
$super();
document.write("B.constructor<br />");
},
hello: function ($super) {
$super();
document.write("B.hello()<br />");
}
});

setTimeout(function () {
alert(b);
// nothing to do
}, 1000);
var b = new B;
b.hello();

Eventually, Prototype library got it right, YES!!!
While every other is associating super to the instance, Prototype understood that super has nothing to do with the instance.
Every method which aim is to override the inherited one must have a $super argument, if we want a limitation but finally the only implementation that does not break anything, whatever happens in the super call.
This is correct, the instance is temporarily injected into the super method and nothing else. No self referencing, no run-time assignments that could break, simply the method, that will host for a call that instance.
Every other method will be wrapped in order to bring the current instance in the super one and in this way we can consider our code somehow safer, the whole application won't break if something goes unpredictably wrong!

Still Something To Argue About

While I have never thought that Prototype got it absolutely right, I must disagree about its Class implementation.
It's that simple, I have already said it, in JavaScript Classes are functions!
Accordingly, why on earth Class should be an object?

function Class(){
return Class.create.apply(null, arguments);
};
Object.extend(Class, {
// the current Class object
});
Class.prototype = Function.prototype;

With a ridiculous effort, Prototype library could be the first one to implement a proper Factory to create classes!

// valid, for OO "new" everything maniacs
var A = new Class(...);

// still valid, alias of Class.create
var B = Class(...);

// explicit Factory
var C = Class.create(...);

// there we are!
alert([
A instanceof Class, // true
B instanceof Class, // true
C instanceof Class, // true
A instanceof Function, // of course
B instanceof Function, // of course
C instanceof Function // of course
]);


How Things Work "There"

The second thing I must disagree about Prototype is the way arguments are retrieved.
The king of public prototypes pollution framework does not cache the Function.prototype.toString to avoid overrides and/or redefinition:

function Fake($super){};
alert(Fake.argumentNames());

Function.prototype.toString = function () {
return this.name || "anonymous";
};

// throws an error
// alert(Fake.argumentNames());

// Fake is a first class *Object*
Fake.toString = function () {
return "[class Fake]";
};
// throws an error
//alert(Fake.argumentNames());

Fake.toString = function () {
return "function Fake(){return Fake instances}";
};
// empty string
alert(Fake.argumentNames());

Are you kidding me? Let's try again:

Function.prototype.argumentNames = (function (toString) {
return function() {
var names = toString.call(this).match(/^[\s\(]*function[^(]*\(([^\)]*)\)/)[1]
.replace(/\s+/g, '').split(',');
return names.length == 1 && !names[0] ? [] : names;
}
})(Function.prototype.toString);

4 out of 4 successful arguments parsing, rather than errors, problems, etc etc, for a framework that is already obtrusive, but at least in this case did not consider obtrusive code at all ... please fix it!

Inevitable Unportable

Finally, since the Prototype way requires wrappers and first argument injection, attached methods become instantly not portable anymore.
If we define a subclass and we would like to recycle its method somewhere else, we are trapped by the replaced, wrapped, injected $super argument.
Unfortunately this is the worst side effect for something that is actually not even close to classic OOP ... but we need to accept this compromise, or we simply need to better understand JavaScript, isn't it?

As Summary

This post does not want to be a "blame everybody for free" one, this post simply shows why I have written my Class implementation and why I do prefer explicit calls (somebody called them hard-coded) to super, shared, parent, whatever, inherited prototypes, as is for any other function we need in the middle of a session. JavaScript is like that, every function could be called without any warning somewhere with a different "this" reference and this is actually one of the most interesting and beauty part of this language.

I hope I have been able to give hints to both libraries authors, just 3 in this case, and specially to developers, those that copya and paste code trusting the source but unable to perform these kind of tests, and those convinced that JavaScript OOP and this._super is cool and it makes sense. As you can see, it does not, logically speaking first, and technically speaking after.
Last, but not least, all these wrappers simply mean less performances, even if we are talking about small numbers (a whole framework/libary based over these small numbers can easily become a pachyderm, seconds slower than many others).

Thursday, March 26, 2009

[js.php] A JavaScript Object Like PHP Class

PHP 5.3 introduces the Closure class which is really useful and more powerful than good old lambdas via create_function.
These are main limits of Closure class:

  • you cannot serialize a Closure instance (and json_encode does not solve the problem at all)

  • you cannot inject scopes via $this unless the closure comes from a class method


While with an emulated prototype style class, something I tried months ago as well, the first point could not be a problem, to solve the second one is quite inevitable to use a Python like variable as first argument, called $self, to make the Closure both portable and re-adaptable.


JSObject :: JavaScript Object Like PHP Class


/** js.php basic JSObject implementation
* @author Andrea Giammarchi
* @blog WebReflection.blogspot.com
* @license Mit Style License
*/
class JSObject implements ArrayAccess {

// public static prototype
static public $prototype;

// ArrayAccess Interface
public function offsetExists($index){return isSet($this->$index);}
public function offsetGet($index){return $this->$index;}
public function offsetSet($index, $value){$this->$index = $value;}
public function offsetUnset($index){unset($this->$index);}

// Invoked lambdas via $this or self::$prototype
public function __call($index, array $arguments){

// inject $this as first argument
array_unshift($arguments, $this);

// invoke the callback
return call_user_func_array(

// if it has been assigned to the object itself
isset($this->$index) ?

// it has priority
$this->$index :

// otherwise invoke from self::$prototype
self::$prototype->$index
,
$arguments
);
}

// JS like behavior, ready for extends
public function __toString(){
return '[object '.get_class($this).']';
// e.g. [object JSObject]
}

// Relevant Global Object implementations
public function getPrototypeOf(){
return get_class($this);
}
public function hasOwnProperty($index){
return isset($this->$index);
}
public function isPrototypeOf(/* string */ $class){
return $this instanceof $class;
}
public function toSource(){
// we could implement __sleep and __wakeup
// to avoid closure serialization (not possible yet)
return serialize($this);
}
public function toString(){
return $this->__toString();
}


// not standard method, anyway useful
public function toJSONString(){
// we could parse properties in a foreach
// to filter meaningless closures, if any
return json_encode($this);
}
}

// the global prototype is a JSObject too
JSObject::$prototype = new JSObject;

// JSObject factory: e.g. $myobj = JSObject(); // rather than new JSObject;
function JSObject(){
return new JSObject();
}

Above class uses an interface from the great SPL, an in-core extension present since PHP 5.1
The rest is theoretically compatible with old style lambdas, static functions, or new Closure instances. Here we go with some example:

// we can assigns prototypes everywhere ...
JSObject::$prototype->getName = function($self){
return $self->name;
};

$o = JSObject();

// ... even after JSObject instances creation
JSObject::$prototype->writeAge = function($self){
echo $self->getName().' is '.$self->age.' years old.';
};

// assign properties
$o->name = 'Andrea';
$o->age = 30;

// test some JS method
echo $o->toJSONString();
// {"name":"Andrea","age":30}

echo $o;
// [object JSObject]

echo $o->toSource();
// O:8:"JSObject":2:{s:4:"name";s:6:"Andrea";s:3:"age";i:30;}

// or tests runtime methods
$o->writeAge();
// Andrea is 30 years old.

// we can assign a custom method runtime
$o->getSurname = function($self){
return 'Giammarchi';
};

// custom methods have priority over prototype
$o->getName = function($self){
return $self->name.' '.$self->getSurname();
};

$o->writeAge();
// Andrea Giammarchi is 30 years old.

Is it cool? And more is coming for backward compatibility:

// prototype via function name resolution
JSObject::$prototype->getName = 'JSObject_getName';

// the function with a prefix to avoid conflicts
function JSObject_getName($self){
return $self->name;
}

// a simple test case
$o = JSObject();
$o->name = 'Andrea';

echo $o->getName();
// Andrea

And obviously we can do the same with create_function:

// prototype via lambda
JSObject::$prototype->getName = create_function('$self','
return $self->name;
');


Conclusion


Via SPL, closures, and some convenient trick, we could completely change the code style of PHP. Performances are always a priority, in any case, but with a couple of good practices, some discarded or "language useless" piece of ECMAScript, we could use JS style as low level structure for more Object Oriented frameworks or completely different ways to code.

What's next?


It is ages that I am waiting for a stable PHP 5.3 plus PECL extensions (in particular the php_operator to add operator overloads) to be able to create a JavaScript version of PHP. I have already created similar classes and my vision is a one2one JavaScript style framework created entirely via PHP. Craziness? Non-sense? Dunno, just try to imagine a Jaxer like behavior in every host with "just" PHP support ... is it a cool idea? Well, please contact me if you are interested ;)

Thursday, February 19, 2009

On JavaScript Inheritance Performance and Libraries Troubles

Update: I have replied to myself and developers in a new post. I would like to say a big Thank You to every developer exposed tests, benchmark, traps, and considerations. Please read my last thoughts about the subject, since I deeply reconsidered my position.
Update: Please do not get me wrong. I have no intention to say that one or any of cited framework, piece of code, library, is not good or fast enough to extend other classes. This post is about maniac optimization based on personal considerations over some deeper analysis to complete in a way the first benchmark.
I am not criticizing libraries, they are great and they offer everything, I am simply showing a specific case, which is particular on purpose, and a specific behavior that, useful or not, could not be respected.


About


Few days ago Ajaxian published a post about JS inherited methods performances via common libraries strategies.
I think the argument is extremely interesting but there's not enough material yet, so here I am with my contribution plus a "best option" proposal.

Why We Need Libraries to Extend Functions


  • libraries (should) manage properly the prototypal chain

  • libraries (should) make code more elegant/readable

  • libraries (should) let us create overrides being able to call parent/super method implicitly if necessary

  • libraries are often based over a generic extended "class" or hierarchy and users should be familiar with that way to extend or create classes in order to avoid internal conflicts



Why We Do Not Need Libraries to Extend Functions


  • we are performances or bytes maniacs and we are scared by library obtrusive implementations

  • we don't trust the library pattern/strategy to extend function - we know a better way to do it simply and quickly

  • we would like to create hybrids unmanageable via used library


About above points, let me answer to this question:
"Which Common Code/Library is Good and Fast to Extend Properly?" Considering the YUI approach out of the game, NOT A SINGLE ONE!!!

Tested Libraries in Alphabetic Order

base2, dojo, jClass, MooTools, Prototype, WebReflection (blog proposal), and YUI


About the Test

I tried to create a particular inheritance case.
There is a parent class with a toString and a toLocaleString prototype method.
These methods are particular since they are hidden methods (read: native) and browsers like Internet Explorer do not discover hidden methods even if those have been explicitly assigned.
The extended class should be able to understand the inheritance without problems and produce the expected result, showed in the Ad Hoc example.


Ad Hoc concept and troubles


  • Concept: manual inheritance over usable constructors.

  • Troubles: requires a bit of skill and parent calls are always explicit.



// manual implementation
// best performances and expected behavior in every browser
function AdHocClass(name){
this.name = name;
};
AdHocClass.prototype.toString = function(){
return this.name;
};
AdHocClass.prototype.toLocaleString = function(){
return "locale: " + this.toString();
};
function AdHocSub(name, age){
AdHocClass.call(this, name);
this.age = age;
};
AdHocSub.prototype = new AdHocClass;
AdHocSub.prototype.constructor = AdHocSub;
AdHocSub.prototype.toString = function(){
return AdHocClass.prototype.toString.call(this) + ": " + this.age;
};

// This is the expected result We would like to obtain
var me = new AdHocSub("Andrea", 30);
alert(me); // Andrea: 30
alert(me.toLocaleString()); // locale: Andrea: 30



base2


  • Concept: runtime injected parent (called via base) over explicit initialization via init method

  • Troubles: every instance calls two functions when initialized: the contructor plus the init method. This slows down performances. At the same time, not every method is inherited properly.



var BaseClass = base2.Base.extend({
constructor:function(name){
this.name = name
},
toString:function(){
return this.name;
},
toLocaleString:function(){return "locale: " + this.toString()}
});
var BaseSub = BaseClass.extend({
constructor:function(name, age){
this.base(name);
this.age = age;
},
toString:function(){
return this.base() + ": " + this.age;
}
});
var me = new BaseSub("Andrea", 30);
alert(me); // Andrea: 30
alert(me.toLocaleString()); // ERROR: same as toString both IE and Others



dojo


  • Concept: lazy dependencies resolution via the initializer method

  • Troubles: the initializer method is not that linear and it is probably the slowest in the list. Sometimes we need to call explicitly the method, as first argument, while sometimes we need to modify the arguments object or create an array to call the parent method. I am not sure I used dojo best practices to replicate the scenario but that's what I found googling for a while (Update: thanks to Eugene Lazutkin I could use a better practice which improved consistently performances). Is the rest fine? Not really, Internet Explorer does not inherit some hidden method. Update: apparently dojo offers different possibilities to extend and "play" with parents, so this is just one of them.


dojo.declare("dojoClass", null, {
constructor:function(name){
this.name = name;
},
toString:function(){
return this.name;
},
toLocaleString:function(){return "locale: " + this.toString()}
});
dojo.declare("dojoSub", dojoClass, {
constructor:function(name, age){
this.age = age;
},
toString:function($super){
return this.inherited("toString", arguments) + ": " + this.age;
}
});
var me = new dojoSub("Andrea", 30);
alert(me); // Andrea: 30 - not in IE
alert(me.toLocaleString()); // ERROR: same as toString in IE



jClass


  • Concept: basically the same one used by base2

  • Troubles: even worse than base2 since there are no explicit searches for toString and valueOf (most common hidden methods)



var ResigClass = jClass.extend({
init:function(name){
this.name = name;
},
toString:function(){
return this.name;
},
toLocaleString:function(){return "locale: " + this.toString()}
});
var ResigSub = ResigClass.extend({
init:function(name, age){
this._super(name);
this.age = age;
},
toString:function(){
return this._super() + ": " + this.age;
}
});
var me = new ResigSub("Andrea", 30);
alert(me); // Error: [object Object] in IE
alert(me.toLocaleString()); // Error: [object Object] in IE



MooTools


  • Concept: runtime injected parent, similar to base2. In my opinion the most clean and elegant way to extend a class.

  • Troubles: Classes are created via Class constructor so we have same bottleneck spotted in base2. Inheritance problems are basically the same found in base2: some hidden method is not inherited.



var MooToolsClass = new Class({
initialize: function(name){
this.name = name;
},
toString:function(){
return this.name;
},
toLocaleString:function(){return "locale: " + this.toString()}
});
var MooToolsSub = new Class({
Extends:MooToolsClass,
initialize:function(name, age){
this.parent(name);
this.age = age;
},
toString:function($super){
return this.parent() + ": " + this.age;
}
});
var me = new MooToolsSub("Andrea", 30);
alert(me); // Andrea: 30 - not inherited in IE
alert(me.toLocaleString()); // ERROR: locale: Andrea in IE



Prototype


  • Concept: $super variable as parent sent as first argument, imho the most obtrusive way so far and not elegant/intuitive at all.

  • Troubles: something works as expected, but only toString and valueOf, as is for base2, are considered hidden methods. The extra argument and the method overload make this library almost slow as dojo inheritance implementation is.



var ProtoClass = Class.create({
initialize:function(name){
this.name = name;
},
toString:function(){
return this.name;
},
toLocaleString:function(){return "locale: " + this.toString()}
});
var ProtoSub = Class.create(ProtoClass, {
initialize:function($super, name, age){
$super(name);
this.age = age;
},
toString:function($super){
return $super() + ": " + this.age;
}
});
var me = new ProtoSub("Andrea", 30);
alert(me); // Andrea: 30
alert(me.toLocaleString()); // ERROR: same as toString in IE




YUI


  • Concept: a constructor link to its parent prototype via "this.constructor.superclass". No runtime operations, no injected overloads, just "raw methods" based on explicit calls.

  • Troubles: not really. The YUI approach is extremely simple and efficient then "of course it works"!. There are just a couple of steps resolved via YAHOO.lang.extend: the correct constructor reassignment after the prototype one, plus the superclass link. I have just a comment about YUI implementation: guys, why do not you avoid that function creation for each extend call?



// No var F = function(){}, i SUGGESTION
extend: function(F){
return function(subc, superc, overrides) {
if (!superc||!subc) {
throw new Error("extend failed, please check that " +
"all dependencies are included.");
}
F.prototype=superc.prototype;
subc.prototype=new F;
subc.prototype.constructor=subc;
subc.superclass=superc.prototype;
if (superc.prototype.constructor == OP.constructor) {
superc.prototype.constructor=superc;
}

if (overrides) {
for (var i in overrides) {
if (L.hasOwnProperty(overrides, i)) {
subc.prototype[i]=overrides[i];
}
}

L._IEEnumFix(subc.prototype, overrides);
}

}
}(function(){}),

And here we are with the scenario:

function YUIClass(name){
this.name = name;
};
YUIClass.prototype.toString = function(){
return this.name;
};
YUIClass.prototype.toLocaleString = function(){
return "locale: " + this.toString();
};
function YUISub(name, age){
this.constructor.superclass.constructor.call(this, name);
this.age = age;
};
YAHOO.lang.extend(YUISub, YUIClass);
YUISub.prototype.toString = function(){
return this.constructor.superclass.toString.call(this) + ": " + this.age;
};
var me = new YUISub("Andrea", 30);
alert(me); // Andrea: 30
alert(me.toLocaleString()); // locale: Andrea: 30



WebReflection Proposal

After an analysis like this one, how could I skip my "all the best from others without troubles" proposal?
These are my considerations:

  • The fastest way to use a parent method is an explicit call

  • The best way to perform above step is via a link able to remove explicit dependencies (read: MyParentClassName instead of this.constructor.superclass). In this way methods could be easily transported from a prototype to another one without problems (less memory usage and less code to maintain)

  • The this.parent() solution is the cleanest one and generally speaking more close to our concept of "Object Oriented JavaScript". It is portable, it is meaningful, it is shorter than an explicit call with or without a link but it is not that fast to execute.

  • Using best practices to cache all we need, create a quick wrapper, resolving hidden methods problems, will not bring us to native or YUI performances, but at least in a good scenario: fast enough to guarantee performances over code elegance and readability


So here we are with my proposal:

  • Concept: parent in prototype but changed runtime for hierarchy purpose only if necessary (read: only for overrides). This will allows us to call parent directly in the constructor, as example, so we won't have double calls for each instance. At the same time, this implementation lets us call explicitly a parent method from those whose were not inherited.

  • Troubles: performances are the best but still far from native one.



function WRClass(name){
this.name = name;
};
WRClass.prototype.toString = function(){
return this.name;
};
WRClass.prototype.toLocaleString = function(){
return "locale: " + this.toString();
};
function WRSub(name, age){
this.parent(name);
this.age = age;
};
wr.extend(WRSub, WRClass, {
toString:function(){
return this.parent() + ": " + this.age;
}
});
var me = new WRSub("Andrea", 30);
alert(me); // Andrea: 30
alert(me.toLocaleString()); // locale: Andrea: 30

// last, but not least
WRSub.prototype.explicitParentToString = function(){
return this.parent.prototype.toString.call(this);
// instead of
return this.constructor.superclass.toString.call(this);
};
alert(me.explicitParentToString()); // Andrea



WebReflection proposed Extend

For future improvements/bugs fixes, please use this link.

var wr = {
extend:function(parent, extend){
/**
* (C) Andrea Giamamrchi
* Mit Style License
*/
return function(self, Function, Object){
var prototype = function(){
this.prototype[key] =
this.prototype.parent && typeof Object[key] == "function" && typeof this.prototype[key] == "function" ?
extend(Function, this.prototype[key], Object[key]) :
Object[key]
;
};
if(Object){
parent.prototype = Function.prototype;
self.prototype = new parent;
self.prototype.constructor = self;
self.prototype.parent = Function.prototype.parent ?
extend(Function, Function.prototype.parent, Function) : Function
} else
Object = Function;
for(var key in Object)
prototype.call(self);
for(key in {toString:key})
return self;
//* ... for Internet Explorer only ...
for(var
split = "hasOwnProperty.isPrototypeOf.propertyIsEnumerable.toLocaleString.toString.valueOf".split(".");
key = split.shift();
)
if(Object.hasOwnProperty(key))
prototype.call(self);
//*/
return self
}
}(
function(){},
function(parent, extend, Function){
return function(){
this.parent = extend;
var result = Function.apply(this, arguments);
this.parent = parent;
return result
}
}
)
};



The Benchmark

I had to choose Prototype or MooTools, since these frameworks seem to have some problem to coexist. Since Prototype has been tested in the Ajaxian post, I decided to put MooTools in the middle.
Something to consider before you try the benchmark page ... I removed the purposeless direct method call since it is absolutely the same for every basic class, created via library or not.
The order is by performances, where generally speaking are these:

  1. Ad Hoc Manual Explicit Inheritance

  2. YUI lang.extend (close to Ad Hoc)

  3. wr.extend - WebReflection proposal (closer to jClass than YUI)

  4. jClass (truly close to base2)

  5. base2 (truly close to jClass)

  6. dojo

  7. Prototype

  8. MooTools


Try out The Benchmark

And have a nice week end ;-)

Thursday, June 19, 2008

Has this constructor been prototyped?

This is a quick post about libraries that uses native constructor in an obtrusive way.
Using a Function prototype, that sounds like a non-sense, it is possible to know if a constructor has some property, or method, defined in its prototype.

Function.prototype.prototyped = function(){
for(var i in new this)
return true;
return false;
};


Some test example?

alert(Array.prototyped()); // false

Object.prototype.each = function(){};
alert(Array.prototyped()); // true

delete Object.prototype.each;
alert(Array.prototyped()); // false

Array.prototype.each = function(){};
alert(Array.prototyped()); // true
alert(Object.prototyped()); // false


Update
Has Kangas spotted, there is no reason to create a new instance.
We could loop directly the prototype object.
But what's up if we have injected privileged methods in the constructor?

Array = function(Array){
var prototype = Array.prototype;
return function(){
arguments = prototype.slice.call(arguments, 0);
arguments.each = function(){
prototype.forEach.apply(this, arguments);
};
return arguments;
};
}(Array);

var a = new Array(1, 2, 3);
a.each(function(value){
alert(value)
});

for(i in Array.prototype)
alert(i); // nothing

Above example is the reason I chose to create an instance ... but hey, why on heart someone should wrap a native constructor? :P

Monday, June 02, 2008

JavaScript prototype behaviour with PHP

One cool thing of JavaScript prototype model, is that you can change dynamically one or more method updating automatically every instance of that constructor.
Even if classic inheritance and OO Programmers hate this feature, it could be really useful in some case.
Another interesting thing, is that thanks to injected scope, you can share a prototype or use one of its defined methods, with every kind of instance.

PHP is (still) dynamically limited


The concept of injected scope, is absolutely extraneous to PHP developers.
Even with a massive usage of Reflection API, it is not possible to use a method of class A with another class B, even if this method contains common usable tasks for both classes.
At the same time, it is not possible to use a function as property, because it is not recognized as function, if called directly, and it cannot contain a $this referer, thanks to engine limitation.

The light comes from PECL


The official repository for PHP extensions, contains a truly interesting one that is able to modify runtime a class and every derived instance.
This extension is absolutely experimental, but right now usable in some version of PHP 5.
Its name is runkit, that with another one, called classkit, let us use PHP in a "more psychedelic way" :D

The prototype behaviour with PHP


Using a couple of technique, such an SPL interface, and runkit extension, I have been able to write and successfully execute a code like this one:

<?php

// basic class
class Demo {
public static $prototype;
}

// prototype assignment, with optional methods
Demo::$prototype = new prototype(
'Demo',
array(
'set_name' => array('$name', '$this->name = $name;'),
'get_name' => array('return $this->name;')
)
);

// a generic instance
$demo = new Demo();
$demo->set_name('Andrea Giammarchi');
echo $demo->get_name(); // Andrea Giammarchi

// add more prototypes
Demo::$prototype->set_age = array('$age', '$this->age = $age;');
Demo::$prototype->get_info = array('return $this->name." is ".$this->age." years old";');

$demo->set_age(30);
echo '
', $demo->get_info();
// Andrea Giammarchi is 30 years old

?>

In few words, I have been able to define a list of methods, to assign as prototype, to use them, and finally add more, usable with pre defined instance without problems.

Shared method emulations


What is possible to do, at this point, is to share one or more method between two classes, and without problems.
It is even possible to assign directly an entire prototype to another one, using the prototype constructor:

<?php

// same stuff of precedent example

class Constructor {

public static $prototype;

// please note that this constructor
// uses method not defined, yet :)
public function __construct($name, $age){
$this->set_name($name);
$this->set_age($age);
}

}

Constructor::$prototype = new prototype('Constructor', Demo::$prototype);

$me = new Constructor('Andrea', 30);
echo $me->get_info();
// Andrea is 30 years old

?>

Of course, another class could simply initialise its public static prototype, and then add, if necessary, only one method:

<?php

class Name {
public static $prototype;
}
Name::$prototype = new prototype('Name');
Name::$prototype->set_name = Demo::$prototype->set_name;

$me = new Name;
$me->set_name('Andrea Giammarchi');
echo $me->name;
// Andrea Giammarchi

?>


The class prototype and its limit


To successfully test above example codes, I have used my prototype class, that as I said, requires usage of SPL and runkit extension as well.

The shared method emulation, is artificial, because of runkit call that will create a new function, with same arguments and body, for each prototoype. Anyway, the usage is, in my opinion, simple as comfortable and without error possibilities, except for == or === operator that will return in every case false (so the trick is to compare the imploded version of both prototypes, if is the identical string, those are the same prototype)

if(implode('',Demo::$prototype->set_name) === implode('',Name::$prototype->set_name))
doYourStuff();


The main limit of this class is created by runkit extension, that does not let me use every kind of method name, and fails for example if I write setName instead of set_name.

In another PHP version, the 5.3.dev, it lets me use every kind of name, but crash when I try to modify one method, or to remove them using unset(ClassName::$prototype->methodName);

For these reason, you can get this class as example, but you know, right now, that with SPL and some cool PECL extension, PHP limits are truly less evident than ever.

Have fun :)

Tuesday, May 20, 2008

Habemus Array ... unlocked length in IE8, subclassed Array for every browser

History


I do not know how many time, during these years, JavaScript Ninjas tried to subclass the native Array to create libraries over its powerful methods without losing performances. I have finally discovered the way to remove locked length from Internet Explorer 8, and to solve problems with every other browser.

We tried to inherit Array instead of Object


This is where my last trip started, simply looking at arguments behaviour. It was there, since 2000 when I started to code in JavaScript, and it was so simple that probably few developers thought about them!

var o = {
length:0,
push:Array.prototype.push,
toString:Array.prototype.join
};

o.push(1,2,3);
alert(o); // 1,2,3

arguments, in JavaScript, is an instanceof Object, and not an Array, as is in ActionScript since version 1.0
What we have done all this time, is to use Array.prototype methods injecting a basic object, with a simple length parameter, inside.
If an object with a length value can be used as an Array, why on heart above code should not work?

We all love prototypal inheritance, we all want an instanceof Array


If you try to inherit directly an array as prototype, Internet Explorer will fix every instance length property, destroying possibility to use simple for loop over generated values.

function MyArray(){};
MyArray.prototype = [];

var a = new MyArray;
a.push(1,2,3);
alert(a.length); // 0 with every Internet Explorer

Problems are much more than a fixed length, as I wrote many months ago when I presented my ArrayObject.
On the other hand, this kind problem has been fixed for Internet Explorer 8, and 7 emulation.
Yes, finally I did it!

/**
* Choose a name for subclassed Array
*/
Stack = (function(){ // (C) Andrea Giammarchi - Mit Style License

/**
* Your personal Array constructor
*/
function Stack(length){
if(arguments.length === 1 && typeof length === "number")
this.length = -1 < length && length === length << 1 >> 1 ? length : this.push(length);
else if(arguments.length)
this.push.apply(this, arguments);
};

// Solution 1:
// Declaration of generic function
// with an array as prototype
function Array(){};
Array.prototype = [];

// Solution 2:
// use the prototype chain to inherit
// Array constructor and its native prototype
Stack.prototype = new Array;

// Solution 3:
// overwrite inherited length with zero value
Stack.prototype.length = 0;

// Solution 4:
// redeclare toString method in this way
// to let JScript core feel better
Stack.prototype.toString = function(){
return this.slice(0).toString();
};

/**
* Return and assign subclassed Array
*/
Stack.prototype.constructor = Stack;
return Stack;

})();

Above code is the basis to create an alternative Array constructor that will be able to work as expected with every browser plus IE8, without length problems.
If you try to remove a single comma from some Solution, it will never work.
If you directly assign an array to the prototype, length will be fixed.
If you remove toString prototype, FireFox and others will not work as expected.

The definitive workaround for every browser


Since first part of this post could be used in every browser, starting from IE 5.5, these old browser can simply use a constructor with a prototype full of native methods, but without instanceof Array behavior.
At the same time, every other cool browser (Safari, Firefox, Opera) could use above code to have the same behavior of IE8.

This is the full cross browser Stack constructor

While this is an improvement over basic JS 1.5 Array, to have JS 1.7 methods too, natives with updated browsers, emulated in a fast standard way with every other.
Stack Extended JS 1.7 Subclassed Array

The last problem to solve, the concat method


concat, is as simple as truly bastard prototype!
There is no way to use native concat method, even with prototypal chain inherited native Array instances.
This is why I have normalized that method, in a Stack self compatible way.
On the other hand, you cannot send a Stack instance as concat parameter, but you can always use native slice method, fast as native one is.

Best performances ever


Yes, using native, incore, prototypes, makes your code execution faster.
This compatibility + benchmark page, can tell you more about this Stack implementation than me, specially with IE8, Safari, and Opera, where performances are neary the same of a generic Array.

FireFox is probably the one that has more problems to manage native code with dynamic constructors, but hey, I am talking about Firefox beta 3, while probably RC1 or nex release will be fast as Safari, or Opera, are.

What to do with Stack?


Libraries, libraries, and libraries, finally with core performaces, the possibility to truly extend the Array, removing every fake iframe, popup, whathever you have used during these days.

Have fun with Stack, and see you soon for some other cool example with them :geek: