It returns Person. Why doesn't it return 'John' ?
Because that Object.create line creates an object with the Person function as its prototype, and the Person function object has a surprising definition of the name property that prevents your writing to it. (The definition makes sense once you know about it, but it's surprising at first.)
What you're creating when you do
john = Object.create(Person);
...is an object that uses the Person function as its underlying prototype. This doesn't create a Person instance (which would use Person.prototype as its prototype), it creates an object that actually uses the function object Person itself as the prototype.
The Person function has a non-writable property called name which is the name of the function (this is not yet in the standard, but it will be in ES6 [currently it's defined in §9.2.11 of the draft spec] and V8 does it already). Because that property is not writable, john.name = 'John' doesn't do anything. (More on non-writable properties below.)
If your goal was to create a new object with Person.prototype as the object's underlying prototype, you'd do:
john = new Person();
or
john = Object.create(Person.prototype);
And since Person accepts an argument, you'd probably do
john = new Person('John');
...rather than assigning to name afterward.
More on non-writable properties: If you haven't run into them yet, they were defined as part of the 5th edition spec a while back. Here's an example:
var parent = {};
Object.defineProperty(parent, "foo", {
writable: false,
value: "original"
});
The parent object has an non-writable property, foo:
console.log(parent.foo); // "original"
parent.foo = "bar";
console.log(parent.foo); // "original"
If we use parent as a prototype, we still can't write to foo even on the child object:
var child = Object.create(parent);
console.log(child.foo); // "original"
child.foo = "bar";
console.log(child.foo); // "original"
That's what's happening in your code. parent is Person, and child is john.
And just to round this out: If we wanted to create a writable property on the child at this point, we could, but just not via assignment we'd have to use defineProperty:
Object.defineProperty(child, "foo", {
writable: true,
value: child.foo // (just sets the initial value)
});
console.log(child.foo); // "original"
child.foo = "bar";
console.log(child.foo); // "bar"
Now child has its own property called foo, which shadows (hides) its prototype's foo, and is writable.