3gwebtrain
3gwebtrain

Reputation: 15297

Javascript - How to create new instance of functions

I know that, we can create the new instance of functions by the following approach. But my question is there any other way to achieve the same?

var Person = function (firstName) {
  this.firstName = firstName;
  console.log('Person instantiated');
};

var person1 = new Person('Alice');
var person2 = new Person('Bob');

// Show the firstName properties of the objects
console.log('person1 is ' + person1.firstName); // logs "person1 is Alice"
console.log('person2 is ' + person2.firstName); // logs "person2 is Bob"

Since, some time in case of new declaration fails, i am not getting the error too..

Especially, in javascript oops concept requires the different approach.

Some times, I am confusing without even calling the new key words it all works fine.. what is the different between using the new keyword and without using that?

example :

var setColor = function (color) {
   return color;
}

var x = setColor('red');
var y = setColor('blue');

console.log(y);
console.log(x);

Upvotes: 2

Views: 2889

Answers (4)

JLRishe
JLRishe

Reputation: 101738

The new [Function] keyword does many things, but the main things it does are:

  • Creates a new object
  • Uses [Function]'s prototype as the parent prototype for the new object
  • Executes the contents of [Function], using this as a reference to the new object

If you call such a function without new, the this reference will be determined the way it would usually be determined when calling a function, and quite often this would be the global object.

One thing you can do to help catch these mistakes more easily is to use strict mode:

"use strict";

var Person = function (firstName) {
  this.firstName = firstName;
  console.log('Person instantiated');
};

var person1 = Person('Alice');

If the above code were executed, this would be null instead of the global object, and you would get an error right away instead of having the properties assigned to the global object (and having hard-to-catch bugs).

A way to avoid these kinds of mistakes with new altogether is to simply have the function return a new object instead of being a constructor:

var person = function (firstName) {
  console.log('person instantiated');
  return {
      firstName: firstName
  };
};

var person1 = person('Alice');
var person2 = person('Bob');

If you do this, it doesn't matter whether you use new or not, because the function doesn't use this.

Edit There was a question below about prototypes. If you are unfamiliar with prototypes, this is a feature that allows you to specify properties and methods that will be shared between all instances of an object:

"use strict";

var Person = function (firstName) {
  this.firstName = firstName;
  console.log('Person instantiated');
};

Person.prototype.getMyName = function () {
    return this.firstName;
};

var person1 = new Person('Alice');
console.log(person1.getMyName());

If you do this, then all instances created with new Person() will share the getMyName method.

The new-less option I detailed later on does not provide this automatic prototype extension, but there are alternatives:

Option 1 - don't use a prototype:

var person = function (firstName) {
  console.log('person instantiated');
  return {
      firstName: firstName,
      getMyName: function () {
          return this.firstName;
      }
  };
};

Option 2 - Use Object.create() to extend the prototype:

var person = function (firstName) {
  console.log('person instantiated');
  var person = Object.create(person.prototype);
  person.firstName = firstName;

  return person;
};

Option 3 - Use Object.assign() method to copy the contents of the prototype to a new object:

var person = function (firstName) {
  console.log('person instantiated');

  return Object.assign({
      firstName: firstName
  }, person.prototype);
};

Upvotes: 3

Joel Cox
Joel Cox

Reputation: 3469

I think you need a bit better understanding of how objects and prototyping work in Javascript.

Consider you have a use case where you want an object that represents a user, and stores their first_name.

Without using any functions, you can simply create an object with your desired properties:

var person = {
    first_name: 'joel'
};

This is a standard javascript object - nothing special at all, and no usage of the new keyword to construct it. An alternate syntax to accomplish the same thing would be:

var person = new Object();
person.first_name = 'joel';

Again - this is just a standard object - nothing special at all.

The main reason for creating new instances of a function, is to use javascript's prototyping system. This is similar to a class in other languages. Let's say you wanted all instances of a person to have a method called getName(). You could either make sure you create that method on every person you have...

var person = {
    first_name: 'joel',
    getName: function() {
        return this.first_name;
    }
};

or...

var person = new Object();
person.first_name = 'joel';
person.getName = function() {
    return this.first_name;
};

However a better approach for this kind of thing, where you're always going to want this method defined for every user, is to create a new instance of a person object, and define the getName method on the prototype property of the Person function:

function Person() {}
Person.prototype.getName = function() {
    return this.first_name;
}

var user = new Person();
user.first_name = 'joel';
console.log(user.getName());

... Or as per your example, you can use a parameter to the Person constructor function to set the first name property:

function Person(first_name) {
    this.first_name = first_name;
}
Person.prototype.getName = function() {
    return this.first_name;
};
var user = new Person('joel');
console.log(user.getName());

Note that using this method you would always use the new keyword when creating a Person instance. The reason for this becomes clear when you consider the followng:

function Person() {this.first_name = 'joel'; return 'test';}
console.log(window.first_name); // Undefined, as expected
console.log(Person()); // Shows "test";
console.log(window.first_name); // shows "joel".
console.log(new Person()); // Shows "{first_name: 'joel'}"

Note that on line 4 above, you can see that by omitting the new keyword on a function call that expects you to be using it, you've accidentally modified a property on the window object, instead of setting it on a new regular object.

Effectively - you can consider usage of the new keyword to cause the return value of the Person function to be disrecarded, and instead you'll be given back a new instance of the Person Object.

Also note that you can reduce the risk of accidental modifying of the window object by omitting the new keyword from inside your function, by checking if this is equal to window and returning a new instance of your function instead:

function Person() {
    if (this === window) return new Person();
    this.first_name = 'joel';
}

With the above, you can instantiate your person object using either of the following methods and both will have the same effect:

var user1 = new Person();
var user2 = Person();

For some more information on how javascript functions and prototype objects work, I suggest reading http://www.w3schools.com/js/js_object_prototypes.asp

Upvotes: 1

James Andino
James Andino

Reputation: 25789

Another possible structure using closures and not objects at all

This structure also can be nested creating private static variables

It has no use of the word this

var thing = function(private_var){

   function get(){
     console.log(private_var)
   }

   function set(z){
      private_var = z
   }

   return {
    get:get,
    set:set
   }


}

var x = thing(0)
var y = thing(1)

Please note :
This makes certain types of programmers freak out and panic

&& importantly x.say !== y.say

Upvotes: 2

wrshawn
wrshawn

Reputation: 439

Using the new keyword when you call a function sets the context (this) inside the function to be a newly instantiated object, rather than window or some other context, which is why you can assign to this.firstName inside the function, and then refer to it as person1.firstName.

Without using the new keyword, the value of this WONT be a blank object, so you will be assigning to window instead. In this case, you want to use new since you are using the function as a constructor. If you aren't planning to use the function as a constructor, you don't want to call it with new.

Upvotes: 2

Related Questions