1

my question here is about functions and objects in javascript. I have three questions that stems from one to other. In the below example, I try to access the value of 'a' in test, but I get undefined. but I create a new object of test, then I am able to access the 'a' value and change it.

//create a function called test
         var test=function() {
           this.a=2
           this.b=3 };
           test.a//undefined
//create a object called test1 using 'new'
test1 = new test();
test1.a//2
//change the value of a in test1
test1.a=4
test1 //Object { a=4, b=3}

while trying to find why this happens, I came across this javascript functions are objects? and another question popped out of this. The accepted solution for that SO question is below

var addn = function func(a) {
  return func.n + a;
};

addn['n'] = 3;
addn(3);

I changed the 'func.n' to 'this' and it no longer works

var addn=function func(a) {
 return this.n+a;
};
addn['n']=3;
addn(3); //NaN

making anonymous function with 'this' also did not help

    //anonymous function
var addn=function(a) {
     return this.n+a;
    };
    addn['n']=3;
addn(3); //NaN

why using 'this' did not work?

one final question, what is the difference in using keyword 'new' and 'createObject'. Douglas Crokford suggests using 'CreateObject' in his book, but I fail to understand why. Thanks all for your comments

Community
  • 1
  • 1
brain storm
  • 30,124
  • 69
  • 225
  • 393

2 Answers2

5

1. Functions are constructors for new objects

When you call new FuncName, the function acts as a constructor, and the value of this inside points to the object being constructed (not the function itself). When you remove new, this becomes undefined, falling back to the global object (unless you're in strict mode).

2. Functions are also objects

Every function is an instance of Function, so the functions themselves are objects and can have have their own properties. Those properties cannot be accessed with this.propName inside the function body, only with funcName.propName. That's because this inside a function is never the function object itself (unless you forced it to be, with bind, call, or apply).


I hope both topics above help you understand how functions work. As for your final question: Crockford's createObject is a different way to implement inheritance, doing basically what Object.create does in ES5-compliant browsers. It allows an object to inherit straight from another object, without requiring you to manually create a new constructor, set its prototype property (which is an example of a property on a function object), and create an instance with new. Crockford prefers that, and said he stopped using new in favor of this approach.


In response to the questions you asked in chat, here is an attempt to explain what functions are and what they do, with examples.

Functions can be just... functions

You call them, they do something:

function alertThis(what) {
    alert(what)
}
alertThis("alerting something");

You can also pass them values, and have them return values

function timesTwo(num) {
    return num * 2;
}
timesTwo(2); // 4

They can be passed and return anything, including objects...

function createPerson(firstName, lastName) {
    return {
        firstName : firstName,
        lastName : lastName
    }
}
var john = createPerson('John', 'Doe');
john.lastName; // "Doe"

...and other functions:

function timesN(n) {
    return function(num) {
        return n * num;
    }
}
var timesThree = timesN(3);
timesThree(5); // 15

Functions are objects

Functions can be passed around and returned like any ordinary object. That's because they are objects. Like any object, they can have properties:

function countCalls() {
    countCalls.timesCalled++;
}
countCalls.timesCalled = 0;
countCalls();
countCalls();
countCalls.timesCalled; // 2

One very important default property of functions is prototype. It's a special property, and we'll see why.

Functions can act as constructors for new objects

Functions can behave like class constructors do in regular OO languages. When called with new, they create a new object of a certain "class". This new object is called this inside the function, and is automatically returned:

function Person(firstName, lastName) {
    this.firstName = firstName;
    this.lastName = lastName;
}
var john = new Person('John', 'Doe');
john.firstName; // "John"
john instanceof Person; // true

... unless you deliberately return something else:

function Person(firstName, lastName) {
    this.firstName = firstName;
    this.lastName = lastName;
    var fakePerson = {
        firstName : firstName,
        lastName : lastName
    };
    return fakePerson;
}
var notPerson = new Person('John', 'Doe');
notPerson.firstName; // "John"
notPerson instanceof Person; // false
// Note: the object called 'this' inside the function is created, but
// after the function is called there is no outside reference to it.

Objects created by constructors know who created them, and can see their prototype property

Back to a real person:

function Person(firstName, lastName) {
    this.firstName = firstName;
    this.lastName = lastName;
}

// Add something to the Person prototype
Person.prototype.sayHi = function() {
    return "hi, I'm " + this.firstName;
}

var john = new Person('John', 'Doe');
john.sayHi(); // "Hi, I'm John"
john.constructor; // Person

The object john can sayHi() because it has access to everything inside its constructor's prototype property. But it cannot see other properties of Person directly (only through their own constructor property):

function Person(firstName, lastName) {
    this.firstName = firstName;
    this.lastName = lastName;
    Person.timesCalled++;
    // There is no 'this.timesCalled', only Person.timesCalled
}
Person.timesCalled = 0;
var john = new Person('John', 'Doe');
john.timesCalled; // undefined - john cannot be called, Person can
john.constructor.timesCalled; // 1
Community
  • 1
  • 1
bfavaretto
  • 71,580
  • 16
  • 111
  • 150
  • Thanks bfavaretto. now I understand that 'this' points to object being created. can you explain what you mean by "when you remove new, 'this' becomes undefined..." and regarding object.create and new, does it mean everytime an object is constructed using new, its prototype needs to be initialized, can I not have it part of the new construction itself by placing function methods inside the main function itself.? Thanks again – brain storm Jun 19 '13 at 21:22
  • 1
    When you call a function without `new`, it's not invoked as a constructor, and `this` is not set to the object being constructed (as there is none). The following code will create a global variable named `bar`: `function foo(){this.bar = true}; foo();`, because `this` will mean the global object (`window`). – bfavaretto Jun 19 '13 at 21:28
  • 1
    The difference between using `Object.create` or `new` has more to do with *inheritance*. `Object.create` just allows you to setup inheritance in a less verbose way (as long as you don't need a constructor). – bfavaretto Jun 19 '13 at 21:32
  • +2:Thanks again for the clarification. in this example,var obj = function() { this.x= 1; return { increment: function() { this.x = this.x + 1; } } }; var test1=new obj(); test1.x //undefined ...but when I remove the return statement section and just have var obj = function() { this.x= 1; }; var test1=new obj(); test1.x//1...why having the return statement does not allow access to x.. – brain storm Jun 19 '13 at 21:37
  • 1
    @user1988876 Because in this case the constructor is not returning the object it was constructing, but the new one you told it to return; `this` inside the constructor refers to the former. – bfavaretto Jun 19 '13 at 21:42
  • following up on what you said, I made one line change here;var obj = function() { this.x= 1; return { increment: function() { this.x = this.x + 1; return this.x;} } }; test1 = new obj(); var c=test1.increment(); c;//now the value of c is NaN..I dont understand why it is NaN – brain storm Jun 19 '13 at 21:49
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/32042/discussion-between-bfavaretto-and-user1988876) – bfavaretto Jun 19 '13 at 21:50
  • Thanks bfavaretto. In the second example on the section above on `Functions can act as constructors for new objects`, you return `fakeperson`. Then when you create a new object `notPerson`, do we need the `new` keyword, since `Person` return `fakeperson`. you also mention `the object called 'this' inside the function is created, but after the function is called there is no outside reference to it`. Since we are returning, `this` is destroyed after the function call rite, if there is no return, then is `this` preserved. – brain storm Jun 21 '13 at 19:18
  • your explanation above is very complete. can you give one illustration where using the keyword `new` and `object.create` will make difference. I was reading somewhere here that by using `new`, everything is cloned into the object from parent but by using`object.create` only the prototypes but not the properties that gets inherited. what does this mean, if this is correct, Any illustration would here help a lot. Thanks a lot again. you are awesome!! – brain storm Jun 21 '13 at 19:21
  • @user1988876 My explanations have already gone way to far from the original scope on of your question. If you have doubts about new vs. Object.create, please search this site for answers, and/or post a separate question. – bfavaretto Jun 21 '13 at 19:29
  • @bfaveretto. I will do that. can you comment on first question above after "continue this discussion in chat". That will help to see if my understanding has been clear. sorry and Thanks very much – brain storm Jun 21 '13 at 20:22
  • @user1988876 [I already answered that in chat](http://chat.stackoverflow.com/transcript/message/10099356#10099356) – bfavaretto Jun 21 '13 at 21:28
0

1. addn['n'] = 3; //Means you add static property n to the function(object) addn. so addn.n also work.

2 this.n means property n of the instance. this.n === undefined so it returns NaN.

3 var addn=function func(a) means you give a second name to func. var addn=function(a) is better format in most case.

4 createObject is not a native javaScript code. 'New' is.