Could anyone point to a reliable model of the JavaScript standard class/prototype cloning inheritance relations?
The "standard prototypes" I refer to are window, navigator, document, and so forth and so on.
If you're referring to the DOM objects provided by browsers, take a look at Mozilla's Gecko DOM reference. Each browser however provides their own native objects though, so you should verify that a certain object is indeed available and works similarly in all the browsers that you want to target.
this is a pretty good one.
http://phrogz.net/js/classes/OOPinJS2.html
As #Radu and #johnH pointed out, there's no "classes" per se, but there is a sort of inheritance through the prototype.
Related
This is something I cannot find an official answer about. For some, DOM objects are JS objects, for others they differ. What is the right answer?
By searching in stackoverflow, you may see controversial opinions.
For example, does the object document.body belongs to DOM API only or may it be considered as part of javascript engine too?
Does Javascript create an internal representation of it or does it just communicates with DOM to access it?
The DOM API is a collection of standards which have implementations in a variety of programming languages.
The DOM available to JavaScript in a browser provides things in the form of JavaScript objects. Large portions of it are written in native code (so are handled by libraries not written in JavaScript but made available through a JavaScript API).
Where JavaScript leaves off and native code begins doesn't really matter, it is an implementation detail and probably varies from browser to browser. The point of having a standard API is that developers using it interact with that API and don't need to worry about how it is implemented under the hood.
Strictly speaking, no. The JavaScript runtime has access to them, and in that capacity they can function as JavaScript objects. But they are defined in a way that is not bound to any particular language, and in most DOM implementations, they're native code. Most DOM implementations take care to make the objects function the same way you'd expect other objects in the chosen language to work, but that's not always the same way that JavaScript objects do: for example, you can't go around adding dynamic properties to objects when you're working in Java.
For most practical purposes, when you're working in the browser or in some other JavaScript runtime, yes. As I stated above, most DOM implementations try to make the DOM objects work the same way as other objects in the language, and for JavaScript, that means making them work like "real" JavaScript objects. Although IE took a while to really get this right (you need IE9+ to take full advantage), these days you can pretty much use DOM objects the same way you'd use any other JavaScript object.
If you inspect deeply the __proto__ of document.body for instance, you would find this :
HTMLBodyElement > HTMLElement > Element > Node > EventTarget > Object
So yes : in the browser's context, DOM objects are JS objects, this is not reciprocal of course.
But DOM API is not exclusive to Javascript, it defines interfaces which can be implemented in any languages, for instance Python has a DOM API too and in this case, DOM objects are Python objects.
The DOM objects are not part of the JavaScript language, they are part of the environment that is provided when JavaScript runs in a browser.
When JavaScript runs in another environment, for example in Node.js, then there is no DOM. Instead there are other objects that make up the environment that the script works with.
The DOM objects are there just for JavaScript so the script works directly with the objects, there is no extra wrapper to make them available to JavaScript.
When adding properties to a JavaScript object are they added in an ordered way (alphabetical etc). And if so does that mean when you lookup a property on a JavaScript object that a quick algorithm is used like a binary tree search? I did a search for this and just found lots of explanations for prototype inheritance which I already understand I'm just interested in how a property is looked up within a single level of the prototype chain.
That entirely depends on the implementation. Google's V8 engine probably does it differently than Firefox's JagerMonkey. And they almost certainly does it different than IE6. Looking up a property in an object is just an interface (a fairly common Map interface as programmers would call it). The only thing Javascript guarantees you is the methods of the interface, no details about implementation, and that's a good thing. It could be a hash table (probably) or it could be a linked list (less likely, but possible) or it could even be a binary search tree.
The point is that we don't know how it's implemented, nor should we. And you should make no assumptions about the implementation. As is common with abstraction in programming, just assume it's magic. :)
Here is a high level description of how v8 does it using hidden classes it then looks up the property value by using the fixed offset provided by the definition of the hidden class. It also confirms that most other implementations use a dictionary type data object.
I am writing an HTML5 application that involves a lot of XML manipulation, part of this manipulation involves comparing the versions of two different XML Elements.
What I need is for every Element, Attr, and TextNode (all of which inherit from Node, AFAIK) object that gets created to have associated version information, but still be able to behave like a normal Element, Attr, or TextNode. The current working solution I am using to store the version information, is the following:
Node.prototype.MyAppAnnotation = {
Version : null
};
Now, I understand that augmenting built-in types is considered bad form, but beyond this technique, I'm at a loss for how to get the desired functionality. I don't think I can encapsulate the Node in a wrapper because I need the Node related properties and functions exposed on the wrapper. I might be able to write some sort of pass-through functions for the wrapper, but that seems really clunky.
I feel that because the app I'm writing is an HTML5 app, and as such only has to run on the most modern browsers (all of which support the augmentation of built-ins), makes this technique appropriate. Also, by providing a sufficiently obscure name to my augmentation object, I can avoid all naming collisions (except for intentional collisions). I've also explored inheritance-based solution using Google's Closure library. However, it appears that because Element, Node and TextNode don't have direct constructors (i.e. they're created off of a Document object), this technique will not work either.
I was wondering if someone could either a) recommend an elegant way of achieving this effect without augmenting Element, or b) provide a compelling reason for why I shouldn't break the "don't augment built-ins" rule in this case.
Many Thanks,
Jarabek
Your idea is theoretically valid, but there's a weird feeling I get when reading about it.
First of all - you don't have to augment any prototypes. If you just do somedomnode.myweirdname='foo' it will become a field of that object. That's what javascript does ;)
So when there is no version you'll get undefined instead of null.
But, if you want to add more functionality or wrap dom node in anything - there's a bit of history of doing that. Most of that history is dominated by stuff like jQuery :)
Just create an object that has a field containing the node. And then you can access it really simply:
myobject.node
And create the object with some constructor or just factory function:
var myobject = createDomNodeWrapper(domnode)
I've come across a few comments here and there about how it's frowned upon to modify a JavaScript object's prototype? I personally don't see how it could be a problem. For instance extending the Array object to have map and include methods or to create more robust Date methods?
The problem is that prototype can be modified in several places. For example one library will add map method to Array's prototype and your own code will add the same but with another purpose. So one implementation will be broken.
Mostly because of namespace collisions. I know the Prototype framework has had many problems with keeping their names different from the ones included natively.
There are two major methods of providing utilities to people..
Prototyping
Adding a function to an Object's prototype. MooTools and Prototype do this.
Advantages:
Super easy access.
Disadvantages:
Can use a lot of system memory. While modern browsers just fetch an instance of the property from the constructor, some older browsers store a separate instance of each property for each instance of the constructor.
Not necessarily always available.
What I mean by "not available" is this:
Imagine you have a NodeList from document.getElementsByTagName and you want to iterate through them. You can't do..
document.getElementsByTagName('p').map(function () { ... });
..because it's a NodeList, not an Array. The above will give you an error something like: Uncaught TypeError: [object NodeList] doesn't have method 'map'.
I should note that there are very simple ways to convert NodeList's and other Array-like
Objects into real arrays.
Collecting
Creating a brand new global variable and stock piling utilities on it. jQuery and Dojo do this.
Advantages:
Always there.
Low memory usage.
Disadvantages:
Not placed quite as nicely.
Can feel awkward to use at times.
With this method you still couldn't do..
document.getElementsByTagName('p').map(function () { ... });
..but you could do..
jQuery.map(document.getElementsByTagName('p'), function () { ... });
..but as pointed out by Matt, in usual use, you would do the above with..
jQuery('p').map(function () { ... });
Which is better?
Ultimately, it's up to you. If you're OK with the risk of being overwritten/overwriting, then I would highly recommend prototyping. It's the style I prefer and I feel that the risks are worth the results. If you're not as sure about it as me, then collecting is a fine style too. They both have advantages and disadvantages but all and all, they usually produce the same end result.
As bjornd pointed out, monkey-patching is a problem only when there are multiple libraries involved. Therefore its not a good practice to do it if you are writing reusable libraries. However, it still remains the best technique out there to iron out cross-browser compatibility issues when using host objects in javascript.
See this blog post from 2009 (or the Wayback Machine original) for a real incident when prototype.js and json2.js are used together.
There is an excellent article from Nicholas C. Zakas explaining why this practice is not something that should be in the mind of any programmer during a team or customer project (maybe you can do some tweaks for educational purpose, but not for general project use).
Maintainable JavaScript: Don’t modify objects you don’t own:
https://www.nczonline.net/blog/2010/03/02/maintainable-javascript-dont-modify-objects-you-down-own/
In addition to the other answers, an even more permanent problem that can arise from modifying built-in objects is that if the non-standard change gets used on enough sites, future versions of ECMAScript will be unable to define prototype methods using the same name. See here:
This is exactly what happened with Array.prototype.flatten and Array.prototype.contains. In short, the specification was written up for those methods, their proposals got to stage 3, and then browsers started shipping it. But, in both cases, it was found that there were ancient libraries which patched the built-in Array object with their own methods with the same name as the new methods, and had different behavior; as a result, websites broke, the browsers had to back out of their implementations of the new methods, and the specification had to be edited. (The methods were renamed.)
For example, there is currently a proposal for String.prototype.replaceAll. If you ship a library which gets widely used, and that library monkeypatches a custom non-standard method onto String.prototype.replaceAll, the replaceAll name will no longer be usable by the specification-writers; it will have to be changed before browsers can implement it.
Other than regularly polling for changes, is there any (standard) way to register an event or callback that will be triggered any time a new property is added to a specific object?
Simply put, the answer is no.
Mozilla's JavaScript implementation has an overload for unresolvable methods, but it doesn't work for standard properties, see __noSuchMethod__. Of course, you asked for a standard method and no other implementations support this as far as I'm aware.
Once upon a time, ActionScript supported the __resolve property. As far as I know, JS has no similar crossbrowser construct, but maybe you could simulate it with some simple (but still bloaty) accessor function, like this:
http://bytes.com/topic/javascript/answers/789987-does-javascript-support-some-kind-__resolve-method