Benjamin W
Benjamin W

Reputation: 2848

Create dynamic prototype like jquery function chain

I try to create a dynamic prototype like jQuery and able to function chain, but I got error without use new and inside of function, return this object correct?

    (function() {
      var peopleDynamicProto = function(name, age, state) {

        this.name = name;
        this.age = age;
        this.state = state;

        if (typeof this.printPerson !== 'function') {
          peopleDynamicProto.prototype.printPerson = function() {
            console.log(this.name + ',' + this.age + ',' + this.state);
            return this;
          };
        }

        if (!this.hasOwnProperty('gender')) {
          peopleDynamicProto.prototype.gender = 'male';
          return this;
        }
      }

      window.peopleDynamicProto = peopleDynamicProto;
      return peopleDynamicProto;

    })();

     //var person1 = new peopleDynamicProto('john', 23,'CA');
     //person1.printPerson();

    peopleDynamicProto('john', 23, 'CA').printPerson(); //got error

Anyone know where is the problem?

Upvotes: 1

Views: 397

Answers (4)

areiilla
areiilla

Reputation: 109

you cant create prototype inside contructor. see this explanation defining-prototype-methods-inside-the-constructor

use this keyword instead of prototype:

(function(){
    var peopleDynamicProto = function(name, age, state){

    this.name   = name;
    this.age    = age;
    this.state  = state;

    this.printPerson = function(){
            console.log( this.name + ',' + this.age + ',' + this.state );
            return this;

    }
    if( !this.hasOwnProperty('gender') ){
        peopleDynamicProto.prototype.gender = 'male';
        return this;
    } 
}
window.peopleDynamicProto = peopleDynamicProto;
return peopleDynamicProto;
})();

peopleDynamicProto('john', 23,'CA').printPerson();

or use prototype outside constructor(this is better since function object not recreated each time object created)

(function(){
 var peopleDynamicProto = function(name, age, state){

    this.name   = name;
    this.age    = age;
    this.state  = state;

    if( !this.hasOwnProperty('gender') ){
        peopleDynamicProto.prototype.gender = 'male';
        return this;
    } 
}
if( typeof this.printPerson !== 'function' ){
        peopleDynamicProto.prototype.printPerson = function(){
            console.log( this.name + ',' + this.age + ',' + this.state );
            return this;
        };
    }
 window.peopleDynamicProto = peopleDynamicProto;
return peopleDynamicProto;
})();

Upvotes: 1

kukkuz
kukkuz

Reputation: 42352

I guess you missed the new operator- see this for reference

The new operator creates an instance of a user-defined object type or of one of the built-in object types that has a constructor function.

See demo below:

(function() {
  var peopleDynamicProto = function(name, age, state) {

    this.name = name;
    this.age = age;
    this.state = state;

    if (typeof this.printPerson !== 'function') {
      peopleDynamicProto.prototype.printPerson = function() {
        console.log(this.name + ',' + this.age + ',' + this.state);
        return this;
      };
    }

    if (!this.hasOwnProperty('gender')) {
      peopleDynamicProto.prototype.gender = 'male';
      return this;
    }
  }

  window.peopleDynamicProto = peopleDynamicProto;
  return peopleDynamicProto;

})();

var person1 = new peopleDynamicProto('john', 23,'CA');
person1.printPerson();

new peopleDynamicProto('john', 23, 'CA').printPerson(); //got error

Upvotes: 1

Alex Santos
Alex Santos

Reputation: 2950

You have to use "new" if you want to create a new object based off a prototype. I am not sure what you are trying to do exactly, and why you are trying to create the prototype dynamically. I'm not going to say 100% sure, but I don't think jQuery does that (plus it looks like a very bad practice). If you're trying to do something like jQuery, where your class is chainable and can be chained as (new peopleDynamicProto(...)).print() or peopleDynamicProto(...).print(), then you can do something like this:

function peopleDynamicProto(name) {
  if (this instanceof peopleDynamicProto) {
    /* initialize attributes here */
    this.name = name;
  } else {
    return new peopleDynamicProto(name);
  }
}

peopleDynamicProto.prototype.printPerson = function() {
   console.log( this.name );
   return this;
}

Now you should be able call it in both ways:

peopleDynamicProto('john').printPerson();
(new peopleDynamicProto('john')).printPerson();

If you don't care about supporting both ways, then you can just return an object, e.g.:

function peopleDynamicProto(name) {
  return {
    name: name,
    printPerson = function() {
      console.log( this.name );
      return this;
    }
  };
}

peopleDynamicProto('John').printPerson();

(There are other ways of doing that)

Upvotes: 3

Nitesh
Nitesh

Reputation: 1550

I think the reason why you are getting such an error is because what you are returning here is a function not an object but you are trying to access a property of an object.

For eg, If you write as:

**

var myFun = function(){
 this.message = "TEST";
}

**

you cannot access myFUN.message because here myFun is a function not an object of this function constructor.

To access its property, you need to do something like (new myFun()).message;

Similarly in you case what you return is "peopleDynamicProto" which is a function only, not an object of this function constructor.

To access method printPerson (which is a member), you need to create an instance of peopleDynamicProto and access its member

Upvotes: 2

Related Questions