[SOLVED] android redefine VS ES5

$25

File Name: android_redefine_VS_ES5.zip
File Size: 216.66 KB

5/5 - (1 vote)

redefine VS ES5
===============

#### Create A Null Object

// redefine
var o = redefine.from(null);

// ES5
var o = Object.create(null);

#### Add Properties During Creation

// redefine
var o = redefine.from(null, {
name: object,
toString: function () {
return Hi, I am + this.name;
}
});

// ES5
var o = Object.create(null, {
name: {
value: object
},
toString: {
value: function () {
return Hi, I am + this.name;
}
}
});

#### Add Configurable + Writable Properties During Creation

// redefine
var o = redefine.from(null, {
name: object,
toString: function () {
return Hi, I am + this.name;
}
}, {
configurable : true,
writable: true
});

// ES5
var o = Object.create(null, {
name: {
configurable: true,
writable: true,
value: object
},
toString: {
configurable: true,
writable: true,
value: function () {
return Hi, I am + this.name;
}
}
});

#### Add A Getter/Setter

// redefine
var o = redefine.from({}, {
bday: Date.now(),
age: redefine.as({
set: function () {
throw you cannot set your age;
},
get: function () {
return parseInt(
(Date.now() this.bday) /
(1000 * 60 * 60 * 24 * 365)
); // I know, no leap year
}
})
});

// ES5
var o = Object.create({}, {
bday: {
value: Date.now()
},
age: {
set: function () {
throw you cannot set your age;
},
get: function () {
return parseInt(
(Date.now() this.bday) /
(1000 * 60 * 60 * 24 * 365)
); // I know, no leap year
}
}
});

#### Real World Example: An Emitter Class
This a simplified `Emitter` class with a logic optimized to save some memory and GC cycle.

// generic basic Emitter constructor
function Emitter(){}
function emit(callback) {
// just a recycled function
callback(this);
}

This is how we can define the prototype of the `Emitter` class.

// redefine
redefine(
Emitter.prototype,
{
emit: function (type, data) {
if (type in this._handlers) {
this._handlers[type].forEach(emit, data);
}
return this;
},
on: function (type, handler) {
var list = this._getList(type);
list.indexOf(handler) < 0 && list.push(handler);return this;},off: function (type, handler) {var list = this._getList(type),i = list.indexOf(handler);if (-1 < i) {list.splice(i, 1);if (!list.length) {delete this._handlers[type];if (!Object.keys(this._handler).length) {delete this._handlers;}}}return this;},_getList: function (type) {return this._handlers[type] || (this._handlers[type] = []);},_handlers: redefine.later(function(){return {};})});The pattern used for the `_handlers` property only is an inherited getter replaced on demand with a direct property access, explained in details in [The Power Of Getters](http://webreflection.blogspot.com/2013/01/the-power-of-getters.html) post.Long story short: we can create 100 instances of `Emitter` and the amount of extra objects will be exactly `100` instead of `200` considering a handler created during initialization.With this pattern, only when the `_handlers` object is needed is created once per instance and set as property to avoid calling the getter per each access.When listeners are removed, both Array used as type list and `_handlers` are removed, if empty. In order to obtain the same behavior in ES5:// ES5Object.defineProperties(Emitter.prototype,{emit: {value: function (type, data) {if (type in this._handlers) {this._handlers[type].forEach(emit, data);}return this;}},on: {value: function (type, handler) {var list = this._getList(type);list.indexOf(handler) < 0 && list.push(handler);return this;},}off: {value: function (type, handler) {var list = this._getList(type),i = list.indexOf(handler);if (-1 < i) {list.splice(i, 1);if (!list.length) {delete this._handlers[type];if (!Object.keys(this._handler).length) {delete this._handlers;}}}return this;}},_getList: {value: function (type) {return this._handlers[type] || (this._handlers[type] = []);}},_handlers: {get: function () {Object.defineProperty(this, “_handlers”, {configurable: true,value: {}});return this._handlers;}}});#### Real World Example: A Safer DefinitionWhile `Object.defineProperties(object, descriptorsList)` second argument loops only through `hasOwnProperty(key)`, once it comes to property definition, and the same is for `Object.defineProperty(obj, key, descriptor)`, the object used to described the property looks up for inherited properties too and consider them.Even if defaults are `{writable: false, enumerable: false, configurable: false}`, it’s easy to make every property `enumerable` and `configurable` simply doing this:Object.prototype.configurable = true;Object.prototype.enumerable = true;After above malicious piece of code, if you think a constant variable defined like this cannot be changed you are wrong:Object.defineProperty(window, “myLibrary”, {value:myLibrary});It is necessary indeed to ensure that defaults are written as well, making defaults meaningless because of inheritance, but even worse, if a malicious code will write `Object.prototype.writable = true` and there are getters or setters involved, these will all throw an exception because `writable` does not accept getters or setters.##### How To Prevent Problems in ES5In ES5 every descriptor should inherit from `null` otherwise no descriptor will be immune from possible attacks.Here an example of few problems we might want to avoid:// set up the nasty environmentObject.prototype.configurable =Object.prototype.enumerable =Object.prototype.writable = true;// verify that there are actually problemstry {Object.defineProperty(this, “problem”, {get: function () {return “we gonna have bad time”;}});} catch(o_O) {console.log(“ouch!”);Object.defineProperty(this, “problem”, {value:true});console.log(this.propertyIsEnumerable(“problem”)); // truethis.problem = {}; // no problemsdelete this.problem; // true again}Accordingly, every single descriptor should be created via `Object.crete(null)` so our code should look likefunction descriptor(object) {// now don’t take this wrong// but this function is almost// as big as the whole redefine.js library// I would not go through this patternfor (varnullDescriptor = Object.create(null),properties = [“configurable”,”enumerable”,”writable”,”get”,”set”,”value”],i = properties.length; i–;object.hasOwnProperty(properties[i]) && (nullDescriptor[properties[i]] = object[properties[i]]));return nullDescriptor;}Object.defineProperty(this, “problem”, descriptor({value: “now we talk”}));this.propertyIsEnumerable(“problem”); // falsethis.problem = {}; // nopedelete this.problem; // falsethis.problem; // “now we talk”Got it? Now …##### How To Prevent Problems in redefine.jsredefine(this, “problem”, “solved”);this.propertyIsEnumerable(“problem”); // falsethis.problem = {}; // nopedelete this.problem; // falsethis.problem; // “solved”If you are wondering about **performance** there are many things to consider behind `redefine.js` and one of these is that performance are really good for what it offers.While is usually slightly slower on desktop, `redefine.js` is [almost as fast in older Android 2.3 devices](http://jsperf.com/redefine-js) where performance matters the most.`redefine.js` is indeed suitable for mobile phones, even if quite old!

Reviews

There are no reviews yet.

Only logged in customers who have purchased this product may leave a review.

Shopping Cart
[SOLVED] android redefine VS ES5
$25