JavaScript __proto__ not acessible - javascript

I was reading on the differences between the __proto__ and the prototype object, but when I tried to access the __proto__ of an instance of an object, it returned me undefined.
Following is the code I wrote:
function Student() {
}
var student = new Student();
student.constructor // works well returns function Student() {}
student.__proto__ // returns undefined.
I was referring this blog but I saw other blogs too that show the same. We never get the prototype on the instance of an object but __proto__ object instead that was created using the prototype property.
Am I missing something or __proto__ has been removed entirely? I've tested this on Chrome version 40.0.2214.94 on Linux.
Any help appreciated. Thanks!

The property __proto__ is not standard in JavaScript versions below ECMA 6 so you cannot expect every broser to support that, or an equal behavior in every browser yet.
Its best to avoid using proto at all.
You can read about it here:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/proto
And here is an interesting comment about that by brendan eich:
https://brendaneich.com/2011/01/harmony-of-my-dreams/
EDIT:
Object.setPrototypeOf is not going to happen. Writable proto is a giant pain to implement (must serialize to cycle-check) and it creates all sorts of type-confusion hazards. You may think you want it as a low-level sharp instrument. JS is not that language. Higher-level forms for classes and mixins seem much better and do not involve such sharp edges.

Related

Why Object.getPrototypeOf is static and not in Object's prototype [duplicate]

This question already has answers here:
Why were ES5 Object methods not added to Object.prototype?
(2 answers)
Closed 1 year ago.
I am asking why, to get an object's prototype, it has been implemented getPrototypeOf as a static method on Object's constructor rather than in its prototype?
Is there any reason for JS creators not to do
Object.prototype.getPrototypeOf = function() { return Object.getPrototypeOf(this); };
(which I could do myself but I know it is not good to extend JS standard objects' prototypes)?
[EDIT] Look, I am not proposing to add getPrototypeOf to Object.prototype, just curious about it wasn't done. I believe it was because of possible malfunctioning in specific cases
Putting anything into Object's prototype means adding it to all the objects ever created in all existing and future JS code on earth. Consequences would be very unpredictable. These extra 7 chars - not too high price to pay for stability.
Well, this method implemented in Object.prototype would be called just getPrototype (as far as getPrototypeOf with no arguments looks a bit strange). It is a very common name and indeed someone already has such method in one of his objects with a totally different meaning. Okay, adding global getPrototype won't break his existing code, but one day I will try to call hisObj.getPrototype assuming the new meaning, and I will get something wrong.
By the way, the isPrototypeOf method added in 3rd edition of ES is 12 years older than getPrototypeOf defined by ES 5.1.

Is it true to say that all objects (besides some custom objects), has a prototype object, in JavaScript?

Is it true to say that all objects (besides some custom objects), has a prototype object, in JavaScript?
I would bet it is indeed this way (because all out of the box objects likely to inherit properties from a prototype object besides some custom ones), but I'm not sure in that 100%.
Edit:
I asked this after reading in first edition of JavaScript: The good parts, book about prototypes - The chapter starts:
Every object is linked to a prototype object.
But it seemed a bit wired to me after what I read on objects in various places and I also read some definitions for prototype that were unclear to me; I wanted to see if I have a primal, basic of the concept of "prototype" in JS.
Nearly all objects in JavaScript are instances of Object; a typical object inherits properties (including methods) from Object.prototype, although these properties may be shadowed (a.k.a. overridden). However, an Object may be deliberately created for which this is not true (e.g. by Object.create(null)), or it may be altered so that this is no longer true (e.g. with Object.setPrototypeOf).
Javascript MDN
No, it's false.
You can create an object without prototype:
var obj = Object.create(null);
To check whether an object has a prototype, you can do
console.log(Object.getPrototypeOf(someObject));

Why the convertToFastObject function make it fast?

I tried Dart SDK after the 1.0 release, and wrote a simple hello-world program in Dart.
Then, with the SDK tool, I generated the JavaScript file: helloworld.dart.js
I went through the output js code, I saw there is a function named convertToFastObject.
The definition is:
function convertToFastObject(properties) {
function MyClass() {};
MyClass.prototype = properties;
new MyClass();
return properties;
}
The usage code is like:
A = convertToFastObject(A);
B = convertToFastObject(B);
I know this code is for various kinds of Browsers, not for Chromium/Chrome only.
I cannot understand, why the function can make the Object faster?
This is a speed optimization for Google's V8 engine.
To be sure, this code snippet looks pretty weird: it assigns properties as the prototype of a constructor MyClass, then uses the constructor to build an instance with new MyClass(), and then returns properties. This is strange because 1) properties is never altered, and 2) the function never uses MyClass or the instance ever again.
Whenever you see strange behaviors like this, you can be fairly sure it's a speed optimization. In this case, the speed is gained by using V8's "hidden class" optimization. From a closely-related section of the Dart source:
// Use the newly created object as prototype. In Chrome,
// this creates a hidden class for the object and makes
// sure it is fast to access.
In the V8 engine, a constructed object is given a "hidden" C++ class to represent its set of properties. By constructing an object whose prototype is the properties object, the property values of properties become part of the new instance's C++ hidden class, which improves property-access speed.
I believe all objects in V8 have hidden classes by default, so the need for this technique isn't immediately obvious. However, it is possible for an object to lose its hidden class (and enter "slow mode" or "dictionary mode") by demonstrating that it doesn't benefit from the optimization. When an object deletes one of its properties or adds too many properties that are unrelated to the properties of any other objects, V8 assumes that a shared hidden class isn't valuable, because the object has no other similar object to share its hidden class with. This convertToFastObject function can re-instate a "slow mode" object's right to a hidden class by using it as the prototype of a newly constructed instance.
Related hidden class question, arising from a different Dart optimization: What is this generated code supposed (intended) to do?
Where data is stored in a script contributes directly to the amount of time it takes to execute. In general, there are four places from which data can be accessed in a script:
-Literal value
-Variable
-Array item
-Object property
Reading data always incurs a performance cost, and that cost depends on which of these four locations the data is stored in. if you create a property using the "Object.Prototype.", the scope here is "Object.Prototype" which is smaller than the object's scope "Object." that hold in addition the local vars and stuff non enumerable. That is why creating proprieties using Prototype have a faster access ! Read these 2 articles to get better understanding:
1- http://oreilly.com/server-administration/excerpts/even-faster-websites/writing-efficient-javascript.html 2-http://www.packtpub.com/article/using-prototype-property-in-javascript

Access [[NativeBrand]] / [[Class]] in ES6 (ECMAScript 6)

I was reading over the draft for ES6, and I noticed this note in the Object.prototype.toString section:
Historically, this function was occasionally used to access the string
value of the [[Class]] internal property that was used in previous
editions of this specification as a nominal type tag for various
built-in objects. This definition of toString preserves the ability to
use it as a reliable test for those specific kinds of built-in objects
but it does not provide a reliable type testing mechanism for other
kinds of built-in or program defined objects.
From reading this thread on es-discuss, it sounds like [[Class]] is being replaced with [[NativeBrand]] in the ES6 draft so that they can specify it as being non-extensible (those were at least Allen Wirfs-Brock's thoughts).
Curious, I ran a quick test in FireFox and Chrome (with experimental JavaScript enabled):
Object.prototype.toString.apply(new WeakMap());
=> '[object WeakMap]'
"WeakMap" is not one of the [[NativeBrand]]s specified in the ES6 draft. However, this test returned "[object WeakMap]" on both browsers.
So I'm confused. I have a few questions.
1. Do Chrome and Firefox behave correctly?
From one way of reading the draft it sounds like they should return [object Object] (and all of this is pretty new, so I wouldn't be surprised to see this change in future editions of these browsers). However, it's hard for me to understand the intention of this section of the draft, especially since there are some places with "???".
Does anyone who has been following es-discuss more fervently have any relevant information? Or anyone who can understand the draft language better?
2. Is there an alternative to Object.prototype.toString?
From the note quoted above it makes it sound as if Object.prototype.toString is retained for legacy reasons, as if there's something new now that should be used instead. Especially the part of the node that reads "it does not provide a reliable type testing mechanism for other kinds of built-in ... objects". Does that mean that future built-ins can't be tested with this method?
Let's use a concrete example.
If I want to ensure an object I have received from an unknown source is a String object (an actual constructed String object, not a primitive string), I could do:
if (Object.prototype.toString.apply(unknownObject) != '[object String]')
throw new TypeError('String object expected.');
This lets me know if unknownObject is a String object no matter what frame it was constructed in.
My question is, should this be the approach I take moving forward into ES6? Or is there an alternative? Something like Object.getNativeBrandOf?
3. Since [[NativeBrand]] seems like it won't include future types of objects, how would one test for these objects?
Will this work?
if (Object.prototype.toString.apply(unknownObject) != '[object Symbol]')
throw new TypeError('Symbol expected.');
...assuming Symbol is the eventual name for Private Names.
Should I use this?
if (Object.prototype.toString.apply(unknownObject) != '[object WeakMap]')
throw new TypeError('WeakMap expected.');
... or something else?
The reason I ask is I am currently writing code that I want to be able to transition as easily as possible to ES6 in a year or two when possible. If there is a replacement for Object.prototype.toString, then I can just shim it in and continue from there. Thanks!
Update
benvie's answer provided me with the correct term to search for and understand the answer to my questions.
I found an email from Allen Wirfs-Brock on es-discuss concerning this issue.
Here's what I found, for anyone else asking the same questions:
1. Do Chrome and Firefox behave correctly?
Yes, why is explained below.
2. Is there an alternative to Object.prototype.toString?
As it is now, there will be a couple "alternatives" in the sense of possibilities, but not in the sense of replacements.
a. Using the ##toStringTag symbol. However, my understanding is that Object.prototype.toString should still probably be used. ##toStringTag is provided to allow extending the results that can be returned from Object.prototype.toString. If you have a prototype you would like to add your own string tag to, you could use ##toStringTag to set the value to any string. Object.prototype.toString will return this value except in the case where this value is one of the ES5 built-ins, in which case the string tag will be prepended with '~'.
b. Using private symbols on user-defined objects. I read one email promoting this as the best way to do the same type of check on a user-defined object. However, I don't see how that really settles the issue, as I fail to understand how it could be a cross-frame solution and it doesn't let you check against ES6 built-ins.
So even though there are some alternatives, it's good to stick with Object.prototype.toString now and going forward, with one caveat:
It'll work to make sure you have an ES5 built-in, such as String, but it won't be fool-proof to make sure you have an ES6 built-in because they can be spoofed with ##toStringTag. I'm not sure why this is, and I may be missing something, or it could change as the spec evolves.
3. Since [[NativeBrand]] seems like it won't include future types of objects, how would one test for these objects?
As mentioned above, Object.prototype.toString can still be used on ES6 built-ins, but it's not fool-proof as it can be spoofed by anyone with access to the ##toStringTag symbol. However, maybe there shouldn't be a fool-proof method, since Object.prototype.toString(weakmap) == '[object WeakMap]' doesn't mean that weakmap instanceof WeakMap (and it shouldn't!). The weakmap could have come from another frame, or it could be a user-created weakmap-like object. The only thing you really know is it reports to be functionally equivalent to a WeakMap.
It does seem to beg the question why you can't have a user-defined object which reports to be functionally equivalent to a String or Array (sans the prefixed "~").
This is currently a moving target in the ES6 spec. For the existing set of objects, the existing mechanics are maintained for various reasons including compatibility. In the most recent ES6 spec, published October 26th, you can find some hints of the potential future direction
15.4.6.2.4 ArrayIterator.prototype.##toStringTag
The initial value of the ##toStringTag property is the
string value "Array Iterator".
15.14.5.13 Map.prototype.##toStringTag
The initial value of the ##toStringTag property is the string value "Map".
You can find the original discussion that originated this in this thread on es-discuss

Writing ECMAScript5 compliant code (Part 2)

I am currently learning advanced JavaScript, with an aim to build a standards compliant (HTML5, CSS3, ESv5) library. Along my way I have already asked a couple of related questions to try and figure out where to start, what to do, what not to do, what to avoid etc. I have already begun reading the ECMA-262 (ECMAScript version 5) documentation, and have been running a few tests before I get started on development work.
Previous questions:
Writing ECMAScript5 compliant code
What's the difference between JavaScript, JScript & ECMAScript?
In my research I found out that different browsers implement the standard differently, and in that respect, they implement different objects. For example, IE implements an object called ActiveXObject, but this is not the case in FireFox. So I wrote a little test facility which determines if something is defined within the browser.
Consider the following which tests a few known objects (including jQuery since this is not built in).
Again, I have reached a point where I am in need of help:
Questions:
Given the example above, what is the difference between an object and a function?
Do I write functions or objects in ES/JS?
Why is Object a function and not an object?
Is there any hierarchical structure to built in objects / functions?
Can built in objects / functions be redefined as something entirely different?
Can built in objects / functions be undefined?
Can built in objects / functions be assigned new features if they do not already support them natively?
If an object is defined in one browser and not another, how can I compensate for this?
P.S. I do not want answers relating to specific implementations (JavaScript/JScript), rather answers relating to the standard (ECMAScript v5). Thanks in advance!
Given the example above, what is the difference between an object and a function?
In Chrome, all these items are functions. In general however, a function is an object with the addition that it holds code and that you can call it. So, you can also just add properties to functions (like jQuery does: $("selector") or $.ajax).
Do I write functions or objects in ES/JS?
Well, obviously that depends on what you code. function() {} gives you a function; {} gives you an object. (Again, functions are objects in the end.)
Why is Object a function and not an object?
Object is a function because you can call it, either as a constructor or not:
Object(); // returns an empty object
new Object(); // same
Also, given that almost everything is an instance of Object, it follows that Object is a constructor and thus a function. (Note again that functions are also objects.)
Is there any hierarchical structure to built in objects / functions?
As for the ECMAScript built-in objects, there is in a sense. There are constructor functions (String) on the global object, functions for instances (Array.prototype.forEach), and "static" functions (Object.defineProperty which is meant to be used on objects, Array.isArray for arrays).
Can built in objects / functions be redefined as something entirely different?
Sure, you can do Object = null. But any code relying on Object will start throwing exceptions, so it's not recommended at all.
Can built in objects / functions be undefined?
No, an object is not undefined by definition. undefined is not an object and vice-versa. This holds for any object.
Can built in objects / functions be assigned new features if they do not already support them natively?
Yes, if e.g. Array.prototype.forEach does not exist, you could set it yourself. But it should be noted that such functions turn up in for(var key in arr) loops which again can cause code to behave differently. This can be solved using Object.defineProperty by using {enumerable: false}. But there is another caveat: the function is shared across the whole environment (e.g. the current page). If other code is also setting them you're experiencing collisions.
If an object is defined in one browser and not another, how can I compensate for this?
You can "shim" such functions. For e.g. ES5 functions such as Array.prototype.forEach there are shims available which make them available on older browsers as well. Underscore.js may be a good example.
Given the example above, what is the difference between an object and a function?
A function is just an object which is callable. However, I guess you ask for the types of host objects (Node, HTMLCollection etc): Their behaviour is implementation-dependent ("not ecmascript-native") - you can't rely on anything.
Do I write functions or objects in ES/JS?
Huh? You write code, which can be interpreted.
Why is Object a function and not an object?
Object is the native object constructor, and therefore a function (and also an Object).
Is there any hierarchical structure to built in objects / functions?
Do you ask for "Everything is an Object"? If you ask for the structure of DOM interfaces: They are implementation-dependent host objects again, but most implementors have a inheritance system based on the DOM specification.
Can built in objects / functions be redefined as something entirely different? Can built in objects / functions be undefined?
No. You can overwrite the global variables pointing to them (the properties of the global object), but every instance will nevertheless be constructed from the native (then [nearly] unaccessible) constructors.
Can built in objects / functions be assigned new features if they do not already support them natively? If an object is defined in one browser and not another, how can I compensate for this?
Yes, you can extend the native objects and their prototypes. But watch out for host objects, they might not like it. If an object is defined only in certain environments, you can easily test for its existance and possibly shim it (es5, html5).
As part of my research into ECMAScript / JavaScript, I have found the following resource which provides a lot of information regarding the JS DOM.
http://krook.org/jsdom/index-all.html

Categories