Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Javascript prototype and __proto__ and getPrototypeOf issue

I have a simple class in javascript:

function foo() {
    this.bar = "bar";
}

var test = new foo;

console.log(foo.prototype,foo.__proto__)
/*output: foo {
               constructor: function foo() { 
               __proto__:   Object
              }
          ,
          function Empty() {}
*/
console.log(test,test.prototype,test.__proto__,test.__proto__.__proto__)
/*output: foo {
              bar: "bar"
              __proto__: foo
          }
          ,
          undefined
          ,
          foo {
              constructor: function foo() {
              __proto__: Object
          }
          ,
          Object {
              ...
          }
      */

What i dont understand:

At the first log the foo.prototype had the __proto__ attribute which was an Object At the second log the test.__proto__ had the __proto__ attribute which was an Object

When to use __proto__ and when prototype, what is the difference?


UPDATE:

In John Resig's blog in the instanceOf section there is something waht I don't understand:

If i use var asd = "asd";Object.getPrototypeOf(asd) it throws a TypeError but
If i use var dsa = new String("dsa");Object.getPrototypeOf(dsa) it returns String
But asd.constructor.prototype == dsa.constructor.prototype is true

Why is the Object.getPrototypeOf(asd) throws error? This is a string, isn't it?

like image 343
Gergely Fehérvári Avatar asked Dec 16 '22 13:12

Gergely Fehérvári


2 Answers

Always use prototype or Object.getPrototypeOf.

__proto__ is non-standard and has been deprecated by Mozilla.

John Resig has a good blog entry about it.


The reason why test.prototype is undefined is because you created a new object that does not have a constructor prototype. Here's an example of when to use Object.getPrototypeOf.

js> function foo(){}
js> typeof foo.prototype;
object
js> var f = new foo();
js> typeof f.prototype;
undefined
js> typeof Object.isPrototypeOf(f);
object
js> typeof f.constructor.prototype;
object
js> foo.prototype === Object.getPrototypeOf(f);
true
js> foo.prototype === f.constructor.prototype;
true

As you can tell, inheritance in JavaScript is tricky. Lets look at an example:

js> typeof "asdf";
string
js> typeof String("asdf");
string

The string literal is of type string. The same is true when calling String() as a function. Now, because of behavior of the new operator, a new object is created, with the prototype of String() as its parent.

js> var s = new String("asdf");
js> typeof s;
object

Because JS likes to coerce things, you can get at the string literal a few ways:

js> s
asdf
js> s.valueOf();
asdf
js> typeof s
object
js> typeof s.valueOf();
string

Prototypal Inheritance in JavaScript by Crockford helped me a lot when learning about JS inheritance.

From Mozilla's Strings page:

String objects may be created by calling the constructor new String(). The String object wraps JavaScript's string primitive data type with the methods described below. The global function String() can also be called without new in front to create a primitive string. String literals in JavaScript are primitive strings.

like image 148
Jeremy Avatar answered Dec 30 '22 00:12

Jeremy


__proto__ is an intermediary object between an object and it's prototype. The biggest benefit in using it is that you can change the prototype chain for an object entirely without modifying the instance or the prototype.

Example:

function F() {} 
F.prototype.a = 1;
var f = new F();
f.__proto__ = { b : 2 }; 
"a" in f => false; 
"b" in f => true;

But as Jeremy said, __proto__ is deprecated. The only use case would be if you would like to add a set of properties to an object, changing its prototype without having to iterate through each one. Not a big deal.

like image 26
Adam Bergmark Avatar answered Dec 30 '22 02:12

Adam Bergmark