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()
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/*!(C) WebReflection *//** @license Mit Style */ | |
// inspired by https://gist.github.com/4395291 | |
this.inherit || (this.inherit = function(create){ | |
if (!create) { | |
if ({__proto__:null} instanceof Object) { | |
for (var | |
Null = function Null() {}, | |
doc = document, | |
html = doc.documentElement, | |
iframe = html.insertBefore( | |
doc.createElement("iframe"), | |
html.lastChild | |
), | |
// works down to IE7, it does NOT work in IE6 | |
NullPrototype = Null.prototype = | |
(iframe.src = "javascript:", iframe.contentWindow.Object.prototype), | |
/* this would work in IE6 too | |
idoc = iframe.contentWindow.document || | |
iframe.contentDocument || | |
iframe.document, | |
NullPrototype = Null.prototype = ( | |
idoc.open(), | |
idoc.write( | |
"<script>parent.inherit=Object.prototype<" + | |
"/script>" | |
), | |
idoc.close(), | |
inherit | |
), | |
//*/ | |
xtend = html.removeChild(iframe) && function xtend(object) { | |
return xtend.prototype === object ? | |
(xtend.prototype = xtend, this) : | |
new xtend(xtend.prototype = object) | |
; | |
}, | |
proto = [ | |
"hasOwnProperty", | |
"isPrototypeOf", | |
"propertyIsEnumerable", | |
"valueOf", | |
"toString", | |
"toLocaleString", | |
"constructor" | |
], | |
i = proto.length; i--; | |
) delete NullPrototype[proto[i]]; | |
// you know ... IE, leaks, and shit ... | |
create = doc = html = iframe = NullPrototype = proto = | |
function(object) { | |
return object == null ? new Null : xtend(object); | |
} | |
; | |
} else { | |
create = function(object) { | |
return {__proto__: object}; | |
}; | |
} | |
} | |
return function(object) { | |
return create(object); | |
}; | |
}(Object.create)); |
More Reliable Than Object.create()
The reason I didn't even try to polyfill the ES5Object.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 evenObject.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. That's correct, objects that inherit from
// some obtrusive code
Object.prototype.troll = function (up) {
throw up;
};
// empty object in every browser/env
var dict = inherit(null);
dict.anyKey = anyValue;
// later on ...
for (var key in dict) {
// only 'anyKey'
}
null
are not affected by the Object.prototype
... really, we cannot even print them without defining a toString
method! Update: On IE DontEnum Bug
Unfortunately the fact IE does not enumeratetoString
and other native Object.prototype
names is not solved here for the simple reason here we are not solving that problem, here we are solving inheritance. However,I think is a must know that even objects created via this function needs an extra loop or something like this:
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
this.forIn = function (){ | |
var | |
propertyIsEnumerable = "propertyIsEnumerable", | |
toString = "toString", | |
OK = {toString:1}[propertyIsEnumerable](toString), | |
keys = OK || [ | |
propertyIsEnumerable, | |
toString, | |
"hasOwnProperty", | |
"isPrototypeOf", | |
"valueOf", | |
"toLocaleString", | |
"constructor" | |
], | |
num = OK || function(obj, callback, self){ | |
for (var | |
key, | |
i = keys.length; | |
i--; | |
(key = keys[i]) in obj && | |
callback.call( | |
self, | |
obj[key], | |
key, | |
obj | |
) | |
); | |
} | |
; | |
return function forIn(obj, callback, self) { | |
for(var key in obj) | |
callback.call( | |
self, | |
obj[key], | |
key, | |
obj | |
) | |
; | |
OK || num(obj, callback, self); | |
}; | |
}(); | |
/* example | |
forIn({toString:123}, function(value, key, obj) { | |
alert(value === 123 && key === "toString"); | |
}); | |
//*/ |
Comments
Post a Comment