0

I was just playing with Date object and I observed this

  1. new Date() // returns Date object
  2. Date() // returns Date in string format

MDN - Date documentation confirms this

Note: Note that JavaScript Date objects can only be instantiated by calling JavaScript Date as a constructor: calling it as a regular function (i.e. without the new operator) will return a string rather than a Date object; unlike other JavaScript object types, JavaScript Date objects have no literal syntax.

Tricky part is new Date returns the same result which new Date() returned ?

I tried the same experiment with a normal function,

function f() {
  console.log(' I am executed');
}

new f

I am surprised to see I am executed gets logged. I am trying to find out the reason why f is called when I did not use execution () operator. Can somebody explain me why new called the method ?

PS: I don't know what new f should have given to me. It was a syntax mistake So I thought it would give me an error. But It does not.

Sachin Jain
  • 21,353
  • 33
  • 103
  • 168
  • m59 is right, in javascript function is just another kind of object. – Frank Conry Dec 24 '13 at 18:39
  • 2
    Parentheses are optional when you use the `new` operator; it's as simple as that. – Pointy Dec 24 '13 at 18:50
  • @Pointy Thanks for clarification. Atleast via this I got to learn something about new :) – Sachin Jain Dec 24 '13 at 18:52
  • 1
    @Pointy would it be reasonable to say that they are optional because you *have* to call the constructor for `new` to work anyway? If not `new f` wouldn't do anything at all because `Function`, wouldn't be invoked and so no "new" function object would be created. Correct? – m59 Dec 24 '13 at 18:52
  • 2
    @m59 yes, that's right. It doesn't make sense to use `new` if you're *not* calling a function, in other words. I guess one should read a `new` expression as, "I want to construct an object, and here's an expression that evaluates to a reference to the function I want you to call as the constructor." So calling the function is implicit. The slightly weird part is that if you want to call a function to provide the constructor, you have to parenthesize that. – Pointy Dec 24 '13 at 19:00

3 Answers3

5

Because new will call the constructor of the object you are creating. In the case of a function, the function is both the object and the constructor for that object.

m59
  • 43,214
  • 14
  • 119
  • 136
  • In case of `new f()` it should call the constructor of what `f()` returns. Isn't it? But even then it calls constructor of f only. – Sachin Jain Dec 24 '13 at 18:40
  • @blunderboy using `new` automatically invokes the constructor. JavaScript objects are different than what you might be used to. You're probably looking for `Object.create()`. Note that there are also no classes in JavaScript. – m59 Dec 24 '13 at 18:44
  • This is just the syntax of JavaScript. It's a bit weird if you come from a C#, Java or C++ background. – Mike Christensen Dec 24 '13 at 18:45
2

I think this part of ECMAScript Spec should explain the operation of the new operator. In your case, that's 5 in the first section, and 6 on the second section. Basically, JS will call the constructor like a function.

The new Operator

The production NewExpression : new NewExpression is evaluated as follows:

  1. Let ref be the result of evaluating NewExpression.
  2. Let constructor be GetValue(ref).
  3. If Type(constructor) is not Object, throw a TypeError exception.
  4. If constructor does not implement the [[Construct]] internal method, throw a TypeError exception.
  5. Return the result of calling the [[Construct]] internal method on constructor, providing no arguments (that is, an empty list of arguments).

The production MemberExpression : new MemberExpression Arguments is evaluated as follows:

  1. Let ref be the result of evaluating MemberExpression.
  2. Let constructor be GetValue(ref).
  3. Let argList be the result of evaluating Arguments, producing an internal list of argument values (11.2.4).
  4. If Type(constructor) is not Object, throw a TypeError exception.
  5. If constructor does not implement the [[Construct]] internal method, throw a TypeError exception.
  6. Return the result of calling the [[Construct]] internal method on constructor, providing the list argList as the argument values.
Joseph
  • 117,725
  • 30
  • 181
  • 234
2

This is a case of a "stupid-proof" code.
As you may know, the new keyword in javascript can be dangerous: for example, say you have a classic Point constructor:

function Point(x, y) {
    this.x = x;
    this.y = y;
}

This works as expected if you create a point by instantiating the constructor with the new keyword. But what if someone forgets to use it? What is the result of the following code?

var myPoint = Point(0, 0); 

Well, since the constructor itself doesn't return anything (doesn't even have a return statement), myPoint will be undefined instead of a Point instance. And all because of a forgotten new keyword.
But have no fear! You can write your code to be stupid-proof:

function Point(x, y) {
    // `this` points to the outer scope 
    // if the function is called witouth `new`
    if(!(this instanceof Point))
        return new Point(x, y);

    this.x = x;
    this.y = y;
}

Although functions such as Date, Array and so on are built in and we can actually see their source, I strongly believe that they have this safety mechanism by default to prevent newcomers from making trivial stupid errors.

Community
  • 1
  • 1
gion_13
  • 41,171
  • 10
  • 96
  • 108