nitinku5021a
nitinku5021a

Reputation: 129

Dynamic attaching property to constructor and use in new object instance?

var Person = function(firstname, lastname){
  this.firstname = firstname;
  this.lastname = lastname;
};

Person.greet = function(){
  console.log("Hello there ! "+ "My name is: "+ this.firstname);
};

var nk = new Person('Mark', 'Z');
console.log(nk.firstname);

nk.greet(); // Error in attaching

So I am trying to attach the function "greet" to the constructor "Person" outside of it. I can certainly do it with prototype but just trying to understand why the above code doesn't work?

For example: this will work:

var Person = function(firstname, lastname){
      this.firstname = firstname;
      this.lastname = lastname;
      this.greet = function(){
      console.log("Hello there ! "+ "My name is: "+ this.firstname);
    };
    };

    var nk = new Person('Mark', 'Z');
    console.log(nk.firstname);

    nk.greet(); 

From MDN:

Function objects created with the Function constructor are parsed when the function is created. This is less efficient than declaring a function with a function expression or function statement and calling it within your code, because such functions are parsed with the rest of the code.

All arguments passed to the function are treated as the names of the identifiers of the parameters in the function to be created, in the order in which they are passed.

Invoking the Function constructor as a function (without using the new operator) has the same effect as invoking it as a constructor.

The global Function object has no methods or properties of its own, however, since it is a function itself it does inherit some methods and properties through the prototype chain from Function.prototype.

Function instances Function instances inherit methods and properties from Function.prototype. As with all constructors, you can change the constructor's prototype object to make changes to all Function instances.

Upvotes: 2

Views: 1056

Answers (3)

Ruan Mendes
Ruan Mendes

Reputation: 92274

As explained by squint

Person.prototype.greet = function... puts the function on the object from which the new instances inherit

That means there will only be one greet function that is shared by all instances.

When you set this.greet in the constructor, you are creating a new instance of the greet function for every instance of person (new Person().greet != new Person().greet). It mostly has the same behaviour with a little more memory usage.

When you do Person.greet, that attaches a method to the constructor, that is not used for each instance. In classical programming, it could be seen as a static method.

I think you will find my blog post helpful http://js-bits.blogspot.com/2014/10/understanding-prototypical-inheritance.html

Upvotes: 1

Xinzoop
Xinzoop

Reputation: 111

The trick is: "this" is not Person constructor, but is the new instance (nk) in your example.

So "this.greet" and"person.greet" are completely different.

In your first example, you attach person.greet, but invoke nk.greet. Thats the reason.

Upvotes: 1

Damon
Damon

Reputation: 4336

You already know the answer - use the function's prototype object which is specifically intended for creating new instances of your constructor. Consider what you are actually doing:

function foo () {
  this.prop = 1
}

foo.bar = function () {
  return this.prop // - not defined
}

foo.prototype.baz = function () {
  return this.prop  // 1
}

var f = new foo()
f.bar // undefined; f.bar() // => Error 
foo.bar // a function that returns undefined when called
f.baz // a function that returns 1 when called
foo.baz // undefined; foo.baz() // => Error

The salient point is: The instance =/= the constructor =/= the prototype object. You are defining a property directly on the constructor, this means you can call that property from the constructor Person.greet() (even though anything you define on the object in the constructor will be undefined because the constructor function is never called in this case). You cannot call that method from an instance of the function because the instance is a separate object from the constructor function. Defining this.greet in the constructor will work, and some people use this approach, however, the one drawback is that these properties will be locked on individual instances. Using the prototype allows you to make a change that affects every instance.

Upvotes: 1

Related Questions