1

Wondering why the init function ends up logging undefined since startDate is defined before logStartDate is called.
The Code:

var startDate;

var init = function(startDate) {
    this.startDate = startDate;
    logStartDate();
};

var logStartDate = function() {
    console.log(startDate);
};

init('2015-01-02');
Daniel Kobe
  • 7,696
  • 11
  • 44
  • 94
  • Maybe `window.startDate` instead of `this.startDate`? But I would suggests just using different names for the variables, like the answers below. – Danny Aug 04 '15 at 15:32
  • Why are you using `this.startDate` inside a regular function? That would be an error if you were running in strict mode because this is a poor construction. Start there to fix your problem. – jfriend00 Aug 04 '15 at 15:33
  • Why is it a poor construction, whats a better construction? – Daniel Kobe Aug 04 '15 at 15:37
  • Also, where do you think you have created a closure? – jfriend00 Aug 04 '15 at 15:37
  • Isnt a function expression a closure? – Daniel Kobe Aug 04 '15 at 15:40
  • @DanielKobe Nope. A closure is when a function "closes over" another variable in a parent scope. [See this question](http://stackoverflow.com/questions/111102/how-do-javascript-closures-work) for more details. – Mike Cluck Aug 04 '15 at 15:44
  • I've added an answer which explains the questions you asked me in comments. – jfriend00 Aug 04 '15 at 15:45

4 Answers4

2

Chances are that your code does not work because the value of this is not what you expect it to be so thus this.startDate does not change the variable startDate you have in your code and thus that variable was never initialized.

You are misusing this in that reference so that is the place to start in fixing your code. In fact, if you ran your code in strict mode, your code would generate an error because this would be undefined. strict mode is designed explicitly to prevent poor coding practices such as accidentally using this the wrong way.

Why is this.startDate a poor construction, what's a better construction?

this is used to refer to an object inside a method call as in obj.method(). Inside of method, this will refer to obj or this can be used in a few other circumstances when the caller of a function explicitly causes the value of this to be set to a meaningful value. In a normal function call, this will either be the global object or in strict mode will be undefined and should generally not be used. See this answer for a listing of exactly what situations the value of this is set to something unique.

Inside a normal function call where this is not explicitly set for you by the caller, you should not be using this at all. In fact, if you run your code in strict mode (which is highly recommended), the value of this will be undefined in your init function.

If you're just trying to set the higher level scoped variable named startDate to the value of whatever was passed to init, then you should change your argument name to the init function to a non-conflicting name and then just refer directly to the startDate variable like this:

var startDate;

var init = function(initialDate) {
    startDate = initialDate;
    logStartDate();
};

var logStartDate = function() {
    console.log(startDate);
};

init('2015-01-02');

Isn't a function expression a closure?

A closure is only created under certain circumstances when some sort of internal reference inside a function is lasting which keeps the scope of the function alive after it finishes executing. All function expressions are not closures. You do not have a closure in this code. See How do JavaScript closures work? for much more discussion of closures.

Community
  • 1
  • 1
jfriend00
  • 580,699
  • 78
  • 809
  • 825
0

Because inside init you're setting the value of this.Startdate (a private member var of init).

You need to modify to use window scope:

var startDate;

var init = function(date) {
    startDate = date;
    logStartDate();
};

var logStartDate = function() {
    console.log(startDate);
};

init('2015-01-02');
BenM
  • 49,881
  • 23
  • 107
  • 158
  • True but in why does his code not work in non-strict mode? Shouldn't `var startDate` generate a member on `window`? Then the function is called with the `window` context so shouldn't this technically work? – Mike Cluck Aug 04 '15 at 15:36
  • Because Im using Node.js – Daniel Kobe Aug 04 '15 at 15:38
  • @DanielKobe Then replace `window` with the general global object. The point is, if you're placing a variable in the global scope, call a function using the global scope, then you should be able to access it's properties (i.e. any declared variables) using `this`. That being said, I wouldn't suggest writing code like that but it's an interesting problem. – Mike Cluck Aug 04 '15 at 15:40
  • I should point out that this code works as OP expects if run in Chrome Dev Tools but fails when run in the browser. [fiddle showing example](http://jsfiddle.net/h3moq1rh/) – Mike Cluck Aug 04 '15 at 15:43
0

Because startDate2 equals to startDate1, not to other startDate.

var startDate;   // 1

var init = function(startDate) {  // startDate here is '2015-01-02'
  this.startDate = startDate;     // not equal to startDate line 1
  logStartDate();
};

var logStartDate = function() {
  console.log(startDate);         // 2, equal to startDate line 1
};

init('2015-01-02');

use this one instead:

var startDate;

var init = function(date) {
  startDate = date;
  logStartDate();
};

var logStartDate = function() {
  console.log(startDate);
};

init('2015-01-02');
iplus26
  • 2,186
  • 12
  • 25
0

The problem you have here is that logStartDate is trying to console.log the first startDate variable you defined but did not assign a value to, hence it is returning as 'undefined'. The poor choice of variable name has also contributed partly to this confusion.

var startDate;                //you defined a new variable startDate
var init = function(date) {   //you defined init, and passed a parameter called date (renamed for clarity)
    this.startDate = date;    //you set this.startDate to the date parameter
    logStartDate();           //you call logStartDate() but have not passed this.startDate as an argument, 
};
var logStartDate = function() {
    console.log(startDate);     // you are console logging the original startDate variable defined at the top of the code block, which did not get assigned a value
};
init('2015-01-02');

A better implementation would be something like this

var init = function(date) {
    logStartDate(date);
};

var logStartDate = function(date) {
    console.log(date);
};

init('2015-01-02');
Huan Zhang
  • 1,075
  • 8
  • 13
  • There is no point creating a global variable startDate when all you need the init function to do is to console.log whatever string you have as the argument when invoking it. – Huan Zhang Aug 04 '15 at 16:00