Зачем мне нужно "новое" ключевое слово для экземпляра `Date` в JavaScript?

Я понимаю разницу в поведении. Date() возвращает строку, представляющую текущую дату, и new Date() возвращает экземпляр объекта Date, методы которого я могу вызвать.

Но я не знаю, почему. JavaScript прототипирован, поэтому Date - это функция и объект, который имеет функции-члены (методы), которые также являются объектами. Но я не написал или не прочитал какой-либо JavaScript, который ведет себя таким образом, и я хотел бы понять разницу.

Может кто-нибудь показать мне пример кода функции, которая имеет метод, возвращает экземпляр с новым оператором и выводит строку при вызове напрямую? например, как это происходит?

Date();                   // returns "Fri Aug 27 2010 12:45:39 GMT-0700 (PDT)"
new Date();               // returns Object
new Date().getFullYear(); // returns 2010
Date().getFullYear();     // throws exception!

Очень конкретный запрос, я знаю. Надеюсь, что это хорошо.:)

Ответ 1

Большинство из них можно сделать сами. Вызов голого конструктора без new и получение строки является специальным для Date по спецификации ECMA, но вы можете имитировать что-то подобное для этого.

Вот как вы это сделаете. Сначала объявите объект в шаблоне конструктора (например, функцию, которая предназначена для вызова с new и которая возвращает ссылку this:

var Thing = function() {
    // Check whether the scope is global (browser). If not, we're probably (?) being
    // called with "new". This is fragile, as we could be forcibly invoked with a 
    // scope that neither via call/apply. "Date" object is special per ECMA script,
    // and this "dual" behavior is nonstandard now in JS. 
    if (this === window) { 
        return "Thing string";
    }

    // Add an instance method.
    this.instanceMethod = function() {
        alert("instance method called");
    }

    return this;
};

Новые экземпляры Thing могут иметь instanceMethod() для вызова. Теперь просто добавьте "статическую" функцию в Thing:

Thing.staticMethod = function() {
    alert("static method called");
};

Теперь вы можете сделать это:

var t = new Thing(); 
t.instanceMethod();
// or...
new Thing().instanceMethod();
// and also this other one..
Thing.staticMethod();
// or just call it plain for the string:   
Thing();