3

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 :)

Tarik
  • 73,061
  • 78
  • 222
  • 327
Eugene Yu
  • 2,898
  • 4
  • 18
  • 27
  • 5
    Ignore everything you know about Java. Java and Javascript have almost nothing in common; they were named like that for marketing purposes. – user2357112 supports Monica Aug 04 '13 at 06:13
  • I was going to vote for a duplicate here, but accidentally clicked enter instead of backspace... then chose wrong and cannot vote for duplicate anymore. Please close this question as a duplicate of http://stackoverflow.com/questions/1646698/what-is-the-new-keyword-in-javascript – Antti Haapala Aug 04 '13 at 06:29
  • @user2357112 I believe I should do so.. Thanks your words I will keep that in my mind – Eugene Yu Aug 04 '13 at 06:39
  • An "object" in javascript is more analogous to a HashMap in java. It's only a collection of key-value pairs -- but they can be of any type (other objects, or even functions). Technically you can think of Objects in java as the same thing except for the fact that you pre-declare what keys can be put in the HashMap and what the types of the values are. Javascript does have built-in language features to predeclare and make "pre-cut" HashMap/objects -- also known as Classes (which can be seen as a declaration of what keys/values an object can have) – Justin L. Aug 04 '13 at 06:41
  • @Antti Haapala the link you posted was helpful. I will close the queestion – Eugene Yu Aug 04 '13 at 06:41
  • @JustinL. Yes the accessibility to properties in function works similar to HashMap in Java. Thanks :) – Eugene Yu Aug 04 '13 at 06:44

5 Answers5

3

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.

Nick
  • 5,767
  • 10
  • 50
  • 77
  • Very helpful. Especially the capital letter indicates constructor function part kinda solved my problem. But more question here, when does the object for function person(name) is created in the second code? the line where the function is declared? or var person1 = person("Chris");? – Eugene Yu Aug 04 '13 at 06:50
  • I mean I tested your second code with these var person1 = person("Chris"); var person2 = person("Malcom"); But it seems like person1 keeps the name Chris. Does this mean the 'new' keyword is hidden when assigning the person to variable? – Eugene Yu Aug 04 '13 at 07:01
  • @EugeneYu The person1 object is created in the line `var person1 = person("Chris");`. Another object is created by your line `var person2 = person("Malcolm");`. The `Person` function is an object itself, of course, but not in the same way. Regarding your second question, there is no hidden `new` keyword, but it does create the same result. In the second version, the function `person` returns an object `{...}`. That's what the parens `{...}` are doing here - you enclose arrays with `[...]` & objects with `{...}`. So you return an object with two methods, but these methods can access `myName`. – Nick Aug 04 '13 at 07:11
  • @EugeneYu The best book to read is "JavaScript: The Good Parts" by Douglas Crockford. It's quite short, but you'll need to read the 60 key pages about ten times before you understand it properly :) – Nick Aug 04 '13 at 07:13
  • Advice noted. Thanks for spending your time to help me. I will definitely check out the book now. – Eugene Yu Aug 04 '13 at 07:19
3

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.

Aadit M Shah
  • 67,342
  • 26
  • 146
  • 271
2

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

0

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.

guleria
  • 729
  • 2
  • 11
  • 21
  • 3
    there are no classes in Javascript, and thinking of functions as classes will get you lost in no time. – Antti Haapala Aug 04 '13 at 06:27
  • @Antti you are right that there are no classes but treating them as classes helps in understanding this concept better – guleria Aug 04 '13 at 07:25
0

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

Dima Kuzmich
  • 1,211
  • 10
  • 17