Posts

Showing posts with the label Object

5 Reasons You Should Avoid __proto__

Update : when you've done with this post, there's even more in comments and the newer one: Yet Another Reason To Drop __proto__ Too many discussions without real outcome about __proto__ magic evilness or feature. It's time to understand why using it is, today , a bad idea. __proto__ Is NOT Standard (yet) TC39 refused to standardize this property because of the amount of problems it brings . Apparently will be part of ES6 but is not there yet. __proto__ is a silent, non spec'd, agreement. What's the problem? Keep reading ;) __proto__ Could NOT Be There The silent non standard agreement sees __proto__ as configurable property of the Object.prototype . As example, try this in some environment: (this.alert || console.warn)( delete Object.prototype.__proto__ ); // false or true ? The outcome is migrating from false to true . As example, current Chrome has a non configurable descriptor, while Canary has a configurable one. Same is for latest node.js, Firefox, an...

A Cross Platform Inherit Function

This (apparently non working) gist gave me the hint. Stuff I've been dealing with for a while , finally used to bring an Object.create(firstArgOnly) cross platform/engine/client/server code that works. The name? inherit() More Reliable Than Object.create() The reason I didn't even try to polyfill the ES5 Object.create() method is quite easy: it is not possible to shim it in a cross platform way due second argument which requires descriptors features, highly improbable to simulate properly. Even if browsers support the create() method, inherit() guarantee that no second argument will ever be used so we are safe from inconsistencies within the function. Forget hasOwnProperty ! Yeah, one of the coolest things about being able to inherit from null is the fact not even Object.prototype is inherited so we can create real empty objects without worrying about surrounding environment, 3rd parts obtrusive libraries, and the boring and slow obj.hasOwnProperty(key) check. // so...

A Safer JS Environment

Oh well, apparently I wasn't joking here and I went even further ... so here I am with a weird hack you probably never thought about before ;) A Globally Frozen Environment Have you ever thought about this in the global context? Object.freeze(this); Apparently not even browser vendors such Chrome or Safari since this condition, today, is always false: Object.isFrozen(Object.freeze(this)); , and even if it works as expected after freezing. Firefox and node.js got it right while Opera Next throws an error .. but latter a part ... Stop Any Global Pollution That's right, if you freeze the window or global object, guess what happens here: Object.freeze(this); var a = 123; alert(this.a); // undefined alert(a); // error: a is not defined We cannot even by mistake create a global variable ... there's no lint that could miss that. Moreover, if you are worried about malicious code able to change some global function or constructor, you can stop worrying with proposed freeze call: t...

Array extras and Objects

When Array extras landed in JavaScript 1.6 I had, probably together with other developers, one of those HOORRAYYY moment ... What many libraries and frameworks out there still implement, is this sort of universal each method that supposes to be compatible with both Arrays and Objects. A Bit Messed Up What I have never liked that much about these each methods is that we have to know in advance in any case if the object we are passing is an Array, an ArrayLike one, or an Object. In latter case, the callback passed as second argument will receive as second argument the key , and not the index , which simply means we cannot trust a generic callback unless this does not check per each iterated item the second argument type, or unless we don't care at all about the second argument. In any case I always found this a bad design. If we think about events, as example, it's totally natural to expect a single argument as event object and then we can act accordingly. This let us reuse c...

Do You Really Know Object.defineProperty ?

I am talking about enumerable , configurable , and writable properties of a generic property descriptor. enumerable most likely the only one we all expect: if false, a classic for/in loop will not expose the property, otherwise it will. enumerable is false by default. writable just a bit more tricky than we think. Nowadays, if a property is defined as non writable, no error will occur the moment we'll try to change this property: var o = {}; Object.defineProperty(o, "test", { writable: false, value: 123 }); o.test; // 123 o.test = 456; // no error at all o.test; // 123 So the property is not writable but nothing happens unless we try to redefine that property. Object.defineProperty(o, "test", { writable: false, value: 456 }); // throws // Attempting to change value of a readonly property. Got it ? Every time we would like to set a property of an unknown object, or one shared in an environment we don't trust, either we use a try/catch plus double ...

Object.defineProperty - A Missed Opportunity

Just a quick post about some clever hack we should probably forget ... make old scripts less obtrusive using new ES5 features. I am talking bout those guys out there that use scripts with a classic: onload = function () { ... }; // or this.onload = ... // or window.onload ... // or self.onload ... // etc etc Apparently WebKit Nightly fires an error when we try to define getters and setters via Object.defineProperty and this is already enough to remove that "hoooraayyyy" for my silly test .... here the code: Object.defineProperty(this, "onload", (function (self, callback) { function onload(e) { while (callback.length) { callback.shift().call(self, e); } } self.addEventListener ? self.addEventListener("load", onload, false) : self.attachEvent("onload", onload) ; return { get: function () { return onload; }, set: function (onload) { callba...

LiveMonitor - Asynchronous Property Monitor

Today I would like to introduce you a quite uncommon JavaScript trick , a trapped Live Object or, generally speaking, a lightweight monitor able to understand when a generic property has been changed. About Live Objects A live object could be described as a particular object able to change without our interaction. The most common live object example is this: // this is the most common live object // the HTMLCollection var divs = document.getElementsByTagName("div"); divs.length; // let's say 4 // let's add another div inside a generic node document.body.appendChild( document.createElement("div") ); divs.length; // 5! In few words DOM searches are dynamic, which is the reason almost every selector library needs to transform the current result into a static Array . About LiveMonitor Specially suited for live objects, LiveMonitor is a function which aim is to notify us when the specified property change: // LiveMonitor example var lm = new LiveMonitor( ...

[COW] A Generic ArrayObject Converter

Few days ago I wrote about a fast Array slice implementation for every browser, a callback able to convert " every collection " into an Array. For collection, I mean every instance with a length attribute and an index access Array like. This object, for example, could be considered as a collection: var generic = { length: 2, "0": "abc", "1": "def" }; Above instance is a basic model of most common libraries such jQuery, prototype, base, and every other based over an Array like prototype. Some library could coexist in the same page without problems but not every library implement a method to create a copy of another collection into a new instance of the library itself. As example, a jQuery or Sizzle result into another instance, a generic DOM collection into a jQuery object, etc etc. All these instances could be passed via Array.prototype.push to be populated, and thanks to this peculiarity we can obtain every kind of instance f...

A fast Array slice for every browser

It is an extremely common task and one of the most used prototype in libraries and applications: Array.prototype.slice The peculiarity of this prototype is to create an Array from an Array like Object such arguments, HTMLCollection, other kind of lists as jQuery results. Every browser, except Internet Explorer, allows direct calls via native prototype obtaining, obviously, best performances. In IE, we have different ways to make this task possible, and these ways are mainly classic loops, or the isArray check to know when it is possible to perform the native call or not. isArray = (function(toString){ return function(obj){ return toString.call(obj) === "[object Array]"; }; })(Object.prototype.toString); Even using a closure, above function could slow down performances, specially in those libraries where Array conversions are performed almost everywhere. As we all know, Internet Explorer behaves weird "sometimes", and one of the weirdest things is tha...

[js.php] A JavaScript Object Like PHP Class

PHP 5.3 introduces the Closure class which is really useful and more powerful than good old lambdas via create_function . These are main limits of Closure class: you cannot serialize a Closure instance (and json_encode does not solve the problem at all) you cannot inject scopes via $this unless the closure comes from a class method While with an emulated prototype style class, something I tried months ago as well, the first point could not be a problem, to solve the second one is quite inevitable to use a Python like variable as first argument, called $self , to make the Closure both portable and re-adaptable. JSObject :: JavaScript Object Like PHP Class /** js.php basic JSObject implementation * @author Andrea Giammarchi * @blog WebReflection.blogspot.com * @license Mit Style License */ class JSObject implements ArrayAccess { // public static prototype static public $prototype; // ArrayAccess Interface public function offsetExists($index){return isSet(...

[IE8] Global constants via defineProperty ... Illusion!

I do not want to spend a single word about Internet Explorer 8 Object.defineProperty implementation, which works only with DOM prototypes and the super global window but not with user defined objects , as __defineGetter__ and __defineSetter__ do since ages : Standards are an important factor to ensure browser interoperability for the Web developer (n.d. oh, really?!??!?!!!!) . The accessor property syntax has only recently begun standardization (you guys have a weird concept of the time ... or the meaning of "recent" in IT therms ...) . As such, many browsers support an older, legacy syntax ... (n.d. which at least has dignity to work with every kind of object ... ) Anyway, few things are better than nothing, so welcome to Object.defineProperty! Let IE8 behaves like every other or change every other to respect new M$ standard? This was the first question when I thought about this new global function: does it mean we finally have a way to emulate __defineGetter__ and setter in...

JavaScript Relator Object, aka unobtrusive informations

Have you never though about add, modify, or remove a generic information from a variable, and without changing variable itself? This is all about what my last simple creation does. Relator Object Concept The main purpose for this object is to associate every kind of information, value, or function, into a generic variable, whatever it is, and without modifying its native state. To obtain this result, I have used a 1:1 relationship between a stack that will contain every stored variable, and another one that will contain related objects. Stack = [1, 2, 3]; RelatedObject = [{}, {}, {}]; // add a property RelatedObject[Stack.indexOf(2)].description = "Number 2"; // remove a property Stack.splice(0, 1); RelatedObject.splice(0, 1); // situation Stack = [2, 3]; RelatedObject = [{description:"Number 2"}, {}]; Using above strategy we obtain 2 benefits: The Stack does not cause memory leaks both Stack and RelatedObject are alw...

PHP - JavaScript like Object class

As I've wrote in last post, there's some JavaScript feature I would like to have in PHP too. This time we will use a basic implementation of JavaScript Object constructor in PHP. What we need to start is this class, based on SPL ArrayAccess interface. class Object extends stdClass implements ArrayAccess { // (C) Andrea Giammarchi - webreflection.blogspot.com - Mit Style License // static public methods static public function create(){ return new Object; } static public function parseJSON($json){ return self::create()->extend(json_decode($json)); } static public function parseSource($source){ return self::create()->extend(unserialize($source)); } // basic JavaScript like methods public function extend(){ for($i = 0, $length = count($arguments = func_get_args()); $i foreach($arguments[$i] as $key => $value) $this->$key = $value; return $th...