Blog
May 21st, 2009
Previously I analyzed ECMAScript 5's Object and Property system. This is a huge new aspect of the language and deserved its special consideration.
There are a number of other new features and APIs that need attention, as well. The largest of which are Strict Mode and native JSON support.
Strict Mode
Strict Mode is a new feature in ECMAScript 5 that allows you to place a program, or a function, in a "strict" operating context. This strict context prevents certain actions from being taken and throws more exceptions (generally providing the user with more information and a tapered-down coding experience).
Since ECMAScript 5 is backwards-compatible with ECMAScript 3, all of the "features" that were in ECMAScript 3 that were "deprecated" are just disabled (or throw errors) in strict mode, instead.
Strict mode helps out in a couple ways:
- It catches some common coding bloopers, throwing exceptions.
- It prevents, or throws errors, when relatively "unsafe" actions are taken (such as gaining access to the global object).
- It disables features that are confusing or poorly thought out.
Most of the information about strict mode can be found in the ES5 specification [PDF] on page #223.
It should be noted that ECMAScript 5's strict mode is different from the strict mode available in Firefox (which can be turned on by going to about:config and enabled javascript.options.strict). ES5's strict mode complains about a completely different set of potential errors (whereas Firefox's existing strict mode tries to enforce some good practices, only).
How do you enable strict mode?
Simple. Toss this at the top of a program to enable it for the whole script:
Or place it within a function to turn on strict mode only within that context.
function imStrict(){
"use strict";
// ... your code ...
}
Note the syntax that's used to enable strict mode (I love this!). It's simply a string in a single statement that happens to contain the contents "use strict". No new syntax is introduced in order to enable strict mode. This is huge. This means that you can turn strict mode on in your scripts - today - and it'll have, at worst, no side effect in old browsers.
As you may note from the examples here and in the previous post there are virtually no new syntax additions or changes to the language in ECMAScript 5. This means that you can write your ES5 scripts in a manner that will be able to gracefully degrade for older useragents - something that wasn't possible with ECMAScript 4. The way in which strict mode is enabled is a great illustration of that point in practice.
A neat aspect of being able to define strict mode within a function is that you can now define complete JavaScript libraries in a strict manner without affecting outside code.
// Non-strict code...
(function(){
"use strict";
// Define your library strictly...
})();
// Non-strict code...
A number of libraries already use the above technique (wrapping the whole library with an anonymous self-executing function) and they will be able to take advantage of strict mode very easily.
So what changes when you put a script into strict mode? A number of things.
Variables and Properties
An attempt to assign foo = "bar"; where 'foo' hasn't been defined will fail. Previously it would assign the value to the foo property of the global object (e.g. window.foo), now it just throws an exception. This is definitely going to catch some annoying bugs.
Any attempts to write to a property whose writable attribute is set to false, delete a property whose configurable attribute is set to false, or add a property to an object whose extensible attribute is set to false will result in an error (these attributes were discussed previously). Traditionally no error will be thrown when any of these actions are attempted, it will just fail silently.
Deleting a variable, a function, or an argument will result in an error.
var foo =
"test";
function test
(){}
delete foo; // Error
delete test; // Error
function test2(arg) {
delete arg; // Error
}
Defining a property more than once in an object literal will cause an exception to be thrown
// Error
{ foo: true, foo: false }
eval
Virtually any attempt to use the name 'eval' is prohibited - as is the ability to assign the eval function to a variable or a property of an object.
// All generate errors...
obj.eval = ...
obj.foo = eval;
var eval = ...;
for ( var eval in ... ) {}
function eval(){}
function test(eval){}
function(eval){}
new Function("eval")
Additionally, attempts to introduce new variables through an eval will be blocked.
eval("var a = false;");
print( typeof a ); // undefined
Functions
Attempting to overwrite the arguments object will result in an error:
arguments = [...]; // not allowed
Defining identically-named arguments will result in an error function( foo, foo ) {}.
Access to arguments.caller and arguments.callee now throw an exception. Thus any anonymous functions that you want to reference will need to be named, like so:
setTimeout(function later(){
// do stuff...
setTimeout( later, 1000 );
}, 1000 );
The arguments and caller properties of other functions no longer exist - and the ability to define them is prohibited.
function test(){
function inner(){
// Don't exist, either
test.arguments = ...; // Error
inner.caller = ...; // Error
}
}
Finally, a long-standing (and very annoying) bug has been resolved: Cases where null or undefined is coerced into becoming the global object. Strict mode now prevents this from happening and throws an exception instead.
(function(){ ... }).call( null ); // Exception
with(){}
with(){} statements are dead when strict mode is enabled - in fact it even appears as a syntax error. While the feature was certainly mis-understood and possibly mis-used I'm not convinced that it's enough to be stricken from the record.
The changes made in ECMAScript 5 strict mode are certainly varied (ranging from imposing stylistic preferences, like removing with statements, to fixing legitimately bad language bugs, like the ability to redefine properties in object literals). It'll be interesting to see how people begin to adopt these points and how it'll change JavaScript development.
All that being said, I'm fairly certain that jQuery is ES5-Strict compatible right now. Once an implementation of the language is made available (so that that premise may be tested) I'll happily switch jQuery over to working exclusively in strict mode.
JSON
The second major feature of the language is the addition of native JSON support to the language.
I've been championing this move for a long time and I'm glad to see it finally arrive in a specification.
In the meantime PLEASE start migrating your JSON-using applications over to Crockford's json2.js. It is fully compatible with the ECMAScript 5 specification and gracefully degrades if a native (faster!) implementation exists.
In fact, I just landed a change in jQuery yesterday that utilizes the JSON.parse method if it exists, now that it has been completely specified.
There are two primary methods for handling JSON: JSON.parse (which converts a JSON string into a JavaScript object) and JSON.stringify (which convert a JavaScript object into a serialized string).
JSON.parse( text )
Converts a serialized JSON string into a JavaScript object.
var obj = JSON.parse('{"name":"John"}');
// Prints 'John'
print( obj.name );
JSON.parse( text, translate )
Use a translation function to convert values or remove them entirely.
function translate
(key, value
) {
if ( key ===
"name" ) {
return value +
" Resig";
}
}
var obj = JSON.parse('{"name":"John","last":"Resig"}', translate);
// Prints 'John Resig'
print( obj.name );
// Undefined
print( obj.last );
JSON.stringify( obj )
Convert an object into a serialized JSON string.
var str = JSON.stringify({ name: "John" });
// Prints {"name":"John"}
print( str );
JSON.stringify( obj, ["white", "list"])
Serialize only a specific white list of properties.
var list = ["name"];
var str = JSON.stringify({name: "John", last: "Resig"}, list);
// Prints {"name":"John"}
print( str );
JSON.stringify( obj, translate )
Serializes the object using a translation function.
function translate
(key, value
) {
if ( key ===
"name" ) {
return value +
" Resig";
}
}
var str = JSON.stringify({"name":"John","last":"Resig"}, translate);
// Prints {"name":"John Resig"}
print( str );
JSON.stringify( obj, null, 2 )
Adds the specified number of spaces to the output, printing it evenly.
var str = JSON.stringify({ name: "John" }, null, 2);
// Prints:
// {
// "name": "John"
// }
print( str );
JSON.stringify( obj, null, "\t" )
Uses the specified string to do the spacing.
var str = JSON.stringify({ name: "John" }, null, "\t");
// Prints:
// {\n\t"name": "John"\n}
print( str );
Additionally, a few new generic methods have been added to some of the base objects but, frankly, they aren't that interesting. The results from String, Boolean, and Number are just equivalent to calling .valueOf() and the result from Date is equivalent to calling .toISOString()
// Yawn...
String.prototype.toJSON
Boolean.prototype.toJSON
Number.prototype.toJSON
Date.prototype.toJSON
.bind()
A welcomed addition to the language is a built-in .bind() method for enforcing the context of a function (virtually identical to Prototype's .bind implementation).
Function.prototype.bind(thisArg, arg1, arg2....)
Enforces the 'this' of the specified function to a specific object - and passing in any specified arguments.
var obj =
{
method:
function(name){
this.
name =
name;
}
};
setTimeout( obj.method.bind(obj, "John"), 100 );
Considering how long this function (and its equivalents) have been around it's a welcome addition to the language.
Date
Dates are now capable of both parsing and outputting ISO-formatted dates. Thank goodness, about time. rimshot
The Date constructor now attempts to parse the date as if it was ISO-formatted, first, then moves on to the other inputs that it accepts.
Additionally, date objects now have a new .toISOString() method that outputs the date in an ISO format.
var date =
new Date
("2009-05-21T16:06:05.000Z");
// Prints 2009-05-21T16:06:05.000Z
print( date.toISOString() );
.trim()
A native, built-in, .trim() is now included for strings. Works identically to all the other trim methods out there - with the potential to possibly work faster.
Steven Levithan has discussed the trim method in great depth.
Array
The JavaScript Array Extras that've been around for, what seems like, forever are finally formally specified. This includes the following methods: indexOf, lastIndexOf, every, some, forEach, map, filter, reduce, and reduceRight.
Additionally a new Array.isArray method is included, providing functionality very similar to the following:
Array.isArray = function( array ) {
return Object.prototype.toString.call( array ) === "[object Array]";
};
Altogether I think ECMAScript 5 makes for an interesting package. It isn't the massive leap that ECMAScript 4 promised but it is a series of respectable improvements that reduces the number of obvious bugs while making the language safer and faster. I'm looking forward to when some implementations start to go public.
Tags: javascript, ecmascript
62 Comments on 'ECMAScript 5 Strict Mode, JSON, and More'
May 21st, 2009
ECMAScript 5 is on its way. Rising from the ashes of ECMAScript 4, which got scaled way back and became ECMAScript 3.1, which was then re-named ECMAScript 5 (more details)- comes a new layer of functionality built on top of our lovable ECMAScript 3.
Update: I've posted more details on ECMAScript 5 Strict Mode, JSON, and More.
There are a few new APIs included in the specification but the most interesting functionality comes into play in the Object/Property code. This new code gives you the ability to dramatically affect how users will be able to interact with your objects, allowing you to provide getters and setters, prevent enumeration, manipulation, or deletion, and even prevent the addition of new properties. In short: You will be able to replicate and expand upon the existing JavaScript-based APIs (such as the DOM) using nothing but JavaScript itself.
Perhaps best of all, though: These features are due to arrive in all major browsers. All the major browser vendors worked on this specification and have agreed to implement it in their respective engines. The exact timeframe isn't clear yet, but it's going to be sooner, rather than later.
There doesn't appear to exist a full implementation of ES5 at this point, but there are a few in the works. In the meantime you can read the ECMAScript 5 specification (PDF - I discuss pages 107-109 in this post) or watch the recent talk by some of the ECMAScript guys at Google.
Note: I've provided a couple simple, example, implementations for these methods to illustrate how they might operate. Almost all of them require other, new, methods to work correctly - and they are not implemented to match the specification 100% (for example there is no error checking).
Objects
A new feature of ECMAScript 5 is that the extensibility of objects can now be toggled. Turning off extensibility can prevent new properties from getting added to an object.
ES5 provides two methods for manipulating and verifying the extensibility of objects.
Object.preventExtensions( obj )
Object.isExtensible( obj )
preventExtensions locks down an object and prevents and future property additions from occurring. isExtensible is a way to determine the current extensibility of an object.
Example Usage:
var obj =
{};
obj.name = "John";
print( obj.name );
// John
print( Object.isExtensible( obj ) );
// true
Object.preventExtensions( obj );
obj.url = "http://ejohn.org/"; // Exception in strict mode
print( Object.isExtensible( obj ) );
// false
Properties and Descriptors
Properties have been completely overhauled. No longer are they the simple value associated with an object - you now have complete control over how they can behave. With this power, though, comes increased complexity.
Object properties are broken down into two portions.
For the actual "meat" of a property there are two possibilities: A Value (a "Data" property - this is the traditional value that we know and love from ECMAScript 3) or a Getter and Setter (an "Accessor" property - we know this from some modern browsers, like Gecko and WebKit).
- Value. Contains the value of the property.
- Get. The function that will be called when the value of the property is accessed.
- Set. The function that will be called when the value of the property is changed.
Additionally, properties can be...
- Writable. If false, the value of the property can not be changed.
- Configurable. If false, any attempts to delete the property or change its attributes (Writable, Configurable, or Enumerable) will fail.
- Enumerable. If true, the property will be iterated over when a user does
for (var prop in obj){} (or similar).
Altogether these various attributes make up a property descriptor. For example, a simple descriptor might look something like the following:
{
value: "test",
writable: true,
enumerable: true,
configurable: true
}
The three attributes (writable, enumerable, and configurable) are all optional and all default to true. Thus, the only property that you'll need to provide will be, either, value or get and set.
You can use the new Object.getOwnPropertyDescriptor method to get at this information for an existing property on an object.
Object.getOwnPropertyDescriptor( obj, prop )
This method allows you to access the descriptor of a property. This method is the only way to get at this information (it is, otherwise, not available to the user - these don't exist as visible properties on the property, they're stored internally in the ECMAScript engine).
Example Usage:
var obj =
{ foo:
"test" };
print(JSON.stringify(
Object.getOwnPropertyDescriptor( obj, "foo" )
));
// {"value": "test", "writable": true,
// "enumerable": true, "configurable": true}
Object.defineProperty( obj, prop, desc )
This method allows you to define a new property on an object (or change the descriptor of an existing property). This method accepts a property descriptor and uses it to initialize (or update) a property.
Example Usage:
var obj =
{};
Object.defineProperty( obj, "value", {
value: true,
writable: false,
enumerable: true,
configurable: true
});
(function(){
var name = "John";
Object.defineProperty( obj, "name", {
get: function(){ return name; },
set: function(value){ name = value; }
});
})();
print( obj.value )
// true
print( obj.name );
// John
obj.name = "Ted";
print( obj.name );
// Ted
for ( var prop in obj ) {
print( prop );
}
// value
// name
obj.value = false; // Exception if in strict mode
Object.defineProperty( obj, "value", {
writable: true,
configurable: false
});
obj.value = false;
print( obj.value );
// false
delete obj.value; // Exception
Object.defineProperty is a core method of the new version of ECMAScript. Virtually all the other major features rely upon this method existing.
Object.defineProperties( obj, props )
A means of defining a number of properties simultaneously (instead of individually).
Example Implementation:
Object.defineProperties = function( obj, props ) {
for ( var prop in props ) {
Object.defineProperty( obj, prop, props[prop] );
}
};
Example Usage:
var obj =
{};
Object.defineProperties(obj, {
"value": {
value: true,
writable: false
},
"name": {
value: "John",
writable: false
}
});
Property descriptors (and their associated methods) is probably the most important new feature of ECMAScript 5. It gives developers the ability to have fine-grained control of their objects, prevent undesired tinkering, and maintaining a unified web-compatible API.
New Features
Building on top of these new additions some interesting new features have been introduced into the language.
The following two methods are very useful for collecting arrays of all the properties on an object.
Object.keys( obj )
Returns an array of strings representing all the enumerable property names of the object. This is identical to the method included in Prototype.js.
Example Implementation:
Object.keys = function( obj ) {
var array = new Array();
for ( var prop in obj ) {
if ( obj.hasOwnProperty( prop ) ) {
array.push( prop );
}
}
return array;
};
Example Usage:
var obj =
{ name:
"John", url:
"http://ejohn.org/" };
print( Object.keys(obj).join(", ") );
// name, url
Object.getOwnPropertyNames( obj )
Nearly identical to Object.keys but returns all property names of the object (not just the enumerable ones).
An implementation isn't possible with regular ECMAScript since non-enumerable properties can't be enumerated. The output and usage is otherwise identical to Object.keys.
Object.create( proto, props )
Creates a new object whose prototype is equal to the value of proto and whose properties are set via Object.defineProperties( props ).
A simple implementation would look like this (requires the new Object.defineProperties method).
Example Implementation: (by Ben Newman)
Object.create = function( proto, props ) {
var ctor = function( ps ) {
if ( ps )
Object.defineProperties( this, ps );
};
ctor.prototype = proto;
return new ctor( props );
};
Other implementation:
Object.
create =
function( proto, props
) {
var obj =
new Object
();
obj.__proto__ = proto;
if ( typeof props !== "undefined" ) {
Object.defineProperties( obj, props );
}
return obj;
};
Note: The above code makes use of the Mozilla-specific __proto__ property. This property gives you access to the internal prototype of an object - and allows you to set its value, as well. The ES5 method Object.getPrototypeOf allows you to access this value but not set its value - thus the above method cannot be implement in a generic, spec-compatible, manner.
I discussed Object.getPrototypeOf previously so I won't bother discussing it again here.
Example Usage:
function User
(){}
User.
prototype.
name =
"Anonymous";
User.
prototype.
url =
"http://google.com/";
var john = Object.create(new User(), {
name: { value: "John", writable: false },
url: { value: "http://google.com/" }
});
print( john.name );
// John
john.name = "Ted"; // Exception if in strict mode
Object.seal( obj )
Object.isSealed( obj )
Sealing an object prevents other code from deleting, or changing the descriptors of, any of the object's properties - and from adding new properties.
Example Implementation:
Object.seal = function( obj ) {
var props = Object.getOwnPropertyNames( obj );
for ( var i = 0; i < props.length; i++ ) {
var desc = Object.getOwnPropertyDescriptor( obj, props[i] );
desc.configurable = false;
Object.defineProperty( obj, props[i], desc );
}
return Object.preventExtensions( obj );
};
You would seal an object if you want its existing properties to stay intact, without allowing for new additions, but while still allowing the user to write to or edit the properties.
Object.freeze( obj )
Object.isFrozen( obj )
Freezing an object is nearly identical to sealing it but with the addition of making the properties un-editable.
Example Implementation:
Object.freeze = function( obj ) {
var props = Object.getOwnPropertyNames( obj );
for ( var i = 0; i < props.length; i++ ) {
var desc = Object.getOwnPropertyDescriptor( obj, props[i] );
if ( "value" in desc ) {
desc.writable = false;
}
desc.configurable = false;
Object.defineProperty( obj, props[i], desc );
}
return Object.preventExtensions( obj );
};
Freezing an object is the ultimate form of lock-down. Once an object has been frozen it cannot be unfrozen - nor can it be tampered in any manner. This is the best way to make sure that your objects will stay exactly as you left them, indefinitely.
All together these changes are very exciting, they provide you with an unprecedented level of control over the objects that you produce. The best aspect, though, is that you will be able to use these features to build larger and more complex features in pure ECMAScript (such as building new DOM modules, or moving more browser APIs into pure-JavaScript). And since all the browsers are on board this is absolutely something that we can look forward to.
Tags: ecmascript, javascript
40 Comments on 'ECMAScript 5 Objects and Properties'
September 9th, 2008
Dion Almaer just posted the fourth episode of the Open Web Podcast in which we sat down with Allen Wirfs-Brock and Pratap lakshman and discussed ECMAScript and Internet Explorer 8.
The full release notes, from Dion, are below:
Allen Wirfs-Brock is the standards guy from Microsoft who sits and works on ECMA. Pratap Lakshman is from the JScript team, and works on the ECMAScript 3.1 committee.
They were gracious enough to joined us on the call to discuss the recent new around ECMAScript Harmony, how Microsoft feels about it, work that is being done in IE 8, performance, and tangents into ideas behind the Open Web.
You can download the podcast directly (OGG format too), or subscribe to the series, including via iTunes).
When a beta of IE 8 comes out, we all download it quickly to find out what was added, what wasn’t, and also making sure that our tricks weren’t taken away!
The guys talked about the Object.defineProperty support added in IE8b2. Allen clarified the implementation details on how this has been added to hosted DOM objects and not JavaScript “native” objects. The team has been working on “end to end performance” issues, and have done a lot of work on the DOM. They also mentioned how we should expect a new set of technology to run JavaScript in the future. It has to happen, they have to join the new performance world with TraceMonkey, V8, and SquirrelFish (Extreme).
The better environments to run JavaScript dovetail nicely with the ability to have JavaScript become more self-hosting, which was discussed in some depth. They also mentioned the goal in IE8 to have JavaScript developers not requiring to do special work for IE, and a bunch of bugs have been fixed around this core issue. What about core DOM event support? John brought up that with the addition of DOM prototypes, that this could be added by libraries, and that this hook could be used for a lot of good.
We were also led into discussing the disconnect between the ECMA standard and the W3C standard, primarily the DOM and JavaScript. Pratap was a little disturbed that the ECMAScript spec only had a few words on DOM, and some banter occurred around the role of JavaScript as being the One True Open Web language, or whether there is a place for the polyglots.
Recent podcasts
Tags: microsoft, ecmascript
5 Comments on 'Podcast: Microsoft on ECMAScript, IE 8'
August 14th, 2008
Historically one JavaScript property that's seen a lot of use (mostly due to its convenience) is that of __proto__. It's a quick-and-dirty way of accessing the original prototype property of the object's constructor function. For example, the following is true:
"test".__proto__ === String.
prototype
// Another alternative, not using __proto__
// Only works when constructor isn't changed
"test".constructor.prototype === String.prototype
This feature has been codified in the upcoming ECMAScript 3.1 specification as a new method: Object.getPrototypeOf(object) (and is implemented in the latest Firefox nightlies).
So how can we make use of this, now standardized, functionality?
instanceOf
If you wish you could implement your own version of the instanceof operator, using pure JavaScript.
function instanceOf(object, constructor
) {
while (object !=
null) {
if (object == constructor.
prototype)
return true;
object = Object.
getPrototypeOf(object
);
}
return false;
}
instanceOf("test", String);
instanceOf(true, Boolean);
In this example we traverse up the prototype chain, checking each constructor along the way. It's an effective method and allows for great expressiveness in our code.
Super Methods
We could use this function to call a super method, while doing some inheritance.
function Person
(){}
Person.prototype.kick = function(type){
alert(type + " kick!");
}
function Norris(){}
// Inherit properties from Person
Norris.prototype = new Person();
Norris.prototype.kick = function(){
Object.getPrototypeOf(this).kick("Roundhouse");
};
In the above code we use Object.getPrototypeOf(this) to tap in to the original, inherited, kick method. Since we have since overridden the method we don't have direct access to it, but using getPrototypeOf we can capture, and utilize, it again.
Cross-Browser Implementation
The obvious question now becomes: How do we begin using Object.getPrototypeOf today if most browsers don't have it implemented yet? In the meantime we can use something like the following code for some form of compatibility:
if ( typeof Object.getPrototypeOf !== "function" ) {
if ( typeof "test".__proto__ === "object" ) {
Object.getPrototypeOf = function(object){
return object.__proto__;
};
} else {
Object.getPrototypeOf = function(object){
// May break if the constructor has been tampered with
return object.constructor.prototype;
};
}
}
While it's not 100% spot-on (since the .constructor property is mutable on any object - it's fully possible that it could've been manipulated by the user at some point) the above code should serve as a "good enough" solution to tide you over until browsers have good ECMAScript 3.1 compatibility.
Why Object.getPrototypeOf?
A common question at this point (and one that's sure to come up often as new features start to trickle in from ECMAScript 3.1): Why is the method Object.getPrototypeOf("test") and not "test".getPrototypeOf() - or even just a property, like __proto__? While having a method, or property, on every object would certainly be more convenient to use it ends up being impractical for generalized use.
For example, take the following case into consideration:
var obj = { getPrototypeOf: "blah" };
Any attempt to call its getPrototypeOf method would end in failure, forcing the developer to always have to fall back to using the generalized Object.getPrototypeOf. Since most uses of getPrototypeOf would be required to work in the general case the fallback would always have to be used. Thus it's not necessary to include it as an extra property of every object.
Additionally, it makes it far easier to backport to old implementations since you no longer have to extend the Object prototype (Object.prototype.getPrototypeOf = ...;) which would've been bad in any case.
Tags: javascript, mozilla, ecmascript
17 Comments on 'Object.getPrototypeOf'
August 13th, 2008
There's been some turmoil in the world of ECMAScript.
While many are - even, at least, vaguely - familiar with the development of ECMAScript 4 the devil is in the details. I've blogged about ES4 extensively in the past - and even did a speaking tour last fall educating developers about its details and implementations, however, a lot has happened since that time.
The ECMAScript 4 specification development was very ad-hoc in nature (primarily tackled by Adobe, Mozilla, Opera, and Google): Implementors agreed upon a set of features that they wished to implement and a specification was molded out of the remaining consensus. Building a specification tailored by implementation is a very pragmatic means of reaching a reasonable result.
However there was a fundamental split related to how much of the specification should be implemented. Enter ECMAScript 3.1. This working group (lead by Microsoft and Yahoo) set out to implement some minor changes and bug fixes to ECMAScript 3 while remaining as a subset of full ECMAScript 4 functionality.
These two groups continued to work side-by-side but a struggle was inevitable. The ECMAScript 3.1 group wanted to add changes to the language that would affect the result of ECMAScript 4. This struggle over the past year finally came to a head this past month at the meeting of TC39 (the committee responsible for both ECMAScript 4 and ECMAScript 3.1). Dubbed "the Oslo meeting" this discussion between the two groups saw an ultimate conclusion: The two efforts had to be merged, otherwise neither one would succeed.
The result was a set of concessions and a re-focus on simplicity and pragmatic language additions. Brendan Eich detailed the result in a lengthy email to the ECMAScript 3.1 and ECMAScript 4 lists.
The important part is the new set of goals for this, now dubbed, ECMAScript Harmony project:
- Focus work on ECMAScript 3.1 with full collaboration of all parties, and target two interoperable implementations by early next year.
- Collaborate on the next step beyond ECMAScript 3.1, which will include syntactic extensions but which will be more modest than ECMAScript 4 in both semantic and syntactic innovation.
- Some ECMAScript 4 proposals have been deemed unsound for the Web, and are off the table for good: packages, namespaces and early binding. This conclusion is key to Harmony.
- Other goals and ideas from ECMAScript 4 are being rephrased to keep consensus in the committee; these include a notion of classes based on existing ES3 concepts combined with proposed ECMAScript 3.1 extensions.
This means a couple things: First, you can forget a lot of what you learned about ECMAScript 4, previously. Many of the complicated concepts contained in the language have been tossed. Instead there is a considerable amount of effort going in to making sure that new features will be easily duplicable through other means.
For example, ECMAScript 3.1 provides a new method - called Object.freeze() - which allows you to pass in an object and "freeze" it, preventing it from being modified any further. This is a subset of the functionality that is needed to implement classes in ECMAScript 4 (classes are immutable).
This means that classes will be a part of the new language but they will be defined as simply being syntactic sugar for a series of plain methods or conventions (such as using closures and Object.freeze to create a Class-like experience). Making sure that complex concepts break down into a simplified form will serve users well - giving them a considerable amount of leverage in using the language.
There is still some debate surrounding the remaining features of ECMAScript 4 - such as type annotations or if classes should support inheritance (and if they do, should the utilize the existing prototypal form of inheritance). A lot of this will become apparent over time.
The process that's gone into developing ECMAScript 4 is being adapted to suit ECMAScript 3.1 development as well. This means that there will be a runnable reference implementation for the language (with as much of the language written in the language itself, as possible - self-hosting code is quite cool).
Probably the most important development within all this is the codification of existing de-facto standards. For example, the concept of JavaScript getters and setters (implemented by Mozilla, Apple, and Opera) are going to be quickly fast-tracked into the specification (in the case of getters and setters they already have been). Seeing real-world code quickly make a bee-line for standardization is truly heartwarming. We'll probably see more of this for topics like 'let' and 'expression closures' - but which will arrive post-ECMAScript 3.1 (since they require new syntax).
There is still a significant amount of work left to do (both in the realm of specification and implementation) but there has been some important progress made here. Seeing an agreement between all of the largest players in the ECMAScript space (Mozilla, Microsoft, Apple, Opera, Google, Yahoo) is quite historic and will stand to serve users well.
--
I will be doing another Open Web Podcast tomorrow with Dion Almaer, Alex Russell, Brendan Eich, and Arun Ranganathan where we will be discussing ECMAScript Harmony.
Tags: ecmascript
59 Comments on 'ECMAScript Harmony'
June 10th, 2008
A very cool new utility has just been released by Olav Junker Kjær called Mascara which is an ECMAScript 4 to JavaScript translator (written in Python).
Using this utility you can begin writing ECMAScript 4 code today, receiving its full benefits (such as IDE integration and compile-time type-checking) while still being able to run the resulting code in all modern browsers.
A simple demonstration is up on the Mascara web site which provides a view into the translated source code, along with run-time (and inline) error messages.
A full break-down of the features currently supported are:
- Type verification
- Classes and inheritance, constructors, super initializers
- Static members
- Type inference from initialization
- Parameterized types, Map and Vector
- Union types
- Structural types
- Getters/setters
- Namespaces
- Nullable types
Definitely be aware, however, that while the above feature list is more than enough to get started there are still a a few items left to be implemented.
The most important question, when looking at the above code, should be: How do I begin using this today? Olav went ahead and made it easy to do IDE integration - even setting up instructions on how to integrate with Eclipse on Windows (he currently shows how to integrate using the JScript command-line interface, but it can easily be expanded). I'm quite excited by this prospect - having the ability to do compile-time type-checking and be able to succinctly write classes with inheritance will be a major boon to development.
Additionally, he provides information on how to do automatic CGI translation (naturally, you would want to do this only in a development environment).
He's continuing to provide frequent updates on the Mascara blog - be sure to follow along if you're interested in starting to use ECMAScript 4 sooner, rather than later.
Tags: javascript, ecmascript, python
13 Comments on 'Writing ECMAScript 4, Today'
April 22nd, 2008
With the recent talk of JavaScript 1.9 there's been some confusion as to what exactly that version means - especially in relation to other browsers. Here's a quick breakdown:
- IE 6-7 support JScript 5 (which is equivalent to ECMAScript 3, JavaScript 1.5)
- IE 8 supports JScript 6 (which is equivalent to ECMAScript 3, JavaScript 1.5 - more bug fixes over JScript 5)
- Firefox 1.0 supports JavaScript 1.5 (ECMAScript 3 equivalent)
- Firefox 1.5 supports JavaScript 1.6 (1.5 + Array Extras + E4X + misc.)
- Firefox 2.0 supports JavaScript 1.7 (1.6 + Generator + Iterators + let + misc.)
- Firefox 3.0 supports JavaScript 1.8 (1.7 + Generator Expressions + Expression Closures + misc.)
- The next version of Firefox will support JavaScript 1.9 (1.8 + To be determined)
- Opera supports a language that is equivalent to ECMAScript 3 + Getters and Setters + misc.
- Safari supports a language that is equivalent to ECMAScript 3 + Getters and Setters + misc.
It should be noted that the only browser that supports 'JavaScript' are Mozilla-based ones. However, all modern browsers support a version of ECMAScript - at least version 3. JavaScript 1.6-1.9 are just code names for the interim versions of ECMAScript (JavaScript on Gecko) that are leading up to JavaScript 2.0 (ECMAScript 4). Of course no other browser will support another JavaScript 1.6-1.9, since they aren't obligated to support JavaScript. However, that hasn't stopped browsers from implementing JavaScript features (such as getters and setters in Opera and Safari).
A big goal of Mozilla is to try implementing difficult ECMAScript features, helping to lead other browsers by example. By using these stepping-stone JavaScript 1.6-1.9 releases as a way to test out bug fixes and functionality both users, and browser vendors, can get a better picture of the changes that will be occurring in the language. This has been a big point in the development of JavaScript 2 (ECMAScript 4) - Mozilla was able to show, through demonstrable real-world usage, that certain features were safe to implement (generators, array comprehension, and getters and setters). Mozilla will be continuing this tradition with JavaScript 1.9, landing new features and bug fixes (the vast majority of which will be from the upcoming ECMAScript 4 specification) - helping to bring the newest version of JavaScript just a couple steps closer.
Tags: javascript, ecmascript
10 Comments on 'Versions of JavaScript'
April 16th, 2008
The feature set for Firefox 3 has long been frozen, and committed - it's well on its way to becoming a polished browser, at this point. It's time to start looking ahead, specifically, at the feature set of JavaScript in the next version of the browser.
Traditionally JavaScript 1.X releases (1.6, 1.7, 1.8, and now 1.9) have served to introduce new features into the language that help to pave the way towards its next major release. The size and scope of the features have, generally, varied - the importance of generators and iterators - or let statements - are, arguably, much more than, say, expression closures.
However, since the final feature set for ECMAScript 4 (JavaScript 2) has calmed down, with implementors starting to lay their code on the line, it's becoming easier to get a full picture of what will be happening in the near future of the language.
A few of us Mozilla folk will be meeting tomorrow at the ECMAScript 4 implementors meeting in Newton, MA to discuss what features, and bug fixes, should be pursued. I have a few that, I feel, are no-brainers like a builtin Function.prototype.bind and a native JSON encoder/decoder.
It's doubtful that we'll be able to land too much with this release (we're hoping to get it out as quickly as possible, post Firefox 3 - so don't expect too much) but, as always, input is appreciated. At the very least, I'll be able to let you know where your suggestions lie within the scope of the language. I should have an update after the meeting with a full re-cap of what was concluded.
Tags: mozilla, ecmascript, javascript, firefox
23 Comments on 'Planning JavaScript 1.9'
·
« Previous entries