21.09.2009, 14:06
|
|
Рассеянный профессор
|
|
Регистрация: 06.04.2009
Сообщений: 2,379
|
|
Сообщение от ZoNT
|
Если вопрос только в этом то надо было писать так:
|
замыкания опять же нет, вопрос был не в способе запомнить что-то в "new Function", а в том, что там в памяти, запомнен ли чей-то scope.
Последний раз редактировалось Riim, 21.09.2009 в 14:08.
|
|
21.09.2009, 14:11
|
|
Модератор Всея Форума
|
|
Регистрация: 14.05.2009
Сообщений: 4,021
|
|
Сообщение от Riim
|
вопрос не в способе запомнить в что-то в "new Function", а в том что там в памяти, запомнен ли чей-то scope
|
Я подразумеваю, что второе - результат работы первого...Только вот этот самый результат не нужен...
|
|
21.09.2009, 14:20
|
|
Рассеянный профессор
|
|
Регистрация: 06.04.2009
Сообщений: 2,379
|
|
B~Vladi, можно через prototype, можно просто создавать нормальную структуру объектов, так что бы до всего нужного можно было добраться через window.
|
|
21.09.2009, 14:55
|
|
Модератор Всея Форума
|
|
Регистрация: 14.05.2009
Сообщений: 4,021
|
|
Ладно, не буду вас доставать
|
|
21.09.2009, 15:45
|
Профессор
|
|
Регистрация: 25.02.2008
Сообщений: 707
|
|
Сообщение от Riim
|
замыкания опять же нет, вопрос был не в способе запомнить что-то в "new Function", а в том, что там в памяти, запомнен ли чей-то scope.
|
Сообщение от ZoNT
|
Функция через new Function ничего не запоминает
|
Вообще, каждая функция имеет [[Scope]], просто для функций, созданных с помощью конструктора Function, [[Scope]] содержит только глобальный объект.
А в виду того, что любая функция хранит [[Scope]] (т.е. Scope chain порождающего контекста), все функции являются замыканиями.
Последний раз редактировалось Dmitry A. Soshnikov, 21.09.2009 в 15:47.
|
|
21.09.2009, 17:11
|
|
Модератор Всея Форума
|
|
Регистрация: 14.05.2009
Сообщений: 4,021
|
|
Сообщение от Dmitry A. Soshnikov
|
А в виду того, что любая функция хранит [[Scope]] (т.е. Scope chain порождающего контекста), все функции являются замыканиями.
|
Аха... Тогда ещё такой вопрос:
Есть код:
function fnc1(){
var i;
function fnc2(){
alert(i)
}
}
А внешний [[scope]], который хранит функция fnc2 - это клон или ссылка на [[scope]] функции fnc1?! Т.е. меня интересует как при этом расходуется память...
|
|
21.09.2009, 17:23
|
Профессор
|
|
Регистрация: 25.02.2008
Сообщений: 707
|
|
Сообщение от B~Vladi
|
А внешний [[scope]], который хранит функция fnc2 - это клон или ссылка
|
Ссылка; там же, в статье о замыканиях можно подробно посмотреть.
Сообщение от B~Vladi
|
или ссылка на [[scope]] функции fnc1?!
|
Свойство [[Scope]] функции - это ссылка на Scope (Scope chain) порождающего (внешнего) контекста, а не на [[Scope]] внешней функции. Если бы была ссылка на [[Scope]] внешней функции, внутренняя функция не видела бы переменные, объявленные во внешней функции.
Т.е.
f1.[[Scope]] === Scope глобальньного контекста === [Global]
Scope (Scope chain) контекста функции f1 === Объект активации (AO) контекста функции f1 + f1.[[Scope]]:
Scope(f1 Context) == AO(f1 context) + f1.[[Scope]]
А f2.[[Scope]]:
f2.[[Scope]] === Scope(f1 Context) === [AO(f1 context), Global]
Последний раз редактировалось Dmitry A. Soshnikov, 21.09.2009 в 17:26.
|
|
21.09.2009, 17:42
|
|
Рассеянный профессор
|
|
Регистрация: 06.04.2009
Сообщений: 2,379
|
|
Dmitry A. Soshnikov, вот такой у меня вопрос: функция запомнила какие-то переменные, если внутри этой функции создать переменную, одноименную с той, что запомнена, то она как бы экранируется, теперь если экранируется все запомненное за счет имен аргументов, то хранится ли в памяти внешняя функция? Что-то у меня не получается создать пример подтверждающий или опровергающий это. Вот код для пояснения вопроса:
var p = (function() {// func1
var a = 5, b = 6;
return function(a, b) {// смысла, хранить в памяти func1, вроде нет, все равно все экранировано, и убрать это экранирование вроде никак (delete применяется к свойствам объектов, но a и b непонятно чьи свойства)
alert(a + b);
};
})();
Последний раз редактировалось Riim, 21.09.2009 в 17:47.
|
|
21.09.2009, 18:07
|
Профессор
|
|
Регистрация: 25.02.2008
Сообщений: 707
|
|
Сообщение от Riim
|
если внутри этой функции создать переменную, одноименную с той, что запомнена, то она как бы экранируется
|
Да, "экранируется", на этом принципе и работает Scope chain.
Т.е. одноимённые переменные (а также, декларации функций и формальные параметры) более глубокого контекста, разрешаются (определяются) раньше, чем переменные с тем же именем, но в контексте выше. Цепь областей видимости контекста (Scope chain) при нахождении в коде переменной, опрашивается интерпретатором от самого глубого звена цепи вверх до глобального объекта (и, в некоторых реализациях, прототипа глобального объекта).
var a = 10;
function A() {
var a = 20;
function B() {
var a = 30;
alert(a); // найдено сразу в AO(контекста B)
}
}
Если бы переменная "а" была объявлена один раз (глобально), то при alert(a) из внутренней функции "B", она бы разрешалась по цепи (Scope chain контекста функции "B"):
1. AO(контекста "B") - (нет) ->
2. AO(контекста "А") - (нет) ->
3. VO(Global) === Global - (да) - 10
Сообщение от Riim
|
теперь если экранируется все запомненное за счет имен аргументов, то хранится ли в памяти внешняя функция
|
Вообще, теоретически, функцию до создания можно распарсить и посмотреть, используются ли в ней свободные переменные, если нет, то, по идее, можно не создавать замыкание. Но в стандарте об этом ничего не сказано, это просто мысли.
С другой стороны, одна вложенная функция может не иметь свободных переменных, а вложенная во вложенную может, поэтому, надо запоминать всегда, получается:
function A() {
var a = 10;
function B() { // нужен ли этой функции Scope A?
function C() {
alert(a); // если B не запомнит Scope A, функция С не найдёт "а"
}
}
}
Но, повторю, по идее, может быть проведена оптимизация на уровне реализации.
Поэтому, все функцию при создании запоминаю лексический контекст (т.е. Scope chain этого контекста), в котором они порождены, отсюда - все функции - замыкания. Функция может быть ни разу не запущена, но [[Scope]] уже в неё записался.
Но, стандарт описывает предложение по оптимизации - объединённые объекты:
function a() {
function b(z) {
return z * z;
}
return b;
}
var x = a();
var y = a();
Т.к. [[Scope]] функций x и y - не различим (и вообще, оба объекты - не различимы), реализация вправе использовать объединённые объекты в этом случае, или даже - использовать один объект. Поэтому, не всегда внутренняя функция будет создаваться каждый раз разная.
Последний раз редактировалось Dmitry A. Soshnikov, 21.09.2009 в 18:21.
|
|
21.09.2009, 20:09
|
|
Рассеянный профессор
|
|
Регистрация: 06.04.2009
Сообщений: 2,379
|
|
Сообщение от Dmitry A. Soshnikov
|
С другой стороны, одна вложенная функция может не иметь свободных переменных, а вложенная во вложенную может, поэтому, надо запоминать всегда
|
совсем обрубать цепочку, конечно, не стоит, она в любом случае должна закончиться на VO(Global) === Global , я имел в виду аккуратно удалять незначащие звенья в этой цепи, вот здесь, например:
function A() {
var a = 10;
function B() { // нужен ли этой функции Scope A?
function C() {
alert(a); // если B не запомнит Scope A, функция С не найдёт "а"
}
}
}
можно не запоминать AO(контекста "B") и из "C" сразу в "A" ссылаться.
Правда я уже не уверен, что такая оптимизация пойдет на пользу, памяти конечно меньше надо будет, но при каждом создании функции столько дополнительной работы делать, с другой стороны там и так этой работы очень много делается.
|
|
|
|