Difficulty Manually Walking The Prototype Chain - javascript

I wanted to try manually walking the prototype chain of a few objects just to see what I find along the way. However, I got stuck on the first one that I tried. Here's the code:
function MyObject() { }
var x = new MyObject();
console.log('--------------------------------------------');
console.log('x.constructor.name: ' + x.constructor.name);
console.log('x.constructor.prototype.constructor.name: ' + x.constructor.prototype.constructor.name);
console.log(x.constructor.prototype === Function.prototype ? 'Good guess.' : 'No, you are wrong.');
console.log(x.constructor === MyObject ? 'Good guess.' : 'No, you are wrong.');
console.log('--------------------------------------------');
The above code results in the following output in the Developer Tools Console of Google Chrome:
--------------------------------------------
x.constructor.name: MyObject
x.constructor.prototype.constructor.name: MyObject
No, you are wrong.
Good guess.
--------------------------------------------
It makes sense that x's constructor is the MyObject function, since x was instantiated using the new keyword on MyObject (this follows from the definition of a constructor). Because of this, I understand the first line of output (note: I started counting lines of output from zero on up). The second line, however, confuses me. I would like to know what MyObject's prototype is. Apparently, it isn't an object of type Function, as indicated by the 3rd line of output, which tells me that I'm wrong. The fourth line of output just reinforces the output from the first line.
On a more general note, I assumed that the correct way to walk the prototype chain of an object would be to go from the object in question to its constructor, and then from the constructor to the constructor's prototype, assuming that this last reference is not null. I assumed that this two-step process (consisting of going to the constructor, and then to the constructor's prototype) should be repeated until a null reference from a constructor to a prototype is reached, thus signifying the end of the prototype chain. This doesn't seem to be working, though, since application of this algorithm to the above scenario just leads to circular references.
In summary, I have two questions:
Why is x.constructor === x.constructor.prototype.constructor (or, in other words, why the circular references), and what kind of an object is x.constructor.prototype, anyway (or, in other words, how did it get instantiated / where did it come from)?
How can the above algorithm be corrected in order to correctly walk the prototype chain for object x?
Edit
I came across a similar question on StackOverflow here, but it doesn't explicity ask the correct way to walk the prototype chain. It does point out the circular references, though...

In Javascript terminology, an object a's "prototype" refers to the object from which a inherits properties. The standards-based way to access this is with Object.getPrototypeOf:
var protoOfA = Object.getPrototypeOf(a);
There's also the old way, non-standard but supported by some browsers:
var protoOfA = a.__proto__;
But if you have a function F, F.prototype does NOT refer the object from which F inherits anything. Rather, it refers to the object from which instances created by F inherit:
function F() {};
a = new F();
console.log(Object.getPrototypeOf(a) === F.prototype); // true
When you define a function, an object is created to serve as the prototype of instances created by that function, and this new object is stored in the function's prototype property.
--
Functions behave like objects in many ways (e.g., they can have properties) but they aren't exactly like other objects:
console.log(typeof a); // "object"
console.log(typeof F); // "function"
Their "prototypes" are ill-defined (example run in Chrome) (this is apparently a Chrome-specific behavior)
console.log(Object.getPrototypeOf(F)); // "function Empty() {}"
console.log(Empty); // ReferenceError: Empty is not defined
--
The constructor property is strange. The interpreter doesn't care about it. MDN says, confusingly:
Returns a reference to the Object function that created the instance's prototype.
Further, you can change the value of constructor on an object, but this has no effect on what the object is or how it behaves - it's merely descriptive.
--
So, to answer your questions:
Why is x.constructor === x.constructor.prototype.constructor
No good reason. This is arbitrary behavior browsers have converged on.
what kind of an object is x.constructor.prototype, anyway
In this example, t's x's prototype, the same as Object.getPrototypeOf(x). But in general you can't rely on x.constructor or anything derived from it, because it's arbitrary.
How can the above algorithm be corrected in order to correctly walk the prototype chain for object x?
for (var p = x ; p != null ; p = Object.getPrototypeOf(p)) {
// do something with p
}

Yeah, this can be a bit difficult to grasp at first. I cannot do better than provide you some links. These always help me out when I am in trouble.
http://dmitrysoshnikov.com/ecmascript/javascript-the-core/
http://mckoss.com/jscript/object.htm
http://zeekat.nl/articles/constructors-considered-mildly-confusing.html
Q1: For the "why" see the references above. x.constructor.prototype is x.__proto__ that is the internal "real" prototype of x, at least in your case when no prototype and constructor properties were overwritten. It is created the moment you define the function MyObject.
Q2: Unfortunately you cannot do it this way. You can use the __proto__ property where it is supported, but see
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/proto

Related

What is meaning of Function.prototype.__proto__?

I am a beginner in Javascript and am learning about Object Oriented and prototyping in it.
As far as I know, Object is a function and is created by Function because Object.__proto__ === Function.prototype but looking through various diagrams online, I am quite confused by fact that How Function.prototype.__proto__ === Object.prototype.
What does Function.prototype.__proto__ mean?
Isn't it something that is developed by language owners as Function is the first thing from which everything arrives.
Then what does it mean? Am I lacking some important fact? I looked through other StackOverflow answers but can't find anything related to it.
TL;DR
__proto__ is a property of an object which enables you to look up in the prototype chain. While prototype is a property of a Function which enables you to add shareable functionalities to a constructor function.
Long Answer
Understand this from an example, let's say you create a constructor function.
function A() {} and then create an instance of it, var a = new A().
Then, add a function as following:
A.prototype.getA = function () { return 'A'; }.
Now, if you try to access a.getA(), you'll get the result, i.e. getA will be executed.
But how does it know about the function getA even though getA has been added after the instance a was created. It's because of using __proto__, you can traverse up in the chain (you must have heard about prototype chaining).
Technically, __proto__ is a property of an object, while prototype is a property of function. But how could functions have property? Because everything in JavaScript is converted implicitly to an object. Ever wondered how could you something like this: 'test'.toUpperCase()? Isn't string literals are 'not object' and they are primitives?
Read this for reference: http://jayendra.co.in/objects-in-javascript/
Now to answer your question:
What does Function.prototype.__proto__ mean?
You are trying to access the prototype property of Function constructor function. Remember, prototype itself is an object, so you can access properties like constructor and __proto__.
Function.prototype.__proto__ === Object.prototype
To enable chaining, when you access __proto__ property, you are looking up!
Any function can access all the properties of an object. How?
A property of Object, let's say toString. You can do, A.toString() // A created at the start. But we never created a function toString for A constructor function!
myFunc.prototype is the __proto__ of any object constructed by calling new myFunc().
Thinking in terms of classical (Java- or C++-style) OO, you could say that myFunc is a constructor and (therefore) myFunc.prototype is the class. In that sense, myFunc.prototype.__proto__ is the superclass; that is, the prototype of the prototype of all objects created with new myFunc.
One useful thing you can do to myFunc.prototype.__proto__ is assign to it to create a superclass relationship, e.g.
myFunc.prototype.__proto__ = mySuperclassConstructor.prototype
This idiom sheds light on why Function.prototype.__proto__ === Object.prototype holds (the core of your question): it simply means that Function is a subclass of Object — Or in other words, JavaScript runtimes do something equivalent to the above code snippet in their prelude so as to make Function a subclass of Object (as they should, per ECMA-262 §§ 19.2.2 and 19.2.3)
Careful though, while __proto__ happens to work on all modern (2019) JavaScript implementations (node.js and browsers), its use is both non-standard and slow. Consider using “real” ES6 classes instead.

Does New make any sense in this case?

Is there any case where a Constructor returns something on purpose and it still makes sense to new it?
var Fn = function(){
return this.fn = function(){}
}
var a = new Fn()
var b = Fn()
I can't seem to find any difference between a and b from console, but just in case I missed something, are they identical? Apart from b's side effect of adding fn as a method to window object. And if they're the same, does it mean that when a Constructor returns something, it's no longer a Constructor and shouldn't be newed?
Edit, the reason I'm asking is that I'm working with Coffee and Angular at the moment, while both seem to be pretty sensitive about return, especially with providers. Do you have any best practises regarding this?
Yes. The new invocation creates a new this context in which the function inside the constructor will be evaluated. Without it, the invocation assumes the local context and attaches your function to it. This is really important if you have multiple functions that you want to bind a unique object to.
I had the same question you did, and read the spec. I wrote about this in What the 'new' operator means to Javascript.
Arun's answer is half-right, in that it's true for the special case that you're working at the base level of the Javascript interpreter, where this === windows (or, for Node, this === global; for PLv8, this === role). Inside other objects (a really common occurrence when working with modern libraries like jQuery or Backbone!), the this operator is the local context, not the windows root.
So with the information #Elf provided, as in
When the [[Construct]] property for a Function object F is called, the following steps are taken:
Create a new native ECMAScript object.
Set the [[Class]] property of Result(1) to “Object”.
Get the value of the prototype property of the F.
If Result(3) is an object, set the [[Prototype]] property of Result(1) to Result(3).
If Result(3) is not an object, set the [[Prototype]] property of Result(1) to the original Object prototype object as described in 15.2.3.1.
Invoke the [[Call]] property of F, providing Result(1) as the this value and providing the argument list passed into [[Construct]] as the argument values.
If Type(Result(6)) is Object then return Result(6).
Return Result(1).
When the Constructor intentionally returns something, that something would get returned in Result(6), therefore defying the purpose of Constructors--to return Result(1) as an instance.
The only possible use of this is to take advantage of Step 6 and call the Fn with certain arguments and certain this, which, could easily be done without using Constructors and a simple call. So I guess, if Constructors return stuff, it ain't Constructor anymore.
Edit:
The interesting exception being, the object returned is Result(1) on purpose, in order to be able to take arbitrary number of arguments: Use of .apply() with 'new' operator. Is this possible?. Thanks #Elf.

What does this sentence mean: "In other words, obj.prototype is in general not the obj's {Prototype}."

I am trying to understand the new word in javascript. The top answer here What is the 'new' keyword in JavaScript? recommends this article.
In that article, in the prototypes section, the author says:
In other words, obj.prototype is in general not the obj's {Prototype}.
What does this mean? I have a hazy understanding of prototype (object that begets other objects). I understand that javascript does not have classes in the way that C# and Java have classes. Is that what the sentence above is expressing?
I'm not sure that article is the best way to understand what's going on here - it's a great technical explanation, but perhaps not the best way to get an intuitive understanding.
Let's step back and work this through.
A quick look at property lookup
One way to understand prototypal inheritance is to think of it as way to say "if I don't have it, look over there".
Say you've got an object and try to access a property that doesn't exist, JS will return the value undefined:
var x = {};
x.foo //=> undefined
All objects inherit from Object.prototype, so look what happens if we modify it:
var x = {};
x.foo //=> undefined
Object.prototype.foo = 'hello there';
x.foo //=> 'hello there';
What happened? When we initially create x, JavaScript sets up an internal [[Prototype]] property that points to Object.prototype. Effectively, there is a lookup algorithm that looks something like (pseudo-code):
Lookup(obj, prop) =
if HasProperty(object, property)
return GetPropertyValue(object, property)
else if HasPrototype(object)
return Lookup(PrototypeOf(object), property)
else
return undefined
In other words, start with the initial object, check for the property, if it doesn't have it, follow the prototype chain to keep looking for it. If we hit the end of the prototype chain, the property must be undefined.
So what about the new operator?
The new operator gives us a way to:
dynamically set the prototype of an object to something other than Object.prototype
do some initialization stuff when we create an object
NOTE: in ES5, we also have Object.create which gives you 1, but not 2.
When you say new Foo(a, b), here's what happens:
we make a new object that has its internal [[Prototype]] set to Foo.prototype.
we run the function Foo (its just a normal function) with its context (think this) set to the new object we just made
we return the new object after the function finishes (actually, if the function explicitly returns a value, we just return that value, but most of the time, we won't be doing that).
But wait, where did Foo.prototype come from?
Let's see - run the following in the console:
function Foo() {}
typeof Foo.prototype //=> "object"
When we create a function in JS, it comes with an object attached to its prototype property. It's just an object, like any other, so you can manipulate it, set/delete properties, even completely overwrite it (which the mentioned article shows an example of).
For example:
function Foo() {}
Foo.prototype.answer = 42;
var foo1 = new Foo();
var foo2 = new Foo();
foo1.answer //=> 42
foo2.answer //=> 42
// If you want you can change foo2's answer
foo2.answer = 'something else';
// Foo.prototype is unchanged
Foo.prototype.answer //=> 42
foo1.answer //=> 42 (still getting its answer from the prototype)
foo2.answer //= 'something else'
Getting back to the original question
Continuing with the foo example from above, what the original article was referring to is that foo1 and foo2 don't have prototype properties set on them:
foo1.prototype //=> undefined
foo2.prototype //=> undefined
NOTE: there is a non-standard __proto__ property that many JS engines provide that will give you an object's prototype, and in ES5, you also have Object.getPrototypeOf to get access to a given object's prototype.
Relevant links:
MDN's page on the new operator.
MDN's page on "working with objects".
I understand that javascript does not have classes in the way that C# and Java have classes. Is that what the sentence above is expressing?
No. While true, it has nothing to do with that sentence.
In other words, obj.prototype is in general not the obj's {Prototype}.
What does this mean?
An object might have a {prototype} (usually referred to as [[prototype]]), which is the object from which it does inherit properties. You can access that via the Object.getPrototypeOf() function, it is not a "visible" property of the object but some "hidden field".
Also, some objects (especially function objects) do have a .prototype property, i.e. a public attribute with the literal name "prototype".
The sentence states that these two "prototypes" are different from each other.
The question you linked now explains how the new keyword relates these different "prototypes". When you call a constructor function with new, then a new instance is created. The instance does inherit (its [[prototype]] will be set to) the prototype object of the "class" (which is shared amongst all instances) and that is looked up via the .prototype property of the constructor function.
As an example, let's look at the ObjMaker function from the code there. The ObjMaker.prototype (property) is the base for all ObjMaker instances. However, Object.getPrototypeOf(ObjMaker) is the object from which all function objects inherit from ([[prototype]]), which is Function.prototype.
The sentence means that you can't access an object's prototype using obj.prototype. You can access it with obj.__proto__ or Object.getPrototypeOf(obj) though. Also see the question __proto__ Vs. prototype in JavaScript.
The article is a bit dated. What it means is that prototype is a property. A property of a function object to be precise. It provides a way to define a prototype for objects created with this function. E.g.:
function Foo() {}
Foo.prototype.myMethod = function() {};
var myFoo = new Foo();
myFoo is an object and it has a prototype that contains the method myMethod.
The prototype of myFoo is not myFoo.prototype. That doesn't even exist.

Forcing a typecast of a custom object in javascript

Suppose I have 2 constructors and a member function defined
function A() {}
function B() {}
A.prototype.a = function(){}
And I've instantiated a B. How can I force a conversion to make it an A?
o = new B();
//What should I put here?
o.a();
I'm new to js. And I have a feeling that whether o mentioned above is an A or a B is merely controlled by a reference to a prototype. Therefore, I feel typecast should be possible.
Answers, as well as explanations that can help me understand js objects, are welcomed.
You can't change (that is, completely swap-out) the prototype of an object once it's been created (yet; in a future version of JavaScript, it's likely to be possible).
Objects in JavaScript are enormously malleable, though. You can do this, for instance:
o.a = A.prototype.a;
...and then o will have the a function. If you wanted to give it all of the enumerable properties of A.prototype (including any from its prototype):
var name;
for (name in A.prototype) {
o[name] = A.prototype[name];
}
The prototype property of functions is a completely normal, boring object assigned to a normal, boring property on the function. When you use new to create an object using that function (which is called a "constructor function"), the function's prototype property is assigned to the newly-created object as its underlying prototype (which has no name you can access in code [yet]).
As of ES5 (reasonably supported in Chrome, Firefox, Opera, and IE9; not in IE8 and earlier), you can get the prototype of an object via Object.getPrototypeOf, and you can create objects assigning them a prototype without going through constructor functions by using Object.create, but you can't change what an object's prototype is once it's been created.
Some JavaScript engines (like the one in Firefox) have a currently-non-standard extension called __proto__ which lets you directly access and manipulate the prototype of an object, by treating it as a property. E.g.:
o.__proto__ = A.prototype;
...but that is not standard at present. It may well be part of the next standard, though. If you're interested in information about the upcoming ES6, you can find draft specifications and such here.

Prototype chain can't get Object()?

I read an article which explains what prototype chain is.
It says that if I try to access an object's property but it doesn't have it, javascript engine will try it's .constructor.propotype. If it doesn't have it either then try .construtor.propotype.constructor.propotype. Untill it find the built-in Object().
But I test this:
function a() {}
b = new a();
then:
c = b.constructor.prototype
I get an empty a object.
then:
d = c.constructor.prototype
I get an empty a object.
It loops. No matter how many .constructor.prototype I call, it can't find Object(). What's wrong? Do I misunderstand the prototype chain?
In JS OOP the constructor and prototype properties are flaky, in that they aren't set for you when you perform inheritance. You are supposed to manually set/alter them to implement inheritance. See, for example, this tutorial.
It looks like the way you're trying to climb the prototype chain (by traversing through .constructor.prototype) never really reaches the Object top-level prototype, since when you have function a(){} the right constructor and prototype properties aren't set on a. I can't even manage to coerce them onto a; in Chrome I get:
> function a(){}
undefined
> a.constructor.prototype
function Empty() {}
> a.constructor.prototype = Object.prototype
Object
> a.constructor.prototype
function Empty() {} // hmmmm, the assignment didn't take...
Of course the runtime doesn't need to do this, since it has a reference to the actual prototype of each object. I.e. the language doesn't do the lookup via .constructor.prototype, it saves the prototype of each instance internally. So you can see how the lookup chain works if instead of .constructor.prototype you use .__proto__:
function a(){}
b = new a();
b.__proto__ === Object.prototype; // false
b.__proto__.__proto__ === Object.prototype; // true since we reached the top of the prototype chain
It is important to note that the property __proto__ has never been standard and in ES5 was standardised in a slightly different manner:
obj.__proto__ === Object.getPrototypeOf(obj);
This renders .__proto__ deprecated.
Looks like that I asked a stupid question.
if A is a function:
A.prototype.constructor === A
if A isn't a function:
A.prototype in a normal property.
So (in standard) there is no way to climb up the prototype chain.

Categories