Eugene Yu
Eugene Yu

Reputation: 3978

JavaScript Object creation with the 'new' keyword

I am studying JavaScript and being confused with its Object concept. I used to be a Java programmer and it is terrifying me that JavaScript does not have class. From what I've learnt so far, function can replace class in JavaScript. and you can instantiate the function by using the 'new' keyword like below.

function person() {
    var name;
    this.tellYourName = function() {
        return 'My name is ' + name;
    }
    this.setName = function(newName) {
        name = newName;
    }
}

var person1 = new person();

person1.setName('Chris');
alert(person1.tellYourName());

in the code above, I created an object 'person1' inheriting the properties from person function.

So here's my question. is person() an object? what I meant by object is whether the person() is a class or an instantiated object.

I was confused with this concept when I was studying closure. Here's the sample code

function closureTest(a) {
    return function(b) {
        return a + b;
    }
}

var test = closureTest(1);
alert(test(2));

Here I guess the closureTest function works as a method not a class. and var test = closureTest(1); line did not use the 'new' keyword. That means test variable will store the return value from the closureTest(1); But as you see the test variable is used as a an object of closureTest. How is this possible? because when I tried it with the test code below

function test(a) {
    return a;
}
var t = test(2);
alert(t);

prints out the return value of the test function as I expected.

I hope my question is not too confusing. I currently moved from Java to JavaScript and my thought that they will be almost same is all wrong. I read several lectures about Object concept in JavaScript but it get even more confusing. Thanks for your time reading this and hope I can get something from you :)

Upvotes: 3

Views: 1277

Answers (5)

Aadit M Shah
Aadit M Shah

Reputation: 74244

I understand your confusion. The only thing that Java and JavaScript have in common is C-like syntax and the name. Other than that Java and JavaScript are two very different programming languages:

  1. Java is a classical object-oriented programming language. JavaScript is a prototypal object-oriented programming language.
  2. In Java functions must be methods of a class. In JavaScript functions are first-class citizens. This makes JavaScript much more powerful than Java.
  3. Java traces its ancestry to C/C++. JavaScript traces its ancestry to Self and Scheme.

Unlike Java, JavaScript is not only an object-oriented programming language but also a functional programming language (although not as functional as Haskell or OCaml). Hence functions play a major role in JavaScript.

Functions in JavaScript may be used to:

  1. Create a template of an object (i.e. behave like a class).
  2. Encapsulate state and behavior (i.e. behave like a namespace).
  3. Share functionality and reduce redundancy (i.e. behave like a mixin).

Functions as classes

JavaScript doesn't have classes because it's a prototypal object-oriented programming language. Unfortunately the prototypal nature of JavaScript is hidden behind constructors to make it look more like Java. However this only makes it difficult for Java programmers to understand inheritance in JavaScript.

For example, say you have the following Rectangle class in Java:

public class Rectangle {
    public int width;
    public int height;

    public Rectangle(int width, int height) {
        this.width = width;
        this.height = height;
    }

    public int area() {
        return this.width * this.height;
    }
}

In JavaScript you would write the above as follows:

function Rectangle(width, height) {
    this.width = width;
    this.height = height;
}

Rectangle.prototype.area = function () {
    return this.width * this.height;
};

If you don't like this syntax then you can make it look more like a class as follows:

function CLASS(prototype) {
    var constructor = prototype.constructor;
    constructor.prototype = prototype;
    return constructor;
}

var Rectangle = CLASS({
    constructor: function (width, height) {
        this.width = width;
        this.height = height;
    },
    area: function () {
        return this.width * this.height;
    }
});

I have written a function called augment which may make your life easier.

Upvotes: 3

Nick
Nick

Reputation: 6025

A few theoretical observations :)

The notion that an object is an instantiation of a class is pretty unhelpful for understanding JavaScript. JavaScript involves prototypal inheritance, not classical inheritance. In other words, objects inherit properties from other objects further up the inheritance chain, but not from a class.

First, functions are objects in JavaScript. This means that functions can have methods.

Second, if a function is invoked with the new prefix, then a new object is created. This new object will be linked to the function's prototype, but this will refer to the new object. Functions designed to be used with new are called constructors.

Third, there are various ways to achieve the same thing. So you can do this:

// The capital for the function indicates a constructor function
function Person(name) {
    this.name = name;
}
Person.prototype.tellYourName = function() {
    return 'My name is ' + this.name;
};
Person.prototype.changeName = function(newName) {
    this.name = newName;
};    
var person1 = new person("Chris"),
    random_string = person1.tellYourName(); // Chris

Alternatively, you can achieve the same thing without using new.

function person(name) {
    // myName is a private variable
    var myName = name; // This line is actually unnecessary if you use name throughout

    return {
        // Public methods
        tellYourName: function() {
            return 'My name is ' + myName;
        },
        setName: function(newName) {
            myName = newName;
        }
    }
}
var person1 = person("Chris"); // Note that `new` is not used

The latter is usually preferred because of the data hiding that comes with it. In other words, the only way to get at the property name is using the public methods.

Upvotes: 3

Dima Kuzmich
Dima Kuzmich

Reputation: 1326

When you use a 'new' key word in JavaScript it performs several steps. First of all it's creates a new instance of Object with prototype of provided function, in your case it's person. Second step is calling a provided function with bounded context of newly created object. The last step is returning a newly created object. So the magic of object creation is all in a new operator. You can read about it here

Upvotes: 0

guleria
guleria

Reputation: 751

The examples your have shown above are two different use cases. In javascript every thing is treated as an Object. When you were using the new keyword for a function then your function Object is treated as a Class and the variable referred with this are your properties of class e.g.

var Person = function(){
    this.name = null;
    this.age = 0;
};

This is treated a Person Class with name and age as its properties which will be available with the instance/Object of the class Person and Object is created as

var someone = new Person();
//someone.name and someone.age are valid then.

But if not using this inside the function does not create it as a class thus it acts as a normal function as shown in your example2 which was returning another object/function which can be used. For more clarification on this matter your should read Object oriented javascript and some more links on this topic.

Upvotes: 0

Phani Koundinya
Phani Koundinya

Reputation: 21

First on the new keyword. Think of it this way: whatever you stored on this during the function body in person function, is passed when a new instance is created. So new Person() returns this and whatever functions you have set on this

On your second problem, think of it as a function returning another function. It is returning a function, not an object. A functions is technically an object. So when you call closuretest(1), you are basically returning

var test=  function(b) {
    return 1+b;
 }

so now if you call test(2) it becomes return 1+2 =3

Hope that helps

Upvotes: 2

Related Questions