Закрытие JavaScript и видимость данных

Попробуйте сначала запустить mvn -DskipTests clean package, чтобы построить Spark.

12
задан Goyuix 3 June 2009 в 21:25
поделиться

8 ответов

Во-первых, вы правы, что в обеих версиях используются замыкания.

Первая версия чище (на мой взгляд) и более популярна в современном 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
10
ответ дан 2 December 2019 в 07:03
поделиться

Объявив счетчик переменных с помощью ключевое слово var, оно уже локально в рамках функции / класса определение. Насколько я знаю и могу скажите, это недоступно из снаружи для начала. Я скучаю что-то из видимости данных

Дело не в том, что переменная счетчика изначально недоступна извне функции, а в том, что она доступна для приращения и print ] после выхода из функции create , что делает замыкания столь полезными.

4
ответ дан 2 December 2019 в 07:03
поделиться

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

Тем не менее, я хочу указать на то, что во втором наборе кода не слишком привлекательно, а именно на тот факт, что вы назначаете новые свойства объектам, содержащимся в ключевом слове this . понять, что это за объект? Это не пустой объект, если вы не используете такой синтаксис создания экземпляров:

var c = new create();

Когда вы это сделаете, ключевому слову this внутри тела функции-конструктора назначается совершенно новый объект, как если бы первый в теле строки были примерно такие:

this = {};

Но когда вы вызываете create () как функцию, как в этом примере,

2
ответ дан 2 December 2019 в 07:03
поделиться

Вы должны сравнить пример с этим фрагментом

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 () могут получить доступ, потому что они закрываются за охватывающую область. Таким образом, мы получаем довольно хорошую эмуляцию объектной инкапсуляции.

2
ответ дан 2 December 2019 в 07:03
поделиться

Ваш второй пример по-прежнему использует замыкания, потому что функции инкремента и печати по-прежнему действуют на переменную, в противном случае они выходят за рамки - к тому времени, когда вы вызываете c.increment () , функция create уже завершилась.

I как и в первом примере, потому что он избегает "

1
ответ дан 2 December 2019 в 07:03
поделиться

У Кристиана Хейльмана есть довольно приличная статья о модульном шаблоне , который вы описываете, которая может помочь вам разобраться в этом и почему он полезен.

1
ответ дан 2 December 2019 в 07:03
поделиться

Во втором примере, когда вы вызываете 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

Решения, как указывали другие,

0
ответ дан 2 December 2019 в 07:03
поделиться

Этот синтаксис делает больше смысл для меня исходит из фона ООП:

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());
1
ответ дан 2 December 2019 в 07:03
поделиться
Другие вопросы по тегам:

Похожие вопросы: