Как вызвать общедоступную функцию из частной функции в шаблоне модуля JavaScript?
Например, в следующем коде
var myModule = (function() {
var private1 = function(){
// How to call public1() here?
// this.public1() won't work
}
return {
public1: function(){ /* do something */}
}
})();
Этот вопрос был задан дважды раньше, с разными принятыми ответами для каждого.
- Сохраните ссылку на возвращаемый объект перед его возвратом, а затем используйте эту ссылку для доступа к общедоступному методу. См. ответ.
- Сохраните ссылку на общедоступный метод в замыкании и используйте ее для доступа к общедоступному методу. См. ответ.
Хотя эти решения работают, они неудовлетворительны с точки зрения ООП. Чтобы проиллюстрировать, что я имею в виду, давайте возьмем конкретную реализацию снеговика с каждым из этих решений и сравним их с литералом простого объекта.
Снеговик 1: Сохранить ссылку, чтобы вернуть объект
var snowman1 = (function(){
var _sayHello = function(){
console.log("Hello, my name is " + public.name());
};
var public = {
name: function(){ return "Olaf"},
greet: function(){
_sayHello();
}
};
return public;
})()
Snowman 2: Сохранить ссылку на общедоступную функцию
var snowman2 = (function(){
var _sayHello = function(){
console.log("Hello, my name is " + name());
};
var name = function(){ return "Olaf"};
var public = {
name: name,
greet: function(){
_sayHello();
}
};
return public;
})()
Снеговик 3: литерал объекта
var snowman3 = {
name: function(){ return "Olaf"},
greet: function(){
console.log("Hello, my name is " + this.name());
}
}
Мы видим, что все три идентичны по функциональности и имеют одни и те же общедоступные методы.
Однако если мы запустим тест простого переопределения
var snowman = // snowman1, snowman2, or snowman3
snowman.name = function(){ return "Frosty";}
snowman.greet(); // Expecting "Hello, my name is Frosty"
// but snowman2 says "Hello, my name is Olaf"
мы видим, что № 2 терпит неудачу.
Если мы запустим тест переопределения прототипа,
var snowman = {};
snowman.__proto__ = // snowman1, snowman2, or snowman3
snowman.name = function(){ return "Frosty";}
snowman.greet(); // Expecting "Hello, my name is Frosty"
// but #1 and #2 both reply "Hello, my name is Olaf"
мы видим, что и № 1, и № 2 терпят неудачу.
Это действительно некрасивая ситуация. Просто потому, что я так или иначе рефакторил свой код, пользователь возвращенного объекта должен внимательно посмотреть, как я все реализовал, чтобы выяснить, может ли он / она переопределить методы моего объекта и ожидать, что это сработает. ! Хотя здесь мнения расходятся, мое собственное мнение состоит в том, что правильное поведение переопределения — это поведение простого литерала объекта.
Итак, это реальный вопрос:
Есть ли способ вызвать общедоступный метод из закрытого, чтобы результирующий объект действовал как литерал объекта в отношении поведения переопределения?
this
. Я хочу сказать, что если вы используете паттерн модуля, я думаю, что странность взаимодействия между модулем и прототипом не является реальной причиной не использовать подход. Это может быть причиной того, чтобы вообще придерживаться прототипов, если вы думаете, что кто-то, кто использует ваш код, сделает это. - person EyasSH   schedule 21.12.2014()
в концеsnowman1
,snowman2
иsnowman3
, иначе они будут функциями. И, вероятно, в переопределении прототипа вы должны настроитьsnowman.name
, иначе я не вижу, как он должен выводить Frosty. - person Oriol   schedule 21.12.2014