0

The following is the code

function add() {
  var counter = 0;
  this.num = 0;
  function plus (){ return counter +=1;}
  plus();
  return counter;
}

console.log(add.num); //outputs :undefined

Function name can be treated as reference of a function object, so the num is the property of add function object, the outputs could have been 0. But the result is not like so, why?

If i change the code to:

function add() {
      var counter = 0;
      this.num = 0;
      function plus (){ return counter +=1;}
      plus();
      return counter;
    }
var obj = new add();
    console.log(obj.num); //outputs : 0

it works correctly. Can anyone explain this? Many many many thanks.

eileen Tao
  • 1,023
  • 1
  • 8
  • 8
  • `console.log(this)` in the function body. – zerkms Jan 30 '15 at 02:54
  • `num` is not a property of the `add` function object. It's a property of the object that you create with `new add`. – Barmar Jan 30 '15 at 02:54
  • @Barmar " It's a property of the object that you create with new add" --- that's not entirely correct. `add.call(anyOtherObject);` – zerkms Jan 30 '15 at 02:55
  • What happens if you try `console.log(new add().num);` – Sir Jan 30 '15 at 02:57
  • @Dave, the output is '0', correct. But what i don't understand is why "add.num" not works. – eileen Tao Jan 30 '15 at 03:08
  • @zerkms: I think you missed **`new`** `add`. `new add` definitely creates a new object and `this` will refer to it. – Felix Kling Jan 30 '15 at 03:09
  • @eileenTao: Because functions don't have a property `add` (by default). But even if `this` referred to the function, you are not calling `add`, so the code inside of it is never executed. The assignment `this.num = 0;` never takes place. – Felix Kling Jan 30 '15 at 03:09
  • 1
    @FelixKling I didn't. My point was for the OP to compare `this` inside a call and `console.log(add)` outside and see they are different things. So the OP could see their mistake immediately, without too much of theory – zerkms Jan 30 '15 at 03:09
  • @zerkms: I was referring to your comment to Barmar. Sorry, that was not clear. – Felix Kling Jan 30 '15 at 03:11

4 Answers4

2

this refers to current instance of your function. until you create a new instance using new add() this will refer to window object.

add.num will check if add has a property named num. Which is false because add refers to a function definition not an instance/object of function.

function add() {
  var counter = 0;
  this.num = 0;
  function plus (){ return counter +=1;}
  plus();
  return counter;
}

console.log(add.num); //outputs :undefined  because add=function(){};

while in another case, when you create object using new it returns you a javascript object having all the public properties.

///obj=Object{ num : 0};

function add() {
      var counter = 0;
      this.num = 0;
      function plus (){ return counter +=1;}
      plus();
      return counter;
    }
var obj = new add();
    console.log(obj.num); //outputs : 0 because obj is {num:0}

Fiddle to play: http://jsfiddle.net/ZpVt9/76/

Vijay
  • 2,965
  • 1
  • 15
  • 24
  • 2
    'this will refer to `window` object.' is not correct. `this` points to global object which may be `window` if the script is executed inside a browser. – Anurag Peshne Jan 30 '15 at 03:04
  • Thats more of depends on the scope of execution. I assumed he is executing in window global scope. – Vijay Jan 30 '15 at 03:08
  • @Vijay well, it makes sense to add some words about the global object though. – zerkms Jan 30 '15 at 03:10
  • "add" has the property named "num", because if i add "add.num = 1 before console statement", then console.log(add.num), the output is 0; – eileen Tao Jan 30 '15 at 03:12
  • @eileenTao if you add it - then it has it, that's correct. – zerkms Jan 30 '15 at 03:13
  • that is because when you add it..javascript interpreted nature checks if add has any property `num`..if not it **adds** and assign the value you supplied. – Vijay Jan 30 '15 at 03:14
  • @Vijay, you mean the statement "add.num = 1;" makes javascript interpreter to treate "add" as an instance/object of function? – eileen Tao Jan 30 '15 at 03:17
  • Not the object of function. It adds it as hidden properties of function definition itself. Try to console `add.num` before assigning and after assigning. – Vijay Jan 30 '15 at 03:19
  • @Vijay "It adds it as hidden properties" --- could you clarify the "hidden" term please? – zerkms Jan 30 '15 at 03:21
  • @Vijay, Many thanks. Function can be treated as an object, why you say"not the object of function"? Can you explain this to me? Lots of thanks! – eileen Tao Jan 30 '15 at 03:24
  • by object of function means `new add()`, what you are saying is function as object itself ;) Anywyz thanks :) – Vijay Jan 30 '15 at 03:28
  • @zerkms: by hidden mean it is not accessible through prototype. javascript standerds says to add properties using prototype...but language support this unusual way too (skipping prototype) – Vijay Jan 30 '15 at 03:29
  • @Vijay,sorry for disturb you, "by object of function means new add(), what you are saying is function as object itself ", what's the difference? – eileen Tao Jan 30 '15 at 03:33
  • 1
    @Vijay " javascript standerds says to add properties using prototype" --- it does not. You are free to add properties to objects without using prototypes. – zerkms Jan 30 '15 at 03:48
  • @eileenTao: Functions **are** objects. Everything but a primitive (string, number, boolean, null, undefined) is an object. – Felix Kling Jan 30 '15 at 04:14
1

It will help to read-up on this in JavaScript: MDN

When you do new add(), the interpreter creates a new JavaScript Object/Hash and binds it to this variable in the function. So this is valid inside the scope of the function.

When you don't do a new you are calling the function without a context, so this is undefined in such cases (in 'use strict' mode).

You can explicitly pass a context to Functions using Function.apply/Function.call/Function.bind

Chintan
  • 374
  • 2
  • 9
1

this inside a function points to different object depending on how the function is called:

  1. If the function is called in the global context (outside any function) this points to global object (which is window if the script is executed within a browser). console.log(this === window) will output true.
  2. If this is referred inside a function, then it depends if we have set strict mode.

    • If the code is in strict mode then this will be undefined unless we explicitly assign it to something.

    • If the code is not in strict mode then this will point to global object. (Which is again window if script is executed in a browser).

  3. If function is used as constructor to make new objects then this points to the new object being made.

  4. If function is used as object method then this points to the object method is called on.

More explanation with examples here: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this


Every function is an object in JavaScript. But as you can see from above explanation none of the ways this points to function object itself from the same function body. Thus the only way you can set function's property is by directly assigning it to the function without using this.

There is another way of adding a property to functions. This is a very bad idea of doing so as adding any property this way will reflect in all functions used. Every function is linked to Function.prototype object. Thus adding any property in this object will get reflected in all functions.

Function.prototype.someProperty = 1;
//now try accessing it via any function object
console.log(add.someProperty); //should print 1 to console.
Anurag Peshne
  • 1,547
  • 12
  • 29
-2

"num" is not a property of the "add" function is a property of the object created and returned by that function if you want to add num to your add function you need to do

add.prototype.num=0; 

and remove it from your objects definition

Dayan Moreno Leon
  • 5,357
  • 2
  • 22
  • 24
  • "is a property of the object created and returned by that function" --- it's a property of a bound object, which may be created anywhere. – zerkms Jan 30 '15 at 02:56
  • by defining any property/function in the prototype of a constructor, you make it part pf the function and not bound to the object, hence you can do, function.property, because it belongs to the functions prototype and it will be available to all the objects created by that function – Dayan Moreno Leon Jan 30 '15 at 02:59
  • I'm not sure how your answer clarifies OP's confusion about why the 1st example doesn't work PS: it's not me who downvoted – zerkms Jan 30 '15 at 02:59
  • @Dayan Moreno Leon , why i need to add "num" to "add" function, "add" can be treated as an object, the add object has already the property "num". – eileen Tao Jan 30 '15 at 03:01
  • no, the object generated by the add function has a "num" property, the constructor doesn't – Dayan Moreno Leon Jan 30 '15 at 03:02
  • 1
    @DayanMorenoLeon well, I'm not an OP and I understand how it works. My point was that your current answer does not clarify anything to the OP (which we can see after their comment above) – zerkms Jan 30 '15 at 03:02
  • 2
    Do you seriously suggest me to read about it or you confuse me with OP? Take a second and compare a name who asked this question then mine. – zerkms Jan 30 '15 at 03:04
  • whel the question asked why the code didin't work, i gave a simple answer, how is my answer incorrect please? – Dayan Moreno Leon Jan 30 '15 at 03:05
  • 1
    I did not say it's incorrect. I'm just saying that it's not helpful to OP. Just compare with another +1'd answer To clarify: I still didn't downvote you here. – zerkms Jan 30 '15 at 03:07
  • i am not betting to get the best answer, i was just trying to point to the right path, give me a fish and ill have a meal, teach me how to fish and ill never be hungry ;), is not an incorrect answer yet has been downvoted twice, makes people doubt about helping other – Dayan Moreno Leon Jan 30 '15 at 03:09