Reserved Words As Properties

Number one of the list is the myth that reserved words cannot be used as properties. Here platforms that cannot:

iOS 4

IE less than 9

Android less than 2.1

So, basically, 99% of mobile browsers support properties such obj.delete(), used in most recent JavaScript specifications, while those jurassic browsers need the obj['delete']() convention.

// exactly same good old ES3 behavior
// using ES5 capabilities
Function.prototype.new = function () {
var
// grab the prototype
p = this.prototype,
// create from it
o = Object.create(p),
// invoke the real constructor
r = this.apply(o, arguments);
// if the result is not undefined or null
// and the returned value is an object/function
// overwrite the result
return r != null && (
typeof r === 'object' ||
typeof r === 'function'
) ? r : o;
};
// you can be Rubyish now ^_^
var instance = MyClass.new(1, 2, 3);
// P.S. if you have problems with JSLint
// and the r != null part in above snippet
// it's just time for you to upgrade to JSHint

Please Do Not Support Too Old Browsers

As easy as that. As a developer, company, software provider, whatever, you are trapping yourself behind problems that will never be fixed in those browsers and you are limiting your customer too, embracing development for such old environment, instead of promoting an update that will benefit them in terms of both potentials, expenses, and security.
Any company that will say no to that should be kindly be abandoned, IMHO, they're already out of web/JS business and they don't realize yet.
I understand some graceful measurement should be taken in order to migrate old users, but as long as they feel confortable, they won't migrate sooner for sure.
Customers or people we'd like to let them access our service, should be informed somehow of new possibilities too.

Apple Drops 3 Years Old Software Too

If Apple not accepting non retina software anymore is not enough as an argument, think how many possibilities you are dropping to your software in order to work the same in those old browsers.
You chose Web technologies, you should catch up with these, end of the story.

Object.defineProperty() *Is* Available

Even my Palm Pre 2 webOS supports Object.defineProperty(), together with Object.defineProperties(), Object.getPrototypeOf() and Object.getOwnPropertyDescriptor()!
If you don't want to deal with all this verbosity but you like the power behind, redefine is really your best friend then!

The most widely adopted list of ES5 features down to Android 2.1 phones and webOS are:

Object.create()

Object.defineProperty()

Object.defineProperties()

Object.getOwnPropertyNames()

Object.getOwnPropertyDescriptor()

Object.getPrototypeOf()

Things like Object.freeze() might have been introduced later on so don't trust them ... but, whenever you wanna try that:

Function.prototype get caller() {return WTF}

Generally speaking the caller property works since ever but there are cases where it does not and this is iOS5 and lower fault.
What am I talking about? About caller over getters, with or without __defineGetter__ old style approach, the new one fails too ^_^
Bear in mind iOS 5.1 and 6.0+ are just fine so you can still use that magic, if needed.
Note a part, that magic ain't disappearing any time soon so ... go on, use caller until there is an alternative: so far, not a single one ^_^

Function.prototype.bind()

It took literarily ages for WebKit to adopt this method so this is something available in all modern browsers but most likely not available with not so old mobile one: easy shim from callerOf!

This is the kind of code that I would like to see in CDN, not just 50K libraries for client sake!

Avoid __proto__

Not only conceptually an error and used only to gain some arguable performance boost, __proto__ is absolutely something that IE 10 and 9 will never have in a consistent way.

If you want to transform a list into an array, just var slice = Function.call.bind([].slice); so that you can slice(whatever, optionalIndex) ALL the things, right? The bind() is there and costs nothing ... just use it!

Better Than Zepto

What this library is doing, except from ignoring IE as a Mobile browser, is a poor/quick&dirty design/convention to obtain a prototype swap instead of initializing things in the right way.
The previously linked code could be represented by exactly the same syntax:

While performance might not be that good in some engine, and everybody knows that you should never $('select') twice per collection so actually, considering above snippet goes 400.000 objects per seconds, that's not a big/real deal at all!
If that is, I tell you something else is wrong in the app logic!
In any case, actually, there's some mobile platform there, those Zepto thinks is supporting, that scores more with lower results than with a prototype swap, which is the most common selector case, BlackBerry 10 is 8 thousands operations per seconds there compared with __proto__
Thomas Fuchs has been so nice in his repository I cannot even push/contributes these improvements ... surely he would get this one as an insult too, isn't it?

A Swap Oriented __proto__ Attempt

Assuming you still want to swap runtime classes because you cannot define a proper inheritance upfront, here a broken attempt to do that in IE8 and lower:

object = dunder(object, proto);

what's dunder()

dunder() is my attempt to bring a friendly cross platform way, included older IE, to swap proto at runtime.
It requires an assignment so, back to Zepto example, return dunder(dom || [], $.fn) would be all you need to make it work everywhere.

JSON.stringify(object, *replacer*)

This is Safari specific gotcha, and it's about the replacer.
While specs say that Let newElement be the result of calling the abstract operation Walk, passing val and **ToString**(I), Safari will send to the receiver the number 0 instead of the string '0'.
What's the big deal here? That in JavaScript, 0 == false while '0' == true so ... if you have this kind of check in your receiver thinking that if empty, nothing should be done:

if (key) {
// parse your value
}

Improve that check with if (key === ''), probably the only place on earth where JSLint would have helped you for real instead of messing up your own code.

7 comments:

The problem with old browsers and modern ECMAScript features is that there are still many users out there who are currently surfing the web with one of those relics. When I spoke to Repubblica's developers last October I was shocked by the fact that their stats still showed a significant percentage of IE6's users (about 13%). As a developer I agree with Ian Hickson when he said that we should code to the standards, not to the lowest common denominator (guess what it is?). As a freelance, my problems are still related to what clients consider a priority, namely an impossible cross-browser compatibility that forces us to write rubbish code just to not break some (one?) browsers. :-)

What I mean, is ttat nobody cares to put a bloody "your flash player is not updated" in any website, but the browser not updated is an ignored problem? I don't like/promote/support that from any point.

If you care about the web, you should care about informig your users they cannot have the web now because they are way behind modern possibilities.

Let them switch, and they will thank you and the day after, forget about old IE ... "they can drag and drop files in the email", can you imagine?