I'm currently learning JavaScript using the Mozilla Developer Network as a reference.
It confuses me that MDN refers to objects as interfaces.
For example: Document.createTreeWalker()
At the bottom, there is a link to the TreeWalker Object, but it says:
The interface of the object it creates: TreeWalker
How can TreeWalker be an interface if I can instantiate it?
And TreeWalker is only an example, almost every object in MDN is referred to as an interface.
I come from a Java background, so the use of interface in this context is not clear to me. Does interface in JavaScript mean something different than in Java?
"interface" arises in this context because that is the term used in standards applicable to the (javascript) object being described on MDN.
Web standards use an interface definition language or IDL described in Web IDL to describe the behavior of browser objects independent of the language, e.g. javascript, used to manipulate them. Hence TreeWalker is documented as an "interface" in the Document Object Model (DOM) Level 2 Traversal and Range Specification
So in a sense MDN is simply using the vocabulary of the standard which defines the interface exposed by the browser object it is describing. To what extent the subject of the documentation would be described as an "interface" in another language might vary on a case by case basis.
C.F. the definition of interface used in web standards.
No, javascript doesn't really have a true interface type or anything. The createTreeWalker() function simply uses Object.create to return on object.
See also:
How to implement interface in javascript
Does JavaScript have the interface type (such as Java's 'interface')?
There isn't a true interface built into JavaScript. It seems like they are referring to an object that gets inherited from as the interface. In your example Document.createTreeWalker() returns an instance of the TreeWalker object.
// myTreeWalker is your object. TreeWalker is the interface.
var myTreeWalker = Document.createTreeWalker()
Related
As I know,getElementsByName is a function defined in HTMLDocument,and HTMLDocument inherits from Document,and Document inherits from Node.
So why I can see Document.prototype.getElementsByName in Chrome but not Firefox?Does not Chrome implement DOM2 spec?
Does not Chrome implement DOM2 spec?
Yeah, probably not. I'd guess they at least implement DOM 3, if not a more current version :-)
However, those don't define a getElementsByName either. So how did they get this? It is actually specified in HTML5 (WHATWG/W3) on the Document partial interface:
The DOM specification defines a Document interface, which this [HTML5] specification extends significantly […]
And at http://dev.w3.org/html5/spec-LC/dom.html#documents-in-the-dom I found the note
Because the HTMLDocument interface is now obtained using binding-specific casting methods instead of simply being the primary interface of the document object, it is no longer defined as inheriting from Document.
So the specification details of these interfaces are still in progress, and varying. Notice that browsers are not even supposed to export any kind of DocumentPrototype - the specs do only define interfaces, not the exact EcmaScript binding representation of them. WebIDL does.
So Chrome does follow the newer specs (but still has some HTMLDocument?), while Firefox implements an older version. However, it only really matters that these methods do exist on every window.document - not how they got there :-)
In terms of the language what do I get back when I grab an element from the DOM as such:
var obj = document.getElementById('foo');
It has properties, so I thought that maybe it might be an object literal. Using type checks I determined that it is not an object literal, it is also not an array literal.
I know what it is used for, and how to use it, just not what it is, technically speaking in terms of the language.
I ran it through this test which I call a test for an abstract object.
obj === Object(obj);
which it returned false.
I know that I can identify node elements as such
obj.nodeType === 1
but still this doesn't tell me what it is, in terms of the language (ES5). What is an element expressed in terms of the language?
Clarification
I mean the language, based on a grammar, JavaScript, the Good
Parts, Chapter 2, This grammar only knows how to deal with language
components, arrays, objects, etc.
Element is not defined in terms of ES5. It is a part of the DOM API.
Here is its definition
The Element interface represents an element in an HTML or XML document.
A language does not have to implement the ES5 specification to implement the DOM API interface, moreover - ES5 implementations can be valid and not implement Element. For example, NodeJS does server side JavaScript and does not implement Element.
In terms of the ECMAScript specification, DOM Elements are "host objects" provided by the browser's host environment (emphasis mine below):
ECMAScript as defined here is not intended to be computationally self-sufficient; indeed, there are no provisions in this specification for input of external data or output of computed results. Instead, it is expected that the computational environment of an ECMAScript program will provide not only the objects and other facilities described in this specification but also certain environment-specific host objects, whose description and behaviour are beyond the scope of this specification except to indicate that they may provide certain properties that can be accessed and certain functions that can be called from an ECMAScript program.
The particular properties of DOM elements are specified by the interfaces laid out in the W3C's DOM specification, not by the ECMAScript spec (although the ECMAScript spec allows for them to exist, by allowing for environment-supplied host objects).
Addendum:
You have added some clarification that your confusion stems from the fact that JavaScript uses a grammar. I'm having a hard time understanding why that causes confusion for you, but I'll try to clear things up.
JavaScript's grammar is lexical, i.e., it deals with written code. That written code is parsed (using a grammar) and the parser identifies particular expressions in the code. Those expression correspond to programmatic operations in the execution environment.
The grammar that is used to refer to a host object is identical to the grammar used to refer to a native object. In fact, a host object is an object. The only difference is that a host object can specify the behavior of its internal methods, like [[Get]] (used for property access).
this is very confused me, and here is my simple html file:
<html>
<head>
</head>
<body>
<div id="misc">Test</div>
</body>
</html>
in Firebug console: I have this script:
var c = document.documentElement.childNodes[2].childNodes[3];
alert(c.id); //Return misc
alert(c.constructor); // Return [object HTMLDivElement]
As far as I know, a constructor of a function is a function (which is also a object but I'm not talking about that Function Object here). Now c's constructor is a object, and if I ask c'constructor constructor (which is c.constructor.constructor), It'll now return a "real" function, like this:
function Object() {
[native code]
}
I don't know why c.constructor is an object ( [object HTMLDivElement] ), it should be a function as expected.
Could you help me understand this one?
Thank you!
The short answer is: c does not have a regular constructor.
The longer answer: native objects like DOM elements, Function objects, the global object (usually window in browsers), the innerHTML function, etc. don't have regular constructors. This is because they are usually not implemented in JavaScript but at a lower level (in whatever language the browser or interpreter was written in).
The JavaScript language specification allows this - native built-in objects do not have to be normal javascript objects. The real reason is historical -- the specs were written by basically reverse engineering Netscape Navigator and having all the contributors agree on what was written. Since then everyone just stuck to it for backwards compatibility. The practical reason usually given these days is performance: if browsers are allowed to do this then they can be faster since native objects need not carry the heavy baggage of normal JavaScript objects.
In your specific case, DOM elements don't have regular constructors. There are 2 ways you can "construct" DOM objects:
document.createElement(). This is the official DOM method for creating <div>s, <span>s etc. In most browsers this method is not a normal constructor since DOM elements don't normally inherit form its prototype.
innerHTML(). This is a thin interface to access the browser's HTML compiler. It's the same compiler that the browser uses to parse regular web pages. Again, this is in no way a regular constructor since it doesn't even return the object(s) it creates.
Since DOM elements don't have normal constructors, browsers may return anything for their constructor property including nothing at all. What you are seeing in your case is mostly left over implementation detail that have leaked through to the javascript engine. It's not something you're supposed to access or use. Much less depend on to develop applications.
I don't understand the difference between native objects and host objects in JavaScript. Does the latter simply refer to non-primitive function objects that were created by a custom constructor (e.g., var bird1 = new Bird();)?
Both terms are defined in the ECMAScript specification:
native object
object in an ECMAScript implementation whose semantics are fully
defined by this specification rather than by the host environment.
NOTE Standard native objects are defined in this specification. Some
native objects are built-in; others may be constructed during the
course of execution of an ECMAScript program.
Source: http://es5.github.com/#x4.3.6
host object
object supplied by the host environment to complete the
execution environment of ECMAScript.
NOTE Any object that is not native is a host object.
Source: http://es5.github.com/#x4.3.8
A few examples:
Native objects: Object (constructor), Date, Math, parseInt, eval, string methods like indexOf and replace, array methods, ...
Host objects (assuming browser environment): window, document, location, history, XMLHttpRequest, setTimeout, getElementsByTagName, querySelectorAll, ...
It is more clear if we distinguish between three kinds of objects:
Built-in objects: String, Math, RegExp, Object, Function etc. - core predefined objects always available in JavaScript. Defined in the ECMAScript spec.
Host objects: objects like window, XmlHttpRequest, DOM nodes and so on, which is provided by the browser environment. They are distinct from the built-in objects because not all environment will have the same host objects. If JavaScript runs outside of the browser, for example as server side scripting language like in Node.js, different host objects will be available.
User objects: objects defined in JavaScript code. So 'Bird' in your example would be a user object.
The JavaScript spec groups built-in objects and user objects together as native objects. This is an unorthodox use of the term "native", since user objects are obviously implemented in JavaScript while the built-ins is most likely implemented in a different language under the hood, just as the host objects would be. But from the perspective of the JavaScript spec, both builtins and user objects are native to JavaScript because they are defined in the JavaScript spec, while host objects are not.
Here's my understanding of the spec.
This:
var bird = new Bird();
...results in a native Object that simply happened to be created using the new operator.
Native objects have an internal [[Class]] property of one of the following:
"Arguments", "Array", "Boolean", "Date", "Error", "Function", "JSON", "Math", "Number", "Object", "RegExp", and "String".
For your bird1 it will be:
"Object"
Just like if you create a function:
function my_func() {
// ...
}
...my_func isn't defined in ECMAScript, but it is still a native object with the internal [[Class]]:
"Function"
A host object is an object provided by the environment in order to serve a specific purpose to that environment not defined in by the specification.
For example:
var divs = document.getElementsByTagName('div')
The object referenced by divs is a NodeList, which is integrated into the environment in such a manner that it feels like a regular JavaScript object, yet it isn't defined anywhere by the specification.
Its internal [[Class]] property is:
"NodeList"
This provides implementation designers some flexibility in suiting the implementation to the specific need of the environment.
There are requirements of host objects that are defined throughout the spec.
In addition to the other answers regarding Host Objects.
Host objects are specific to a environment. So next to the browsers' host objects, there are also specific objects in nodejs.
For the sake of the example, first starting with the Standard objects as defined in Javascript. Then the common objects for the Browser/DOM. Node has it's own Objects.
Standard Javascript built-in object examples:
Object
Function
Boolean
Symbol
Number
Math
... (See full list on MDN web docs)
Host Objects Document Object Model Examples:
Window
Document
History
... (See full list on DOM objects on MDN web docs)
XMLHttpRequest (part of Web API)
... (See full list Web API on MDN web docs)
Host Objects in Node.js:
http
https
fs
url
os
... (See full list on nodejs.org)
Could not see a convincing answer to the question whether var bird1 = new Bird(); is a native or host object. Assuming Bird is a user defined function, a native non-built-in object will be created according to http://es5.github.io/#x13.2 by the javascript implementation. In contrast, native built-in objects will be present since the start of a javascript program (such as Object and many others). A difference between a native object and a host object is that former is created by the javascript implementation and the latter is provided by the host environment. As a result host object internal [[class]] property can be different from those used by built-in objects (i.e. "Arguments", "Array", "Boolean", "Date", "Error", "Function", "JSON", "Math", "Number", "Object", "RegExp", and "String").
Also, worthwhile noting that ECMA6 http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-262.pdf does not use the terminology native and host objects any more. Instead, it defines below object types, with more clear explanations of their intended behaviour.
4.3.6 ordinary object
object that has the default behaviour for the essential internal methods that must be supported by all objects
4.3.7 exotic object
object that does not have the default behaviour for one or more of the essential internal methods that must be supported by all objects
NOTE
Any object that is not an ordinary object is an exotic object.
4.3.8 standard object
object whose semantics are defined by this specification
4.3.9 built-in object
object specified and supplied by an ECMAScript implementation
Considering three objects: Host, Native, Custom.
Host Objects are created by the environment and are environment specific. Best known environment would be a web-browser but could be another platform. The host objects created in web-browser could be the window object or the document. Typically a browser uses an API to create Host Objects to reflect the Document Object Model into JavaScript. (Webbrowser have different JavaScript Engines that do this) A host object is created automatically the moment the page renders in a browser.
A Native Object is created by the developer using predefined classes of JavaScript. Native Objects are in your written script.
Than, a Custom Object is made by the developer from a custom (not predefined, or partially predefined) class.
Native objects are objects that adhere to the specs, i.e. "standard objects".
Host objects are objects that the browser (or other runtime environment like Node) provides.
Most host objects are native objects, and whenever you instantiate something using new, you can be 99.99% sure that it is a native object, unless you mess around with weird host objects.
This notion has been introduced due to the presence of very bizarre objects in IE(and other old browsers?). For example:
typeof document.all == "undefined"; // true
document.all.myElementId; // object
When seeing this, everyone would agree that document.all is clearly "non-standard", and thus a non-native host object.
So why not call native objects standard objects in the first place? Simple: after all, the Standard(!) document talks about non-native objects too, and calling them non-standard would lead to a paradox.
Again:
native == "standard"
host == provided by the browser or Node or …
most host objects are native, and all non-host objects are native too
This may be overkill, but for simplicity a native object is one that exist and is usable in any environment that implements an ECMAScript compliant engine. This is usually (but not always) a browser.
So, your Internet Explorer or your Google Chrome, doesn't make the String object available to you, for example. The reason you can use the String object is because it is "native" (built-in) to the JavaScript language itself.
However, if you'd like to create a pop-up window, you'll need to use the window object. The window object is provided by the browser software itself, so it is not native to JavaScript, but it is part of the "Browser Object Model" or the BOM.
Objects in JavaScript can be used as Hashtable
(the key must be String)
Is it perform well as Hashtable the data structure?
I mean , does it implemented as Hashtable behind the scene?
Update: (1) I changed HashMap to hashtable (2) I guess most of the browser implement it the same, if not why not? is there any requirement how to implement it in the ECMAScript specs?
Update 2 : I understand, I just wonder how V8 and the Firefox JS VM implements the Object.properties getters/setters?
V8 doesn't implement Object properties access as hashtable, it actually implement it in a better way (performance wise)
So how does it work? "V8 does not use dynamic lookup to access properties. Instead, V8 dynamically creates hidden classes behind the scenes" - that make the access to properties almost as fast as accessing properties of C++ objects.
Why? because in fixed class each property can be found on a specific fixed offset location..
So in general accessing property of an object in V8 is faster than Hashtable..
I'm not sure how it works on other VMs
More info can be found here: https://v8.dev/blog/fast-properties
You can also read more regarding Hashtable in JS here:(my blog) http://simplenotions.wordpress.com/2011/07/05/javascript-hashtable/
"I guess most of the browser implement it the same, if not why not? is there any requirement how to implement it in the ECMAScript specs?"
I am no expert, but I can't think of any reason why a language spec would detail exactly how its features must be implemented internally. Such a constraint would have absolutely no purpose, since it does not impact the functioning of the language in any way other than performance.
In fact, this is absolutely correct, and is in fact the implementation-independence of the ECMA-262 spec is specifically described in section 8.6.2 of the spec:
"The descriptions in these tables indicate their behaviour for native
ECMAScript objects, unless stated otherwise in this document for particular kinds of native ECMAScript objects. Host objects may support these internal properties with any implementation-dependent behaviour as long as it is consistent with the specific host object restrictions stated in this document"
"Host objects may implement these internal methods in any manner unless specified otherwise;"
The word "hash" appears nowhere in the entire ECMA-262 specification.
(original, continued)
The implementations of JavaScript in, say, Internet Explorer 6.0 and Google Chrome's V8 have almost nothing in common, but (more or less) both conform to the same spec.
If you want to know how a specific JavaScript interpreter does something, you should research that engine specifically.
Hashtables are an efficient way to create cross references. They are not the only way. Some engines may optimize the storage for small sets (for which the overhead of a hashtable may be less efficient) for example.
At the end of the day, all you need to know is, they work. There may be faster ways to create lookup tables of large sets, using ajax, or even in memory. For example see the interesting discussion on this post from John Reseig's blog about using a trie data structure.
But that's neither here nor there. Your choice of whether to use this, or native JS objects, should not be driven by information about how JS implements objects. It should be driven only by performance comparison: how does each method scale. This is information you will get by doing performance tests, not by just knowing something about the JS engine implementation.
Most modern JS engines use pretty similar technique to speed up the object property access. The technique is based on so called hidden classes, or shapes. It's important to understand how this optimization works to write efficient JS code.
JS object looks like a dictionary, so why not use one to store the properties? Hash table has O(1) access complexity, it looks like a good solution. Actually, first JS engines have implemented objects this way. But in static typed languages, like C++ or Java a class instance property access is lightning fast. In such languages a class instance is just a segment of memory, end every property has its own constant offset, so to get the property value we just need to take the instance pointer and add the offset to it. In other words, in compile time an expression like this point.x is just replaced by its address in memory.
May be we can implement some similar technique in JS? But how? Let's look at a simple JS function:
function getX(point) {
return point.x;
}
How to get the point.x value? The first problem here is that we don't have a class (or shape) which describes the point. But we can calculate one, that is what modern JS engines do. Most of JS objects at runtime have a shape which is bound to the object. The shape describes properties of the object and where these properties values are stored. It's very similar to how a class definition describes the class in C++ or Java. It's a pretty big question, how the Shape of an object is calculated, I won't describe it here. I recommend this article which contains a great explanation of the shapes in general, and this post which explains how the things are implemented in V8. The most important thing you should know about the shapes is that all objects with the same properties which are added in the same order will have the same shape. There are few exceptions, for example if an object has a lot of properties which are frequently changed, or if you delete some of the object properties using delete operator, the object will be switched into dictionary mode and won't have a shape.
Now, let's imagine that the point object has an array of property values, and we have a shape attached to it, which describes where the x value in this property array is stored. But there is another problem - we can pass any object to the function, it's not even necessary that the object has the x property. This problem is solved by the technique called Inline caching. It's pretty simple, when getX() is executed the first time, it remembers the shape of the point and the result of the x lookup. When the function is called second time, it compares the shape of the point with the previous one. If the shape matches no lookup is required, we can take the previous lookup result.
The primary takeaway is that all objects which describe the same thing should have the same shape, i.e. they should have the same set of properties which are added in the same order. It also explains why it's better to always initialize object properties, even if they are undefined by default, here is a great explanation of the problem.
Relative resources:
JavaScript engine fundamentals: Shapes and Inline Caches and a YouTube video
A tour of V8: object representation
Fast properties in V8
JavaScript Engines Hidden Classes (and Why You Should Keep Them in Mind)
Should I put default values of attributes on the prototype to save space?
this article explains how they are implemented in V8, the engine used by Node.js and most versions of Google Chrome
https://v8.dev/blog/fast-properties
apparently the "tactic" can change over time, depending on the number of properties, going from an array of named values to a dictionary.
v8 also takes the type into account, a number or string will not be treated in the same way as an object (or function, a type of object)
if i understand this correctly a property access frequently, for example in a loop, will be cached.
v8 optimises code on the fly by observing what its actually doing, and how often
v8 will identify the objects with the same set of named properties, added in the same order (like a class constructor would do, or a repetitive bit of JSON, and handle them in the same way.
see the article for more details, then apply at google for a job :)