2

in this example a property called 't' is added to speak function.Speak.t=5;when i call speak() it prints the value 5 via another function called show.But when i create new instance of Speak it doesn't inherit the property t.Why is that so??i mean if it is a property of Speak constructor all its instances should inherit it??

<html>
<body>
<script>
function Speak(){

    show(Speak.t);
}
Speak.t=5;
function show(v){
    console.log('value is : '+v);
}
Speak();
var s1=new Speak();
console.log(s1.t);
</script>
</body>
</html>
AL-zami
  • 8,902
  • 15
  • 71
  • 130
  • 1
    I'm positive this *has* to be a duplicate, but I can't find it. – CodingIntrigue Aug 29 '14 at 07:23
  • Speak.something would be static: http://stackoverflow.com/questions/25253831/javascript-inherit-static-and-instance-methods-properties/25255577#25255577 prototype is shared by instances: http://stackoverflow.com/questions/16063394/prototypical-inheritance-writing-up/16063711#16063711 – HMR Aug 29 '14 at 08:51

4 Answers4

4

"i mean if it is a property of Speak constructor all its instances should inherit it?"

No. Its instances inherit from the constructor's prototype, not the constructor itself. JavaScript is prototype-based, not "Constructor-based". If you are familiar with other OOP languages, Speak.t will be similar to a public static property.

Changing it to Speak.protoype.t = 5 will add the property t: 5 to the prototype which will be inherited to all of its instances:

function Speak(){
    show(this.t);
}
Speak.prototype.t = 5;

function show(v){
    console.log('value is : '+v);
}

var s1 = new Speak();    //"value is : 5"
console.log(s1.t);       //5

Since instances inherit from its constructor's prototype, you can actually achieve class inheritance by doing this:

function SpecialSpeak(){}
SpecialSpeak.prototype = new Speak();

This creates a Speak instance and assign it as the SpecialSpeak's prototype.

new SpecialSpeak() instanceof SpecialSpeak;     //true
new SpecialSpeak() instanceof Speak;            //true

Since all Speak instances will be updated if its prototype has changed, it will also update SpecialSpeak's prototype and also update all SpecialSpeak's instances.

var s = new SpecialSpeak();
s.v;                             //undefined
Speak.prototype.v = "text";
s.v;                             //text

This demonstrates how inheritance works in JavaScript. The chaining of prototypes is sometimes called a "prototype chain".

You might also want to check out this great article about inheritance.


Side note: Since all prototype chains must have a starting point,

Object.prototype instanceof Object;    //false

Although Object.prototype is an object, it is the very top prototype (object) that everything* inherits from, therefore it's not an instance of Object. It is the Object!

* Starting from ES5, Object.create is introduced which lets you create objects that doesn't inherit from Object.prototype.

Derek 朕會功夫
  • 92,235
  • 44
  • 185
  • 247
  • Instance of parent to set prototype part of child and child not re using parent constructor? Would it not be better to refer to an article that shows how to use prototype? – HMR Aug 29 '14 at 08:53
  • 2
    @HMR - I have added a link to the inheritance article on MDN. – Derek 朕會功夫 Aug 29 '14 at 09:04
1

When the new operator is called on a constructor function, the JavaScript engine executes a few steps behind the scene:

  1. It allocates a new object inheriting from your constructor function's prototype
  2. It executes your constructor function, passing the newly created object as this
  3. If your constructor function returns an object, then it uses it. Otherwise it uses the this object.

At no time it considers the class properties attached to the constructor function. This is why Speak.t = 5 doesn't create an inherited property.

However, those pieces of code will do:

// By attaching `t` to the prototype
function Speak1() {}
Speak1.prototype.t = 5;

// By attaching `t` to the newly created object
function Speak2() {
  this.t = 5;
}

// By returning an object containing `t` (thus overriding the formerly allocated this)
function Speak3() {
  return {
    t: 5
  };
}

DEMO

You can read here for more information.

aymericbeaumet
  • 6,853
  • 2
  • 37
  • 50
1

This happens because you don't set internally the value of t. You should instantiate the value of t inside the constructor of Speak like this :

function Speak(){
  this.t = 5;
  show(this.t);
}
function show(v){
    console.log('value is : '+v);
}
Speak();
var s1=new Speak();
console.log(s1.t);

You could also attach the showmethod inside the constructor to access the prototype of it.

var Speak = (function() {
  function Speak() {
    this.t = 5;
    this.show();
  }

  Speak.prototype.show = function() {
    return console.log('value is : ' + this.t);
  };

  return Speak;

})();

var s1=new Speak();
console.log(s1.t);
gaelgillard
  • 2,483
  • 1
  • 14
  • 20
  • i didn't understand your second example .you have declared another Speak function inside another Speak function.it's confusing.little explanation would've been better.thanks anyway..:) – AL-zami Aug 29 '14 at 08:43
  • The `var Speak`will contains the function returned by an auto-executed function. In this auto-executed function, I created the function Speak and attached the `t` property and the `show` function to his prototype. Is it clear now ? – gaelgillard Aug 29 '14 at 11:05
1

Since functions are just objects t becomes a property of the function Speak, which is not shared with the instances.

for e.g functions by default get a property called length ( gives arity of the function) which will not be shared with the instances.

function Speak(){}
var obj = new Speak();
console.log("length" in Speak); // true
console.log("length" in obj); // false

you can see quite clearly the length is not shared with the instances. In javascript the only way to have a property or a method shared is through the prototype pattern.

Creating a property this way, makes it behave like a static variable on Speak

Prabhu Murthy
  • 9,031
  • 5
  • 29
  • 36
  • function argument have length property.But how a function itself has a length property.i mean what Speak.length might return?? – AL-zami Aug 29 '14 at 08:47
  • 1
    for e.g if you a function say function test(a,b){}. test.length will be 2. length gives you the number of parameters that the function can accept . this just asserts the fact that functions are just objects in javascript – Prabhu Murthy Aug 29 '14 at 08:48
  • @BOSS - `.length` does not give you the number of parameters that the function can accept. Instead, it returns the number of parameters that the function expected. – Derek 朕會功夫 Aug 29 '14 at 17:29