13

I known this has been asked hundreds of times, however, I can't seem to grasp the concept of prototype

Here's my sample script

var config = {
  writable: true,
  enumerable: true,
  configurable: true
};

var defineProperty = function(obj, name, value) {
  config.value = value;
  Object.defineProperty(obj, name, config);
}


var man= Object.create(null);
defineProperty(man, 'sex', "male");

var person = Object.create(man);
person.greet = function (person) {
    return this.name + ': Why, hello there, ' + person + '.'
}
var p=Object.getPrototypeOf(person);
alert(p.sex);//shows male
person.prototype.age=13;//why there is a error said the prototype is undefined? I thought it supposed be man object...

var child=function(){}
child.prototype.color="red";//why this line doesn't show error? both child and person are an object . 

alert(child.prototype.color);//shows red

var ch=Object.getPrototypeOf(child);

alert(ch.color);//why it is undefined? it is supposed red.

Hope you can give me some helps... thanks.

Updated:

Thanks your guys kindly help, Based on Elclanrs's answer, Below is what I learned.

Function is the one of the build-in objects in javascript. the 3 format creation function object are equal.

var function_name = new Function(arg1, arg2, ..., argN, function_body)
function function_name(arg1, arg2, ..., argN)
{
...
}
var function_name=function(arg1, arg2, ..., argN)
{
...
}

So, that is why create a prototype chain we have to create a function and then call it with the new keyword .

Function.prototype is the reference to All the Function object prototype.

Cheers

Joe.wang
  • 10,375
  • 20
  • 91
  • 164
  • This [post](http://stackoverflow.com/questions/1646698/what-is-the-new-keyword-in-javascript) is partly answer the question . very helpful. – Joe.wang Mar 12 '13 at 08:17

2 Answers2

13

The prototype property only exists on functions, and person is not a function. It's an object.

Here's what's happening:

var man = Object.create(null);         // man (object) -> null
man.sex = "male";

var person = Object.create(man);       // person (object) -> man (object) -> null
person.greet = function () { ... };

var p = Object.getPrototypeOf(person); // man (object) -> null
alert(p.sex);                          // p is the same object as man

person.prototype.age = 13;             // person doesn't have a prototype

var child = function () {};            // child (function) -> Function.prototype
                                       // -> Object.prototype -> null
child.prototype.color = "red";         // child has a prototype

var ch = Object.getPrototypeOf(child); // Function.prototype

alert(ch.color);                       // ch is not the same as color.prototype
                                       // ch is Function.prototype

For more information I suggest you read this answer: https://stackoverflow.com/a/8096017/783743

Edit: To explain what's happening in as few words as possible:

  1. Everything in JavaScript is an object except primitive values (booleans, numbers and strings), and null and undefined.

  2. All objects have a property called [[proto]] which is not accessible to the programmer. However most engines make this property accessible as __proto__.

  3. When you create an object like var o = { a: false, b: "something", ... } then o.__proto__ is Object.prototype.

  4. When you create an object like var o = Object.create(something) then o.__proto__ is something.

  5. When you create an object like var o = new f(a, b, ...) then o.__proto__ is f.prototype.

  6. When JavaScript can't find a property on o it searches for the property on o.__proto__ and then o.__proto__.__proto__ etc until it either finds the property or the proto chain ends in null (in which case the property is undefined).

  7. Finally, Object.getPrototypeOf(o) returns o.__proto__ and not o.prototype - __proto__ exists on all objects including functions but prototype only exists on functions.

Community
  • 1
  • 1
Aadit M Shah
  • 67,342
  • 26
  • 146
  • 271
10

I think you might be mixing concepts. Try grasping the concept of prototypes with classic prototype inheritance first, then you can get into all the new Object stuff.

In JavaScript, every object (numbers, strings, objects, functions, arrays, regex, dates...) has a prototype which you can think of as a collection of methods (functions) that are common to all current and future instances of that object.

To create a prototype chain you have to create a function and then call it with the new keyword to specify that it is a constructor. You can think of constructors as the main function that takes the parameters necessary to build new instances of your object.

Having this in mind, you can extend native objects or create your own new prototype chains. This is similar to the concept of classes but much more powerful in practice.

Similar to your example, you could write a prototype chain like this:

// Very basic helper to extend prototypes of objects
// I'm attaching this method to the Function prototype
// so it'll be available for every function
Function.prototype.inherits = function(parent) {
  this.prototype = Object.create(parent.prototype);
}

// Person constructor
function Person(name, age, sex) {
  // Common to all Persons
  this.name = name;
  this.age = age;
  this.sex = sex;
}

Person.prototype = {
  // common to all Persons
  say: function(words) {
    return this.name +'says: '+ words;
  }
};

// Student constructor   
function Student(name, age, sex, school) {
  // Set the variables on the parent object Person
  // using Student as a context.
  // This is similar to what other laguanges call 'super'
  Person.call(this, name, age, sex);
  this.school = school; // unique to Student
}

Student.inherits(Person); // inherit the prototype of Person

var mike = new Student('Mike', 25, 'male', 'Downtown'); // create new student

console.log(mike.say('hello world')); //=> "Mike says: hello world"

In newer version of JavaScript (read EcmaScript) they added new ways to deal with objects and extend them. But the concept it's a bit different from classical prototype inheritance, it seems more complicated, and some more knowledge of how JS works underneath would help to really understand how it works, plus it doesn't work in older browsers. That's why I suggest you start with the classical pattern for which you'll find accurate and abundant information on the internet.

elclanrs
  • 85,039
  • 19
  • 126
  • 159
  • Thank you for your kindly answer and help . I can't upvote it more. I updated my post. I have a question for you. Is it necessary to call with `new` keyword before I can use `.prototype`? – Joe.wang Jan 27 '13 at 08:26
  • @Joe.wang You may call the .prototype property of a constructor function (which will usually just return Object) or you must make a new instance of an object by using new with a constructor function. Once you've done that you can get the prototype by looking at the instances' constructor.prototype – user1739635 Mar 01 '15 at 22:24