ecmascript 5

Post on 08-Sep-2014

27.948 Views

Category:

Technology

3 Downloads

Preview:

Click to see full reader

DESCRIPTION

The new ECMAScript 5 standard brings on the table some very nice features you can use right away in the modern browsers. The presentation is a big overview of them.

TRANSCRIPT

ECMAScript 5

Damian Wielgosikvarjs.com

front-trends.com@varjs

Hey, what is that ECMAScript actually?

let’s create a simplest object ever

var obj = {};

let’s add a property to it

var obj = { foo : 1};

let’s read that property

var obj = { foo : 1};

obj.foo; // 1 - this is how we read a value from property "foo" of the object "obj"

let’s modify that property

var obj = { foo : 1};

obj.foo = 2;obj.foo; // 2

every object except null takes some stuff from

Object.prototype

var obj = {};typeof obj.hasOwnProperty; // "function"

var obj = {};obj.hasOwnProperty === Object.prototype.hasOwnProperty; // true

hasOwnProperty is a good example of Object.prototype

property

is there a way to create an object without

Object.prototype properties?

Object.create

var obj = Object.create(null); // ECMA 5 way

var obj = Object.create(null); // ECMA 5 waytypeof obj.hasOwnProperty; // "undefined"

Object.create(null) does not use Object.prototype

Object.create(null) - pure object

Object.create(null) you don’t get:

•.constructor•.toString•.toLocaleString•.valueOf•.hasOwnProperty•.isPrototypeOf•.propertyIsEnumerable

Object.create(null) - imagine null-like object with

allowed extensions

Dude, I want Object.prototype

Object.create - put a prototype you want to

inherit from as a first argument

var obj = Object.create({});typeof obj.hasOwnProperty; // "function"obj instanceof Object; // true

Hell yeah!

var obj = Object.create({});obj.__proto__.__proto__ === Object.prototype; // true (ES3 way)

btw. there is Object.isPrototypeOf

var obj = Object.create({});Object.prototype.isPrototypeOf(obj); // true

var obj = Object.create({});obj.__proto__.__proto__ === Object.prototype; // true (ES3 way)

same as

everything starts with Object.prototype, I’m sure you

lied!

var obj = Object.create(null);Object.prototype.isPrototypeOf(obj); // false

isPrototypeOf is even from ECMA 3!

Object.getPrototypeOf is a new stuff however...

var obj = Object.create({});Object.getPrototypeOf(obj) === obj.__proto__; // true

with Object.getPrototypeOf you simply forget about

non-standard obj.__proto__

var fn = function() {};fn.prototype.foobar = 1;

var obj = new fn();Object.getPrototypeOf(obj) === fn.prototype;

var obj = Object.create({});Object.prototype.isPrototypeOf(obj); // true

var obj = Object.create({});Object.getPrototypeOf(Object.getPrototypeOf(obj)) === Object.prototype; // true// no __proto__!

same as

Ok, you won. Tell me more about Object.create!

if (!Object.create) { Object.create = function (o) { if (arguments.length > 1) { throw new Error('Object.create implementation only accepts the first parameter.'); } function F() {}; F.prototype = o; return new F(); }; }

wow, we found a polyfill!

inheritance?

var animal = Object.create({ age : null, setAge: function(age) { this.age = age; }});

var bird = Object.create(animal);bird.setAge(10);bird.age; // 10

give me analogy, I still remember ECMA3

var Animal = function() {};Animal.prototype = { age : null, setAge: function(age) { this.age = age; }};

var Bird = function() {};Bird.prototype = new Animal();

var bird = new Bird();bird.setAge(10);bird.age; // 10

more analogies?

var Animal = function() {}; var obj = new Animal();

var obj2 = Object.create(Animal.prototype);

obj2.constructor === obj.constructor; // true

not enough, you know that

var obj = {};// does the same job asvar obj2 = Object.create(Object.prototype);

more ECMA5!

Object.defineProperty

how we used to add new properties

var obj = {};obj.myProperty = 100;

how we do it with defineProperty

var obj = {};Object.defineProperty(obj, "foobar", { value : 100, // default: undefined writable : true, // default: false enumerable : true, // default: false configurable : true // default: false});

obj.foobar; // 100

writable?!

var obj = {};Object.defineProperty(obj, "foobar", { value : 100, writable : false});

obj.foobar; // 100obj.foobar = 200;obj.foobar; // 100

writable: falseforget about changing

property’s value

enumerable?!

var obj = {};Object.defineProperty(obj, "foobar", { value : 100, enumerable : false});

for (var i in obj) { console.log(obj[i]);}// nothing happened

however...

var obj = {};Object.defineProperty(obj, "foobar", { value : 100, enumerable : true !});

for (var i in obj) { console.log(obj[i]);}// „foobar” !

configurable?!

var obj = {};Object.defineProperty(obj, "foobar", { value : 100, configurable : false});

delete obj.foobar; // falseobj.foobar; // 100

var obj = {};Object.defineProperty(obj, "foobar", { value : 100, configurable : false}); // it’s ok, we just defined a foobar property not to be configurable

Object.defineProperty(obj, "foobar", { configurable : true}); // throws a TypeError

Object.defineProperty(obj, "foobar", { writable : true}); // throws a TypeError

Object.defineProperty(obj, "foobar", { enumerable : true}); // throws a TypeError

Summary of descriptors

var obj = {}; obj.foobar = 100;

Object.defineProperty(obj, "foobar", { value : 100, writable : true, configurable : true, enumerable : true});

same as

Object.defineProperty(obj, "foobar", { value : 100});

Object.defineProperty(obj, "foobar", { value : 100, writable : false, configurable : false, enumerable : false});

same as

Summary of descriptors

IE8 allows you use it only with DOM objects

Oh, there are setters and getters

setters

var rect = { x: 5, y: 2};

Object.defineProperty(rect, "area", { set: function(value) { throw new Error("Cannot set a value"); }, get: function() { return this.x * this.y; }});

rect.area = -21; // Error: Cannot set a value

watch out

var rect = { x: 5, y: 2};

Object.defineProperty(rect, "area", { set: function(value) { throw new Error("Cannot set a value"); }, get: function() { return this.x * this.y; }, writable: false // TypeError: Invalid property. A property cannot both have accessors and be writable or have a value: #<Object>});

getters

var rect = { x: 5, y: 2};

Object.defineProperty(rect, "area", { set: function(value) { throw new Error("Cannot set a value"); }, get: function() { return this.x * this.y; }});

rect.area; // 10 (5 * 2 = 10)

Object.defineProperties

var obj = {};

Object.defineProperties(obj, { "firstname": { value: "Damian", writable: false }, "nickname": { value: "varjs", writable: false }});

obj.firstname; // "Damian"obj.nickname; // "varjs"

Object.defineProperties in other words

Object.defineProperties = function(obj, props) { for (var prop in props) { Object.defineProperty(obj, prop, props[prop]); }};

back to Object.create...

var obj = Object.create({}, { "foobar" : { value: 100, writable: true, enumerable: false }});

obj.foobar; // 100

Object.getOwnPropertyDescriptor

var obj = {};

Object.defineProperties(obj, { "firstname": { value: "Damian", writable: true }, "nickname": { value: "varjs", writable: true }});

obj.firstname; // "Damian"obj.nickname; // "varjs"

Object.getOwnPropertyDescriptor(obj, "firstname"); // Object { value="Damian", writable=true, enumerable=false, configurable=false}

Object.getOwnPropertyNames

works for arrays!

var arr = ["a", "b", "c"]; Object.getOwnPropertyNames(arr); // ["length", "0", "1", "2"]

works for objects!

var obj = { foo: "bar", barbar: "barbar"};

Object.getOwnPropertyNames(obj); // ["foo", "barbar"]

works even with not enumerable properties

var obj = {};Object.defineProperty(obj, "foobar", { enumerable: false});

Object.getOwnPropertyNames(obj); // ["foobar"]

Object.keys

var obj = { foo: 1, bar: 2, foobar: 3};

Object.keys(obj); // ["foo", "bar", "foobar"]

it returns only enumerables...

var obj = Object.create({}, { "foo" : { value: 100, enumerable: false ! }, "bar" : { value: 200, enumerable: true }});

Object.keys(obj); // ["bar"] !

no „foo” since it’s not enumerable

arrays?

var arr = [1, 2, 3];Object.keys(arr); // ["0", "1", "2"]

Polyfill?

if(!Object.keys) { Object.keys = function(o) { if (o !== Object(o)) { throw new TypeError('Object.keys called on non-object'); } var ret = []; var p; for (p in o) { if (Object.prototype.hasOwnProperty.call(o, p)) { ret.push(p); } } return ret; };}

Object.seal

var obj = { foo: 1};

Object.seal(obj);obj.myEvilProperty = 1337;obj.myEvilProperty; // undefined

It prevents new properties from being added to the sealed

object!

var obj = { foo: 1};

Object.seal(obj);Object.defineProperty(obj, "foo", { value: "boom" }); // throws a TypeError

Object.seal makes all the properties not configurable

var obj = { foo: 1};

Object.seal(obj);Object.defineProperty(obj, "foo", { get: function() { return "g"; } }); // throws a TypeError

var obj = { foo: 1};

Object.seal(obj);delete obj.foo; // does nothingobj.foo; // 1

Object.isSealed

var obj = { foo: 1};

Object.seal(obj);Object.isSealed(obj); // true

Object.freeze

well, you can do nothing

Freezes an object: that is, prevents new properties from being added to it; prevents existing properties from being removed; and prevents existing properties, or their enumerability, configurability, or writability, from being changed. In essence the object is made effectively immutable. The method returns the object being frozen.

- MDN - the best source of knowledge

https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Object/freeze

var obj = { foo: 1};

Object.freeze(obj);obj.myEvilProperty = 1337;obj.myEvilProperty; // undefined

var obj = { foo: 1};

Object.freeze(obj);obj.foo = 1337;obj.foo; // 1

var obj = { foo: 1};

Object.freeze(obj);Object.defineProperty(obj, "foo", { value: "boom" }); // throws a TypeError

var obj = { foo: 1};

Object.freeze(obj);delete obj.foo; // false

Object.isFrozen

var obj = { foo: 1};

Object.freeze(obj);Object.isFrozen(obj); // true

Object.preventExtensions

Simply, you can’t add new properties

var obj = { foo: 1};

Object.preventExtensions(obj);obj.myEvilProperty = 1337;obj.myEvilProperty; // undefined

How it’s different than Object.seal?

You can remove properties!

var obj = { foo: 1};

Object.seal(obj);delete obj.foo; // false

var obj2 = { bar: 2};

Object.preventExtensions(obj2);delete obj2.bar; // true

You can change descriptors!

var obj = { foo: 1};

Object.seal(obj);Object.defineProperty(obj, "foo", { enumerable: false}); // throws a TypeError

var obj2 = { bar: 2};

Object.preventExtensions(obj2);Object.defineProperty(obj2, "bar", { enumerable: false}); // it's ok

Object.isExtensible

var obj = { foo: 1};

Object.preventExtensions(obj);Object.isExtensible(obj); // false

More ECMAScript 5?

Array.prototype.reduceRightArray.prototype.reduceArray.prototype.filterArray.prototype.map

Array.prototype.forEachArray.prototype.someArray.prototype.every

Array.prototype.lastIndexOfArray.prototype.indexOf

More?!

Function.prototype.bind

Function.prototype.bind = function(){ var fn = this, args = Array.prototype.slice.call(arguments), object = args.shift(); return function(){ return fn.apply(object, args.concat(Array.prototype.slice.call(arguments))); }; };

Date.now()

Date.now() === +new Date()

Date.now(); // 1318362644511

Array.isArray

We used to use...

Object.prototype.toString.call([]) === "[object Array]";

Now we use...

Array.isArray(null); // falseArray.isArray([]); // trueArray.isArray({ length: 1 }); // false

String.prototype.trim

We used to use...

String.prototype.trim = function() { return this.replace(/^\s+|\s+$/, "");}

"my string ".trim(); // "my string"

Now we use...

"my string ".trim(); // "my string"

In ECMAScript 5 we have...

Native JSON!

typeof JSON === "object"; // true

var foo = {}; foo.bar = "new property"; foo.baz = 3; var JSONfoo = JSON.stringify(foo); // {"bar":"new property","baz":3}var foo = JSON.parse(JSONfoo); // yet again we have an object

strict mode

"use strict";eval = 17;arguments++;++eval;var obj = { set p(arguments) { } };var eval;try { } catch (arguments) { }function x(eval) { }function arguments() { }var y = function eval() { };var f = new Function("arguments", "'use strict'; return 17;");

all of these throw errors

"use strict";var fn = function() { return arguments.callee; }; fn();

more: https://developer.mozilla.org/en/JavaScript/Strict_mode

top related