KEMBAR78
Say Hello To Ecmascript 5 | KEY
Say hello to
ECMAScript 5


    by @kangax
What is ECMAScript?
•   Originated as JavaScript (actually, Mocha)
•   Standardized by ECMA International
•   JavaScript, JScript, ActionScript
•   5th edition in Dec ‘09
ECMAScript         5
 New meta-level control

Additions to language API

 Refinements, bug fixes

      Strict mode
New meta-level control
New meta-level control

{
      foo:   "string",
      bar:   3.14,
    "baz":   true,
        5:   [1,2,3]
}
New meta-level control

{
      foo:   "string",
      bar:   3.14,
    "baz":   true,
        5:   [1,2,3]
}
New meta-level control

{
      foo:     "string",
      bar:     3.14,
    "baz":     true,
        5:     [1,2,3]
}



             [[Writable]]
             [[Enumerable]]
             [[Configurable]]
New meta-level control

  [[Writable]] [[Enumerable]] [[Configurable]]


var object = { key: "value" };

// when writable
object.property = "new value";
object.property; // "new value"

// not writable
object.property = "new value";
object.property; // "value"
New meta-level control

  [[Writable]] [[Enumerable]] [[Configurable]]


var object = { key: "value" };

var keys = [];
for (var prop in object) {
  keys.push(prop);
}

keys;
// enumerable — ["key"]
// non-enumerable — []
New meta-level control

  [[Writable]] [[Enumerable]] [[Configurable]]


var object = { key: "value" };

delete object.key;

// configurable
object.key; // undefined

// non-configurable
object.key; // "value"
New meta-level control
     Property descriptors to the rescue


Object.defineProperty
Object.defineProperties
Object.create
New meta-level control
     Property descriptors to the rescue


Object.defineProperty({}, "key", {

 value: "foo bar baz",

  writable: true,
  enumerable: true,
  configurable: true
});
New meta-level control
     Property descriptors to the rescue


Object.defineProperty({}, "key", {

  value: "foo bar baz",

  writable: true,
  enumerable: true,
  configurable: true
});
New meta-level control
      Property descriptors to the rescue


Object.defineProperty({}, "key", {

  value: "foo bar baz",

  writable: true,
  enumerable: true,
  configurable: true
});                              Property descriptor
New meta-level control
      Property descriptors to the rescue


Object.defineProperty({}, "key", {

  value: "foo bar baz",

  writable: true,
  enumerable: true,
  configurable: true
});
New meta-level control
     Property descriptors to the rescue


Object.defineProperty({}, "key", {

 value: "foo bar baz",

  writable: true,
  enumerable: true,
  configurable: true
});
New meta-level control
     Property descriptors to the rescue


Object.defineProperty({}, "key", {

 value: "foo bar baz",

  writable: true,
  enumerable: true,
  configurable: true
});


               { key: "foo bar baz" }
New meta-level control
      Property descriptors to the rescue


Object.defineProperties({}, {
  key1: {
    value: "foo bar baz",
    enumerable: true
  },
  key2: {
    value: "foo bar baz",
    configurable: true
  }
});
New meta-level control
      Property descriptors to the rescue


Object.defineProperties({}, {
  key1: {
    value: "foo bar baz",
    enumerable: true
  },                       Property descriptors
  key2: {
    value: "trololololo",
    configurable: true
  }
});
New meta-level control
     Property descriptors to the rescue


Object.defineProperties({}, {
  key1: {
    value: "foo bar baz",
    enumerable: true
  },
  key2: {
    value: "trololololo",
    configurable: true
  }
});
New meta-level control
     Property descriptors to the rescue


Object.defineProperties({}, {
  key1: {
    value: "foo bar baz"
  },
  key2: {
    value: "trololololo"
  }
});
                    {
                      key1: "foo bar baz",
                      key2: "trololololo"
                    }
New meta-level control
     Property descriptors to the rescue


Object.create(parentObject, {
  key1: {
    value: "foo bar baz",
    enumerable: true
  },
  key2: {
    value: "foo bar baz",
    configurable: true
  }
});
New meta-level control
      Property descriptors to the rescue


Object.create(parentObject, {
  key1: {
    value: "foo bar baz",
    enumerable: true
  },                       Property descriptors
  key2: {
    value: "foo bar baz",
    configurable: true
  }
});
New meta-level control
      Property descriptors to the rescue


Object.create(parentObject, {
  key1: {
    value: "foo bar baz"
  },
  ...
});
                          [[Prototype]]
             {
                 key1: "foo bar baz",
                 key2: "trololololo"
             }
New meta-level control
                Examples


Object.defineProperty(Object.prototype,
  "clone", {
    value: function(props){
      return Object.create(this, props);
    }
  }
);
New meta-level control
                Examples


Object.defineProperty(Object.prototype,
  "clone", {
    value: function(props){
      return Object.create(this, props);
    }
  }
);
New meta-level control
                Examples

var john = {
  name: "John",
  skill: "Javascript"
};

var mike = john.clone({
  name: { value: "Mike" }
});

mike.name; // "Mike"
mike.skill; // "Javascript"
New meta-level control
                Examples

var john = {
  name: "John",
  skill: "Javascript"
};

var mike = john.clone({
  name: { value: "Mike" }
});

mike.name; // "Mike"
mike.skill; // "Javascript" (inherited)
New meta-level control
                Examples

var john = {
  name: "John",
  skill: "Javascript"
};

var mike = john.clone({
  name: { value: "Mike" }
});

for (var prop in mike) {
  console.log(prop); // "name" and "skill"
}
Additions to language API
Additions to language API

1) String.prototype.trim

 " hello world     ".trim(); // "hello world"

 var person = {
   name: " Joe ",
   trim: String.prototype.trim,
   toString: function(){
     return this.name;
   }
 };

 person.trim(); "Joe"
Additions to language API

1) String.prototype.trim

 " hello world     ".trim(); // "hello world"

 var person = {
   name: " Joe ",
   trim: String.prototype.trim,
   toString: function(){
     return this.name;
   }
 };

 person.trim(); "Joe"
Additions to language API


2) Array.prototype extensions

  [1,2,3].map(function(value){
    return value * 2;
  });

  // [2,4,6]
Additions to language API


2) Array.prototype extensions

  [1,2,3].map(function(value){
    return value * 2;
  });

  // [2,4,6]
Additions to language API


2) Array.prototype extensions

  [1,2,3,4,5,6].filter(function(value){
    return value > 3;
  });

  // [4,5,6]
Additions to language API


2) Array.prototype extensions

  [1,2,3,4,5,6].filter(function(value){
    return value > 3;
  });

  // [4,5,6]
Additions to language API


2) Array.prototype extensions

  [1,2,3,4,5,3].indexOf(3); // 2
  [1,2,3,4,5,3].lastIndexOf(3); // 5
Additions to language API


2) Array.prototype extensions

  [1,2,3,4,5,3].indexOf(3); // 2
  [1,2,3,4,5,3].lastIndexOf(3); // 5
Additions to language API


2) Array.prototype extensions

  [1,2,3,4].reduce(function(prev, curr){
    return prev + curr;
  });

  // 10

  1+2 -> 3
  3+3 -> 6
  6+4 -> 10
Additions to language API


2) Array.prototype extensions

  [1,2,3,4].reduce(function(prev, curr){
    return prev + curr;
  });

  // 10

  1+2 → 3
  3+3 → 6
  6+4 → 10
Additions to language API


2) Array.prototype extensions

  function sum(){
    return this.reduce(function(prev, curr){
      return prev + curr;
    });
  }
  Object.defineProperty(
    Array.prototype, "sum", { value: sum });

  [1,2,3].sum(); // 6
  [1,2,3,4,5].sum() // 15
Additions to language API


2) Array.prototype extensions

  function sum(){
    return this.reduce(function(prev, curr){
      return prev + curr;
    });
  }
  Object.defineProperty(
    Array.prototype, "sum", { value: sum });

  [1,2,3].sum(); // 6
  [1,2,3,4,5].sum() // 15
Refinements, bug fixes
Refinements, bug fixes


1) undefined, NaN, Infinity are non-writable

      if (undefined == foo){
        foo = { ... };
      }
Refinements, bug fixes


1) undefined, NaN, Infinity are non-writable

      if (undefined = foo){
        foo = { ... };
      }

      undefined; // foo (!)

      if (undefined == bar) {
        // might never be created
        bar = { ... };
      }
Refinements, bug fixes


2) reserved words as property names

   var myApp = {
     export: [module1, module2]
   };

   var chevy = new Car();
   chevy.class = "classic";
Refinements, bug fixes


      2) reserved words as property names

         var myApp = {
           export: [module1, module2] // boom!
         };
ES3
         var chevy = new Car();
         chevy.class = "classic"; // boom!
Refinements, bug fixes


      2) reserved words as property names

         var myApp = {
           export: [module1, module2] // OK!
         };
ES5
         var chevy = new Car();
         chevy.class = "classic"; // OK!
Refinements, bug fixes


    3) Tamper-proof built-ins

function Array(){
  alert("Stole your data!");
}

var privateData = [...];

// Vulnerable browsers — e.g. FF2
Refinements, bug fixes


    3) Tamper-proof built-ins

function Array(){
  alert("Stole your data!");
}

var privateData = [...];

// Vulnerable browsers — e.g. FF2
Refinements, bug fixes


          3) Tamper-proof built-ins

      function Array(){
        alert("Stole your data!");
      }

      var privateData = [...];


ES3    Data stolen   ES5   Built-in function is called
Strict mode
Strict mode


“use strict”
Strict mode
styles = {
  bodyColor: “red”,
  bodyBgColor: “green”,
  bodyColor: “yellow”
}
setTimeout(function(x, eval, x){
  with(document) {
    if (!body) {
      setTimeout(arguments.callee, 10);
    }
    else {
      body.style.color = styles.bodyColor;
    }
  }
}, 10);
Strict mode
styles = {
  color: “red”,
  bgColor: “green”,
                      Undeclared assignment
  color: “yellow”
}
setTimeout(function(x, eval, x){
  with(document) {
    if (!body) {
      setTimeout(arguments.callee, 10);
    }
    else {
      body.style.color = styles.color;
    }
  }
}, 10);
Strict mode
styles = {
  color: “red”,         Repeating property
  bgColor: “green”,
                             names
  color: “yellow”
}
setTimeout(function(x, eval, x){
  with(document) {
    if (!body) {
      setTimeout(arguments.callee, 10);
    }
    else {
      body.style.color = styles.color;
    }
  }
}, 10);
Strict mode
styles = {
  color: “red”,
  bgColor: “green”,
                      eval as argument name
  color: “yellow”
}
setTimeout(function(x, eval, x){
  with(document) {
    if (!body) {
      setTimeout(arguments.callee, 10);
    }
    else {
      body.style.color = styles.color;
    }
  }
}, 10);
Strict mode
styles = {
  color: “red”,         repeating argument
  bgColor: “green”,
                               names
  color: “yellow”
}
setTimeout(function(x, eval, x){
  with(document) {
    if (!body) {
      setTimeout(arguments.callee, 10);
    }
    else {
      body.style.color = styles.color;
    }
  }
}, 10);
Strict mode
styles = {
  color: “red”,
  bgColor: “green”,
                          with statement
  color: “yellow”
}
setTimeout(function(x, eval, x){
  with(document) {
    if (!body) {
      setTimeout(arguments.callee, 10);
    }
    else {
      body.style.color = styles.color;
    }
  }
}, 10);
Strict mode
styles = {
  color: “red”,
  bgColor: “green”,
                         arguments.callee
  color: “yellow”
}
setTimeout(function(x, eval, x){
  with(document) {
    if (!body) {
      setTimeout(arguments.callee, 10);
    }
    else {
      body.style.color = styles.color;
    }
  }
}, 10);
Browser support




http://kangax.github.com/es5-compat-table/
References

ECMA-262 5th ed. specification
http://www.ecma-international.org/publications/standards/Ecma-262.htm


ECMA-262 3rd ed. unofficial HTML version
http://bclary.com/2004/11/07/


es-discuss mailing lists
http://mail.mozilla.org/listinfo/es-discuss/
http://mail.mozilla.org/listinfo/es5-discuss/


comp.lang.javascript (here be dragons)
http://groups.google.com/group/comp.lang.javascript/
Thank you!




  by @kangax

Say Hello To Ecmascript 5

  • 1.
  • 2.
    What is ECMAScript? • Originated as JavaScript (actually, Mocha) • Standardized by ECMA International • JavaScript, JScript, ActionScript • 5th edition in Dec ‘09
  • 3.
    ECMAScript 5 New meta-level control Additions to language API Refinements, bug fixes Strict mode
  • 4.
  • 5.
    New meta-level control { foo: "string", bar: 3.14, "baz": true, 5: [1,2,3] }
  • 6.
    New meta-level control { foo: "string", bar: 3.14, "baz": true, 5: [1,2,3] }
  • 7.
    New meta-level control { foo: "string", bar: 3.14, "baz": true, 5: [1,2,3] } [[Writable]] [[Enumerable]] [[Configurable]]
  • 8.
    New meta-level control [[Writable]] [[Enumerable]] [[Configurable]] var object = { key: "value" }; // when writable object.property = "new value"; object.property; // "new value" // not writable object.property = "new value"; object.property; // "value"
  • 9.
    New meta-level control [[Writable]] [[Enumerable]] [[Configurable]] var object = { key: "value" }; var keys = []; for (var prop in object) { keys.push(prop); } keys; // enumerable — ["key"] // non-enumerable — []
  • 10.
    New meta-level control [[Writable]] [[Enumerable]] [[Configurable]] var object = { key: "value" }; delete object.key; // configurable object.key; // undefined // non-configurable object.key; // "value"
  • 11.
    New meta-level control Property descriptors to the rescue Object.defineProperty Object.defineProperties Object.create
  • 12.
    New meta-level control Property descriptors to the rescue Object.defineProperty({}, "key", { value: "foo bar baz", writable: true, enumerable: true, configurable: true });
  • 13.
    New meta-level control Property descriptors to the rescue Object.defineProperty({}, "key", { value: "foo bar baz", writable: true, enumerable: true, configurable: true });
  • 14.
    New meta-level control Property descriptors to the rescue Object.defineProperty({}, "key", { value: "foo bar baz", writable: true, enumerable: true, configurable: true }); Property descriptor
  • 15.
    New meta-level control Property descriptors to the rescue Object.defineProperty({}, "key", { value: "foo bar baz", writable: true, enumerable: true, configurable: true });
  • 16.
    New meta-level control Property descriptors to the rescue Object.defineProperty({}, "key", { value: "foo bar baz", writable: true, enumerable: true, configurable: true });
  • 17.
    New meta-level control Property descriptors to the rescue Object.defineProperty({}, "key", { value: "foo bar baz", writable: true, enumerable: true, configurable: true }); { key: "foo bar baz" }
  • 18.
    New meta-level control Property descriptors to the rescue Object.defineProperties({}, { key1: { value: "foo bar baz", enumerable: true }, key2: { value: "foo bar baz", configurable: true } });
  • 19.
    New meta-level control Property descriptors to the rescue Object.defineProperties({}, { key1: { value: "foo bar baz", enumerable: true }, Property descriptors key2: { value: "trololololo", configurable: true } });
  • 20.
    New meta-level control Property descriptors to the rescue Object.defineProperties({}, { key1: { value: "foo bar baz", enumerable: true }, key2: { value: "trololololo", configurable: true } });
  • 21.
    New meta-level control Property descriptors to the rescue Object.defineProperties({}, { key1: { value: "foo bar baz" }, key2: { value: "trololololo" } }); { key1: "foo bar baz", key2: "trololololo" }
  • 22.
    New meta-level control Property descriptors to the rescue Object.create(parentObject, { key1: { value: "foo bar baz", enumerable: true }, key2: { value: "foo bar baz", configurable: true } });
  • 23.
    New meta-level control Property descriptors to the rescue Object.create(parentObject, { key1: { value: "foo bar baz", enumerable: true }, Property descriptors key2: { value: "foo bar baz", configurable: true } });
  • 24.
    New meta-level control Property descriptors to the rescue Object.create(parentObject, { key1: { value: "foo bar baz" }, ... }); [[Prototype]] { key1: "foo bar baz", key2: "trololololo" }
  • 25.
    New meta-level control Examples Object.defineProperty(Object.prototype, "clone", { value: function(props){ return Object.create(this, props); } } );
  • 26.
    New meta-level control Examples Object.defineProperty(Object.prototype, "clone", { value: function(props){ return Object.create(this, props); } } );
  • 27.
    New meta-level control Examples var john = { name: "John", skill: "Javascript" }; var mike = john.clone({ name: { value: "Mike" } }); mike.name; // "Mike" mike.skill; // "Javascript"
  • 28.
    New meta-level control Examples var john = { name: "John", skill: "Javascript" }; var mike = john.clone({ name: { value: "Mike" } }); mike.name; // "Mike" mike.skill; // "Javascript" (inherited)
  • 29.
    New meta-level control Examples var john = { name: "John", skill: "Javascript" }; var mike = john.clone({ name: { value: "Mike" } }); for (var prop in mike) { console.log(prop); // "name" and "skill" }
  • 30.
  • 31.
    Additions to languageAPI 1) String.prototype.trim " hello world ".trim(); // "hello world" var person = { name: " Joe ", trim: String.prototype.trim, toString: function(){ return this.name; } }; person.trim(); "Joe"
  • 32.
    Additions to languageAPI 1) String.prototype.trim " hello world ".trim(); // "hello world" var person = { name: " Joe ", trim: String.prototype.trim, toString: function(){ return this.name; } }; person.trim(); "Joe"
  • 33.
    Additions to languageAPI 2) Array.prototype extensions [1,2,3].map(function(value){ return value * 2; }); // [2,4,6]
  • 34.
    Additions to languageAPI 2) Array.prototype extensions [1,2,3].map(function(value){ return value * 2; }); // [2,4,6]
  • 35.
    Additions to languageAPI 2) Array.prototype extensions [1,2,3,4,5,6].filter(function(value){ return value > 3; }); // [4,5,6]
  • 36.
    Additions to languageAPI 2) Array.prototype extensions [1,2,3,4,5,6].filter(function(value){ return value > 3; }); // [4,5,6]
  • 37.
    Additions to languageAPI 2) Array.prototype extensions [1,2,3,4,5,3].indexOf(3); // 2 [1,2,3,4,5,3].lastIndexOf(3); // 5
  • 38.
    Additions to languageAPI 2) Array.prototype extensions [1,2,3,4,5,3].indexOf(3); // 2 [1,2,3,4,5,3].lastIndexOf(3); // 5
  • 39.
    Additions to languageAPI 2) Array.prototype extensions [1,2,3,4].reduce(function(prev, curr){ return prev + curr; }); // 10 1+2 -> 3 3+3 -> 6 6+4 -> 10
  • 40.
    Additions to languageAPI 2) Array.prototype extensions [1,2,3,4].reduce(function(prev, curr){ return prev + curr; }); // 10 1+2 → 3 3+3 → 6 6+4 → 10
  • 41.
    Additions to languageAPI 2) Array.prototype extensions function sum(){ return this.reduce(function(prev, curr){ return prev + curr; }); } Object.defineProperty( Array.prototype, "sum", { value: sum }); [1,2,3].sum(); // 6 [1,2,3,4,5].sum() // 15
  • 42.
    Additions to languageAPI 2) Array.prototype extensions function sum(){ return this.reduce(function(prev, curr){ return prev + curr; }); } Object.defineProperty( Array.prototype, "sum", { value: sum }); [1,2,3].sum(); // 6 [1,2,3,4,5].sum() // 15
  • 43.
  • 44.
    Refinements, bug fixes 1)undefined, NaN, Infinity are non-writable if (undefined == foo){ foo = { ... }; }
  • 45.
    Refinements, bug fixes 1)undefined, NaN, Infinity are non-writable if (undefined = foo){ foo = { ... }; } undefined; // foo (!) if (undefined == bar) { // might never be created bar = { ... }; }
  • 46.
    Refinements, bug fixes 2)reserved words as property names var myApp = { export: [module1, module2] }; var chevy = new Car(); chevy.class = "classic";
  • 47.
    Refinements, bug fixes 2) reserved words as property names var myApp = { export: [module1, module2] // boom! }; ES3 var chevy = new Car(); chevy.class = "classic"; // boom!
  • 48.
    Refinements, bug fixes 2) reserved words as property names var myApp = { export: [module1, module2] // OK! }; ES5 var chevy = new Car(); chevy.class = "classic"; // OK!
  • 49.
    Refinements, bug fixes 3) Tamper-proof built-ins function Array(){ alert("Stole your data!"); } var privateData = [...]; // Vulnerable browsers — e.g. FF2
  • 50.
    Refinements, bug fixes 3) Tamper-proof built-ins function Array(){ alert("Stole your data!"); } var privateData = [...]; // Vulnerable browsers — e.g. FF2
  • 51.
    Refinements, bug fixes 3) Tamper-proof built-ins function Array(){ alert("Stole your data!"); } var privateData = [...]; ES3 Data stolen ES5 Built-in function is called
  • 52.
  • 53.
  • 54.
    Strict mode styles ={ bodyColor: “red”, bodyBgColor: “green”, bodyColor: “yellow” } setTimeout(function(x, eval, x){ with(document) { if (!body) { setTimeout(arguments.callee, 10); } else { body.style.color = styles.bodyColor; } } }, 10);
  • 55.
    Strict mode styles ={ color: “red”, bgColor: “green”, Undeclared assignment color: “yellow” } setTimeout(function(x, eval, x){ with(document) { if (!body) { setTimeout(arguments.callee, 10); } else { body.style.color = styles.color; } } }, 10);
  • 56.
    Strict mode styles ={ color: “red”, Repeating property bgColor: “green”, names color: “yellow” } setTimeout(function(x, eval, x){ with(document) { if (!body) { setTimeout(arguments.callee, 10); } else { body.style.color = styles.color; } } }, 10);
  • 57.
    Strict mode styles ={ color: “red”, bgColor: “green”, eval as argument name color: “yellow” } setTimeout(function(x, eval, x){ with(document) { if (!body) { setTimeout(arguments.callee, 10); } else { body.style.color = styles.color; } } }, 10);
  • 58.
    Strict mode styles ={ color: “red”, repeating argument bgColor: “green”, names color: “yellow” } setTimeout(function(x, eval, x){ with(document) { if (!body) { setTimeout(arguments.callee, 10); } else { body.style.color = styles.color; } } }, 10);
  • 59.
    Strict mode styles ={ color: “red”, bgColor: “green”, with statement color: “yellow” } setTimeout(function(x, eval, x){ with(document) { if (!body) { setTimeout(arguments.callee, 10); } else { body.style.color = styles.color; } } }, 10);
  • 60.
    Strict mode styles ={ color: “red”, bgColor: “green”, arguments.callee color: “yellow” } setTimeout(function(x, eval, x){ with(document) { if (!body) { setTimeout(arguments.callee, 10); } else { body.style.color = styles.color; } } }, 10);
  • 61.
  • 62.
    References ECMA-262 5th ed.specification http://www.ecma-international.org/publications/standards/Ecma-262.htm ECMA-262 3rd ed. unofficial HTML version http://bclary.com/2004/11/07/ es-discuss mailing lists http://mail.mozilla.org/listinfo/es-discuss/ http://mail.mozilla.org/listinfo/es5-discuss/ comp.lang.javascript (here be dragons) http://groups.google.com/group/comp.lang.javascript/
  • 63.
    Thank you! by @kangax