Jump to content

Constructor Pattern


musicman

Recommended Posts

Hi,

 

I'm studying a constructor function pattern. I have made this constructor:

function Person( firstname, age, place ) {
    this.firstname   = firstname;
    this.age  = age;
    this.greeting = { Hello: function(){ console.log( "Hello " + firstname ); }, 
                YouAre: function(){ console.log( "You are " + age + " years old"); }
              }
    this.greeting2 = {
    Hello: function(){ console.log( "Hello " + this.firstname ); }, 
    YouAre: function(){ console.log( "You are " + this.age ); }
  }
}

Person.prototype = { 
  greeting3: {
    Hello: function(){ console.log( "Hello " + this.firstname ); }, 
    YouAre: function(){ console.log( "You are " + this.age ); }
  }
}

var Clara = new Person( 'Clara', '20' );

Clara.greeting.Hello(); // Hello Clara
Clara.greeting.YouAre(); // You are 20 years old

Clara.greeting2.Hello(); // Hello undefined
Clara.greeting2.YouAre(); // You are undefined

Clara.greeting3.Hello(); // Hello undefined
Clara.greeting3.YouAre(); // You are undefined

On the greeting2.Hello and greeting2.YouAre methods, 'this' name and age result is undefined, the same with greeting3 method.

 

The question is: How do we get a property value through a method inside an object array?

 

and who is 'this' in greeting2 and greeting3 functions?

 

Thanks!

Edited by musicman
Link to comment
Share on other sites

this most likely refers to greeting2/greeting3 rather than Person.

 

You should have a reference to the object itself like this:

function Person( firstname, age, place ) {
    var self = this;
    self.firstname   = firstname;
    self.age  = age;
    self.greeting = { Hello: function(){ console.log( "Hello " + firstname ); }, 
                YouAre: function(){ console.log( "You are " + age + " years old"); }
              }
    self.greeting2 = {
    Hello: function(){ console.log( "Hello " + self.firstname ); }, 
    YouAre: function(){ console.log( "You are " + self.age ); }
  }
}

For greeting3, if you want access to the self variable it will need to be declared inside the Person function.

  • Like 1
Link to comment
Share on other sites

Thank you, Ingolme! All works well now. Just an additional remark, have to make global var with the 'self' object, so we can use it in greeting3 as well.

var elem;

function Person( firstname, age, place ) {
    elem = this;
    this.firstname = firstname;
    this.age  = age;
    this.greeting = { Hello: function(){ console.log( "Hello " + firstname ); }, 
                YouAre: function(){ console.log( "You are " + age + " years old"); }
              }
    this.greeting2 = {
    Hello: function(){ console.log( "Hello " + elem.firstname ); }, 
    YouAre: function(){ console.log( "You are " + elem.age + " years old" ); }
  }
}

Person.prototype = { 
  greeting3: {
    Hello: function(){ console.log( "Hello " + elem.firstname ); }, 
    YouAre: function(){ console.log( "You are " + elem.age + " years old" ); }
  }
}

var Clara = new Person( 'Clara', '20' );

Clara.greeting.Hello(); // Hello Clara
Clara.greeting.YouAre(); // You are 20 years old

Clara.greeting2.Hello(); // Hello Clara
Clara.greeting2.YouAre(); // You are 20 years old

Clara.greeting3.Hello(); // Hello Clara
Clara.greeting3.YouAre(); // You are 20 years old

Thanks again!

Edited by musicman
Link to comment
Share on other sites

Making it global has the problem that if you create more than one instance of the object "self" only refers to the last instance created.

 

Just try creating two people and you'll see the problem.

 

Why is it necessary to have greeting 3 outside of the constructor?

Link to comment
Share on other sites

oh you're right. So the best way to do this is to keep the methods inside its constructor.. are you agree?

function Person( firstname, age, place ) {
    var elem = this;
    this.firstname = firstname;
    this.age = age;
    this.greeting = { Hello: function(){ console.log( "Hello " + firstname ); }, 
                YouAre: function(){ console.log( "You are " + age + " years old"); }
              }
    this.greeting2 = {
    Hello: function(){ console.log( "Hello " + elem.firstname ); }, 
    YouAre: function(){ console.log( "You are " + elem.age + " years old" ); }
  }
}

var Clara = new Person( 'Clara', '20' );
var Jason = new Person( 'Jason', '25' );

Clara.greeting.Hello(); // Hello Clara
Clara.greeting.YouAre(); // You are 20 years old

Clara.greeting.Hello(); // Hello Clara
Clara.greeting.YouAre(); // You are 20 years old

Jason.greeting2.Hello(); // Hello Jason
Jason.greeting2.YouAre(); // You are 25 years old

Jason.greeting2.Hello(); // Hello Jason
Jason.greeting2.YouAre(); // You are 25 years old

Clara.greeting2.Hello(); // Hello Clara
Clara.greeting2.YouAre(); // You are 20 years old

 

Edited by musicman
Link to comment
Share on other sites

If you're defining those yourself then yeah, that's the best way. You typically only need to modify the prototype if you're trying to extend something that is built-in or that you imported from somewhere else. Although this is the usual way to do that, rather than assigning an entire object to the prototype:

 

Person.prototype.greeting3 = { 
  Hello: function(){ console.log( "Hello " + this.firstname ); }, 
  YouAre: function(){ console.log( "You are " + this.age ); }
}
Also, you can always use console.log to print this to see what it's set to. The default is the window object unless it's in another scope.
Link to comment
Share on other sites

Thanks @justsomeguy!

 

this return [object Object] in greeting3. I think this represents the key-value (?).

 

And one thing I have learned from this study is how to add methods into a constructor as object array.

It seems like we shouldn't use methods in object array to modify a constructor prototype.

Link to comment
Share on other sites

When I check this constructor, this came from the function:

Person.prototype.greeting3 = {   Hello: function(){ console.log( this.constructor ); },   YouAre: function(){ console.log( this.constructor ); }}// function Object() { [native code] }// function Object() { [native code] }
Link to comment
Share on other sites

If I may ask another basic question, I read this article and I couldn't get Step #4.

 

I just couldn't get when it say:

 

When our _() function returns this , it is actually returning the entire window, or the global scope. Therefore, when we call _().toggle() , we are asking the browser to call the toggle() method which belongs to the window. Obviously this fails.

This problem can be solved by recursively creating another _ object using the new keyword.

 

 

why would we use this condition in a constructor like shown in the article (Step #4)..?

if (window === this) {
      return new _(id);
   }

Thanks!

Link to comment
Share on other sites

  • 2 weeks later...

If you try to print this it will always print that it is an object. That's what it shows when you tell it to print an object, and this is always an object unless you specifically set it to something strange.

 

why would we use this condition in a constructor like shown in the article (Step #4)..?

By default, this is usually set to the window object. That condition checks if that is the case and, if so, returns a new "_" object. The reason that works is because of the new keyword. It creates a new object and returns that if you are running in the global scope. Otherwise, it just returns the current scope.
  • Like 1
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...