Закрытия в перекомпилированном JavaScript

Скажем, у нас есть этот код (забудьте о прототипах на мгновение):

function A(){
  var foo = 1;
  this.method = function(){
    return foo;
  }
}
var a = new A();

внутренняя функция перекомпилирована каждый раз, когда функция A выполняется? Или это лучше (и почему), чтобы сделать это как это:

function method = function(){ return this.foo; }
function A(){
  this.foo = 1;
  this.method = method;
}
var a = new A();

Или действительно ли механизмы JavaScript достаточно умны для не создания новой функции 'метода' каждый раз? Google v8 Specifically и node.js.

Кроме того, любые общие рекомендации на том, когда использовать, какая техника приветствуется. В моем определенном примере это действительно подходит мне для использования первого примера, но я знаю thath, внешняя функция будут много раз инстанцировать.

16
задан disc0dancer 10 May 2010 в 20:49
поделиться

6 ответов

Насколько я понимаю, дело не столько в "компиляции" функции, сколько в том, что при каждом выполнении она имеет другую "область видимости".

Второй метод, который вы использовали, всегда будет иметь method из той же области видимости.

Первый метод помещает method внутрь области видимости вызова функции A(). Поэтому любая информация, находящаяся внутри этой области видимости (var foo, параметры функции и т.д.), хранится в этом экземпляре области видимости функции. Таким образом, каждый раз будет ссылаться один и тот же код функции, но он будет находиться в другой области видимости (и, следовательно, в другом "объекте").

7
ответ дан 30 November 2019 в 23:05
поделиться

Да, вы создаете новый Функциональный объект при каждой реализации объекта A.Вы можете продемонстрировать это следующим образом:

function A(){
  var foo = 1;
  this.method = function(){
    return foo;
  }
}
var a = new A();
var b = new A();
alert(a.method == b.method); // Returns false; two different Function objects

Если вы хотите повторно использовать один и тот же объект Function, сделайте метод свойством прототипа, а не экземпляров.

function B() {
  this.foo = 1;
}

B.prototype.method = function() {
  return this.foo;
}

var a = new B();
var b = new B();
alert(a.method == b.method); // Returns true; it's the same Function object

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

В моем коде я использую соглашение об именах, чтобы различать «общедоступные» и «частные» свойства. Я называю частные свойства первым символом подчеркивания. Поэтому, если я вижу что-то вроде myObject._someMethod () , я знаю, что что-то не так.


Edit2: из http://code.google.com/apis/v8/design.html , я бы подумал, что V8 компилирует закрытие один раз, когда создает скрытый класс, содержащий свойство метода .

3
ответ дан 30 November 2019 в 23:05
поделиться

Я бы предположил, что она компилируется только один раз... потому что ключевое слово "this" относится к контексту выполнения... поэтому компилятору не нужно много знать о функции, чтобы интерпретировать ее.

Более того, когда вы объявляете переменную в нижней части функции, она все еще доступна в верхней части:

function test()
{
  alert(hello);
  // ...
  var hello = 2;
}

То же самое с функциями. Я полагаю, что с учетом этих двух вещей, она не перекомпилируется каждый раз, когда вызывается A.

Mike

0
ответ дан 30 November 2019 в 23:05
поделиться

Представьте себе функцию как еще один объект, а затем, когда вы создаете новый, это просто копия старого, с измененной переменной данных. Вам не нужно повторно анализировать источник объекта, чтобы это произошло. Хорошая аналогия - это функциональные элементы в C ++, функциональные объекты в Lua, и я действительно не знаю многих других языков.

0
ответ дан 30 November 2019 в 23:05
поделиться
function A(){
  var foo = 1;
  this.method = function(){
    return foo;
  }
}

не может быть скомпилирован в

function method = function(){ return this.foo; }
function A(){
  this.foo = 1;
  this.method = method;
}

потому что функциональность изменится. В первом примере переменная 'foo' видна только конструктору 'A' и функции 'method', тогда как во втором примере она доступна всему, что имеет доступ к экземпляру 'A'.

Можно скомпилировать его в

function method = function(){ return 1; }
function A(){ 
  this.method = method;
}

Но я не думаю, что какой-либо движок javascript зайдет так далеко, но если вы умеете препроцессировать свои файлы и готовы приложить дополнительные усилия, компилятор закрытия google может зайти довольно далеко, если использовать его в расширенном режиме.

0
ответ дан 30 November 2019 в 23:05
поделиться

Метод не перекомпилирован.

Интерпретатор Javascript создаст новый закрывающий объект, содержащий внутренние методы и локальные переменные каждый раз, когда вы вызываете внешние методы.

Точная реализация зависит от механизма Javascript.

2
ответ дан 30 November 2019 в 23:05
поделиться
Другие вопросы по тегам:

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