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?
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.
__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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With