Ответ 1
В JavaScript, когда вы используете ключевое слово new
с функцией, функция ведет себя по-разному, когда вызывается без ключевого слова new
. С его помощью функция действует как класс, и из нее создается экземпляр нового объекта, как и в традиционных языках ООП. Кроме того, контекст this
устанавливается на себя, а возвращаемое значение функции игнорируется.
В отличие от этого ключевого слова new
контекст this
устанавливается в глобальную область, которая для браузеров - это объект window
, а возвращаемое значение может быть записано любым его именем.
Возможно создать что-то вроде вашего примера на С++, в котором вам не понадобится ключевое слово new
, и оно все равно возвращает новый объект.
function foo(value) {
function foo(value) {
this.value = value;
this.bar = function () {};
this.twice = function() { return this.value + this.value; }
}
return new foo(value);
}
console.log( foo(3.14).twice() ); // 6.28
Объяснение:
внешняя функция foo
ведет себя как нормальная функция и предназначена для вызова без ключевого слова new
. Внутри находится внутренний foo
, который должен быть похож на класс, называемый ключевым словом new
. Внешний foo
создает новый экземпляр внутреннего foo
и возвращает его. Таким образом, его можно использовать как пример С++. Нет необходимости объявлять класс-функцию во внешней функции, это просто зависит от того, хотите ли вы инкапсулировать ее во внешнюю.
Видимость
Два примера в вопросе не совсем эквивалентны, потому что пример JavaScript использует все общедоступные свойства и методы, тогда как пример С++ имеет bar
и value
как закрытый.
Ниже приведена версия, которая ближе к версии С++:
function foo(value) {
function foo(value) {
var value = value;
function bar(){}
this.twice = function() { return value + value; }
}
return new foo(value);
}
console.log( foo(3.14).twice() ); // 6.28
console.log( foo(3.14).value ); // undefined because it private
console.log( foo(3.14).bar() ); // undefined because it private
Как видно из тестовых примеров, value
и bar
не являются общедоступными/видимыми. Это достигается за счет использования префикса this
и объявления value
с использованием ключевого слова var
(который определяет локальную переменную). Функция объявляется как выражение вместо выражения. В JavaScript нет формального способа объявления/дифференциации общедоступных и частных свойств или методов, подобных языкам ООП.
Возможно, вы заметили, что приведенные выше примеры не используют прототип для объявления каких-либо методов. Причиной этого является то, что прототип всегда будет объявлять методы с общедоступной видимостью, а методы прототипа не могут видеть какие-либо переменные внутри "класса" или функции. Кодовые комментарии в вопросе предполагают, что использование this.bar
внутри тела функции делает его закрытым, но это не так.