Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why doesn’t adding a function to `Date` work like adding it to `Date.protoype` in JavaScript?

Tags:

javascript

The Original Question

I realized I am not 100% sure why this behaves the way it does, so I figured it would make a good SO question.

Observe:

Date.bar = function() { return 'called bar'; }
Date.prototype.foo = function() { return 'called foo'; }

Then in your console, note these two lines work:

Date.bar(); // 'called bar'
(new Date).foo() // 'called foo'

But these two blow up and complain about undefined not being a function:

Date.foo();
(new Date).bar();

In theory, shouldn't adding a method to Date's prototype make it available when called off Date? What is actually going on here?


What I got out of your answers and from playing around in the console

Basically, Date (that is, window.Date) is not a date object. It’s a function, and it wasn’t constructed from Date.prototype. (Also, date objects do not have the prototype property defined, though of course they still have a prototype chain.) Check it out:

typeof Date; // function
typeof (new Date); // object
Date.prototype.isPrototypeOf(new Date); // true
Date.prototype.isPrototypeOf(Date); // false
(new Date).prototype; // undefined

Realizing that Date is not a date object or the prototype for date objects makes this all make a lot more sense to me. Thanks, everyone.

Also, note that Date.prototype and Date.__proto__ are different! The former is used when Date is run as a function, when creating new date objects. The latter is related to the normal prototype chain (and is Date’s prototype).

like image 235
Alan H. Avatar asked Dec 28 '22 09:12

Alan H.


1 Answers

Adding foo to Date.prototype affects all objects created from invoking Date as a constructor. That's why foo is visible when you say (new Date()).foo() but not Date.foo()—the latter does not invoke Date as a constructor.

Remember, when you say new Date() you get an object that's based on Date's prototype. You added foo to the prototype, so you'll get foo on objects created from new Date()

Adding something directly to Date simply adds it to the Date function. That's why Date.bar() works, but not (new Date()).bar(). bar is not on the prototype, and therefore not visible to objects created from invoking Date as a constructor.

like image 136
Adam Rackis Avatar answered May 16 '23 16:05

Adam Rackis