Попробуйте сначала запустить mvn -DskipTests clean package
, чтобы построить Spark.
Во-первых, вы правы, что в обеих версиях используются замыкания.
Первая версия чище (на мой взгляд) и более популярна в современном javascript. Главный потенциальный недостаток первого стиля заключается в том, что вы не можете эффективно назначать объекты прототипу конструктора, что полезно (и более эффективно), если вы создаете много одинаковых объектов.
Второй стиль, я на самом деле никогда не видел в производстве Javascript. Обычно вы создаете экземпляр create
с помощью new
вместо того, чтобы возвращать this
в функции create ()
, например:
function create() {
var counter = 0;
this.increment = function() {
counter++;
}
this.print = function() {
console.log(counter);
}
}
var c = new create();
c.increment();
c.print(); // 1
Объявив счетчик переменных с помощью ключевое слово var, оно уже локально в рамках функции / класса определение. Насколько я знаю и могу скажите, это недоступно из снаружи для начала. Я скучаю что-то из видимости данных
Дело не в том, что переменная счетчика
изначально недоступна извне функции, а в том, что она доступна для приращения
и print
] после выхода из функции create
, что делает замыкания столь полезными.
Ну, я не хочу ввязываться в религиозную войну из-за того, как создавать объекты в JavaScript, поскольку некоторые люди твердо убеждены, что есть правильный и неправильный способ сделать это.
Тем не менее, я хочу указать на то, что во втором наборе кода не слишком привлекательно, а именно на тот факт, что вы назначаете новые свойства объектам, содержащимся в ключевом слове this
. понять, что это за объект? Это не пустой объект, если вы не используете такой синтаксис создания экземпляров:
var c = new create();
Когда вы это сделаете, ключевому слову this
внутри тела функции-конструктора назначается совершенно новый объект, как если бы первый в теле строки были примерно такие:
this = {};
Но когда вы вызываете create ()
как функцию, как в этом примере,
Вы должны сравнить пример с этим фрагментом
function create() {
this.counter = 0;
this.increment = function() {
this.counter++;
};
this.print = function() {
console.log(counter);
}
}
var c = new create();
c.increment();
c.print(); // 1
Итак, когда вызывается new create (), он инициализирует новый объект двумя методами и одной переменной экземпляра (а именно: счетчик). Javascript не имеет инкапсуляции как таковой, поэтому вы можете получить доступ к c.counter, как показано ниже:
var c = new create();
c.increment();
c.counter = 0;
c.print(); // 0
При использовании замыканий (как показано в ваших примерах) счетчик теперь больше не является полем экземпляра, а скорее локальной переменной. С одной стороны, вы не можете получить доступ извне к функции create (). С другой стороны, increment () и print () могут получить доступ, потому что они закрываются за охватывающую область. Таким образом, мы получаем довольно хорошую эмуляцию объектной инкапсуляции.
Ваш второй пример по-прежнему использует замыкания, потому что функции инкремента и печати по-прежнему действуют на переменную, в противном случае они выходят за рамки - к тому времени, когда вы вызываете c.increment ()
, функция create уже завершилась.
I как и в первом примере, потому что он избегает "
У Кристиана Хейльмана есть довольно приличная статья о модульном шаблоне , который вы описываете, которая может помочь вам разобраться в этом и почему он полезен.
Во втором примере, когда вы вызываете create ()
в рамках функции, this
является глобальный объект (что всегда имеет место, когда вы вызываете «голую» функцию, не используя ее в качестве конструктора или не обращаясь к ней как к свойству (например, вызов «метода»)). В браузерах глобальным объектом является окно
. Поэтому, когда вы вызываете create последующие разы, он создает новые замыкания, но затем вы назначаете их тому же глобальному объекту, что и раньше, перезаписывая старые функции, что вам не нужно:
var c = create(); // c === window
c.increment();
c.print(); // 1
var c2 = create(); // c2 === c === window
c.print(); // 0
c2.print(); // 0
increment(); // called on the global object
c.print(); // 1
c2.print(); // 1
Решения, как указывали другие,
Этот синтаксис делает больше смысл для меня исходит из фона ООП:
Create = function {
// Constructor info.
// Instance variables
this.count = 10;
}
Create.prototype = {
// Class Methods
sayHello : function() {
return "Hello!";
},
incrementAndPrint : function() {
this.count++;
// Inner method call.
this.print();
},
print : function() {
return this.count;
}
}
var c = new Create();
alert(c.incrementAndPrint());