2

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?

Community
  • 1
  • 1
bernie2436
  • 22,841
  • 49
  • 151
  • 244

4 Answers4

3

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:

  1. dynamically set the prototype of an object to something other than Object.prototype
  2. 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:

  1. we make a new object that has its internal [[Prototype]] set to Foo.prototype.
  2. we run the function Foo (its just a normal function) with its context (think this) set to the new object we just made
  3. 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:

satchmorun
  • 12,487
  • 2
  • 41
  • 27
  • great answer. But in your second-to-last example, why does foo2.answer return 12 instead of returning 'something else'. – bernie2436 Jan 12 '14 at 16:19
  • Good catch - I had initially used 12 and then decided to change it for some reason and forget to update it in both places. Edited. – satchmorun Jan 12 '14 at 16:32
2

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.

Bergi
  • 630,263
  • 148
  • 957
  • 1,375
1

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.

Community
  • 1
  • 1
nwellnhof
  • 32,319
  • 7
  • 89
  • 113
1

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.

a better oliver
  • 26,330
  • 2
  • 58
  • 66
  • What do you mean by "dated"? The article seems to explain it quite well and even is correct (maybe apart from the "initialiser inheritance" section). – Bergi Jan 12 '14 at 14:27
  • @Bergi "dated" means based on ECMAScript v3. I doesn't matter in terms of constructors, which is the main topic, but we now have `Object.getPrototypeOf`, e.g. – a better oliver Jan 12 '14 at 14:40