Модераторы: Sardar, Aliance
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Связь параметров и объекта arguments, почему-то рвётся при выходе из функции 
:(
    Опции темы
Се ля ви
Дата 22.1.2009, 16:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Java/SOAрхитектор
****


Профиль
Группа: Модератор
Сообщений: 2016
Регистрация: 5.6.2004
Где: place without tim e and space

Репутация: 5
Всего: 127



Вообще, задача передо мной стоит такая - нужно добиться перечислимости переменных внешней функции из её под-функции без необходимости называть их по именам.

Если бы у нас была ссылка на т.н. "call object", то мы могли бы просто перечислить его свойства через for-in, но в ECMA-262 он заявлен как неявный объект и ссылку на него получить не получится.

Я хотел действовать через объект arguments и перечислять его как массив, по индексам, присваивая его элементам нужные значения - тогда и соответствующие параметрам переменные тоже меняли бы значения, поскольку между параметрами и arguments существует синонимичная связь. Но оказалось, что эта связь рвётся при выходе из функции во всех браузерах, кроме Google Chrome:

Код
function a(x) {

    var args = arguments; //Присваиваем переменной, что бы не потерять ссылку на тот объект arguments, который нам нужен
    
    alert('args[0] = 5 = ' + (
        args[0] = 5
    ));
    alert('x = ' + x);
    
    var setX = function(newX) {
    
        alert('args[0] = ' + newX + ' = ' + (
            args[0] = newX
        ));
        
        alert('x = ' + x);
    }
    
    setX(15);
    
    return setX;
}
var a1 = a(10); //'args[0] = 5 = 5', 'x = 5', 'args[0] = 15 = 15', 'x = 15' - т.е. всё работает как надо, пока всё это выполняется внутри функции, но:
a1(20); // Выводит ''args[0] = 20 = 20', а потом (в IE, FF, Opera и Safari) - 'x = 15'! И только Chrome в конце пишет 'x = 20'.


Т.е. связь, которая работает при первом вызове setX - внутри ещё выполняющейся функции 'a' - работает нормально. Но стоит нам функцию завершить, как она рвётся и переменная x после этого существует отдельно от args[0] и смена одного уже не приводит к автоматической смене другого.

Собственно, я не нашёл явного упоминания о том, как это должно работать, в ECMA-262, но угадайте, почему поведение Chrom`а мне нравится больше ;)))

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


--------------------
  )
 (
[_])
проф. блог

Кролики думали, что занимаются любовью, а на самом деле их просто разводили...
PM MAIL WWW Skype GTalk   Вверх
Zeroglif
Дата 22.1.2009, 17:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 644
Регистрация: 22.9.2005

Репутация: 28
Всего: 66



Цитата(Се ля ви @  22.1.2009,  16:26 Найти цитируемый пост)
не нашёл явного упоминания о том, как это должно работать, в ECMA-262

10.1.8 Arguments Object
<...>
In the case when arg is less than the number of formal parameters for the Function object, this property shares its value with the corresponding property of the activation object. This means that changing this property changes the corresponding property of the activation object and vice versa.
<...>

Цитата(Се ля ви @  22.1.2009,  16:26 Найти цитируемый пост)
И как же мне теперь перечислимости переменных внешней функции добиваться? 

Ну, так 'х' есть, можно работать. Или, наоборот, args[0] есть... зачем имя дополнительное?

PM MAIL WWW   Вверх
Се ля ви
Дата 22.1.2009, 18:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Java/SOAрхитектор
****


Профиль
Группа: Модератор
Сообщений: 2016
Регистрация: 5.6.2004
Где: place without tim e and space

Репутация: 5
Всего: 127



Цитата(Zeroglif @  22.1.2009,  17:24 Найти цитируемый пост)
10.1.8 Arguments Object
<...>
In the case when arg is less than the number of formal parameters for the Function object, this property shares its value with the corresponding property of the activation object. This means that changing this property changes the corresponding property of the activation object and vice versa.
<...>

Да, но где сказано, что эта связь должна или не должна рваться при выходе из функции - что я и продемонстрировал.


Цитата(Zeroglif @  22.1.2009,  17:24 Найти цитируемый пост)
Цитата(Се ля ви @  22.1.2009,  16:26 Найти цитируемый пост)
И как же мне теперь перечислимости переменных внешней функции добиваться? 

Ну, так 'х' есть, можно работать. Или, наоборот, args[0] есть... зачем имя дополнительное?

Мне нужно именно copy/pase решение, что бы пользователь мог вставить мой блок кода в любую функцию и она приобретала специфический функционал. А как разработчик назовёт свои переменные, я не могу заранее знать. Мне нужно решение в общем виде.

Я просто пытаюсь совместить инкапсуляцию на основе замыканий и принципы prototype-based OOP. Я расписывал это в двух статейках - тут и тут.


--------------------
  )
 (
[_])
проф. блог

Кролики думали, что занимаются любовью, а на самом деле их просто разводили...
PM MAIL WWW Skype GTalk   Вверх
Zeroglif
Дата 22.1.2009, 20:50 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 644
Регистрация: 22.9.2005

Репутация: 28
Всего: 66



Цитата(Се ля ви @  22.1.2009,  18:30 Найти цитируемый пост)
Да, но где сказано

К моменту вызова внутренней функции контекст исполнения внешней функции жив? Нет. Фишка с алиасами имеет отношение к контексту, описывается в этом разделе (10 Execution Contexts), если контекста уже нет, и объект активации уже и не объект активации (терминологически), а безыдейная часть scope chain ;) , то магию алиасов можно убрать.
PM MAIL WWW   Вверх
IDVsbruck
Дата 22.1.2009, 22:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 778
Регистрация: 12.11.2006

Репутация: 8
Всего: 22



А если применить вариант с сохраненным состоянием?
Код
function a(x) {
    var args = arguments;
    alert('args[0] = 5 = ' + (args[0] = 5));
    alert('x = ' + x);
    var setX = function(newX) {
        if (!arguments.callee.ownerParameter) arguments.callee.ownerParameter = args;
        alert('args[0] = ' + newX + ' = ' + (args[0] = newX));
        alert('x = ' + arguments.callee.ownerParameter[0]);
    }
    setX(15);
    return setX;
}

var a1 = a(10); - тут все так и осталось.
А при вызове a1(20); не знаю, как в Хроме, но в ИЕ выдается 'args[0] = 20 = 20' и 'x = 20'.
PM MAIL   Вверх
Се ля ви
Дата 23.1.2009, 00:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Java/SOAрхитектор
****


Профиль
Группа: Модератор
Сообщений: 2016
Регистрация: 5.6.2004
Где: place without tim e and space

Репутация: 5
Всего: 127



Цитата(Zeroglif @  22.1.2009,  20:50 Найти цитируемый пост)
К моменту вызова внутренней функции контекст исполнения внешней функции жив? Нет. Фишка с алиасами имеет отношение к контексту, описывается в этом разделе (10 Execution Contexts), если контекста уже нет, и объект активации уже и не объект активации (терминологически), а безыдейная часть scope chain ;) , то магию алиасов можно убрать.

Чё-то как-то непоследовательно получается. Вся фишка closures как раз и состояла в том, что бы при выходе из контекста можно было безпроблемно обращаться к этому контексту. Так значит, всё и должно работать так, как будто мы в контексте. Другое дело, что надо было это специально в стандарте прописать, а то так и получается, что можно понимать и так и эдак... Грустно. Не знаешь, разработчики JS 2.0 на этот момент не обратили внимания? Может, им написать?

Похоже, единственный выход - использовать with... :((( Несмотря на все его минусы.

IDVsbruck, мне нужно добиться изменения внутренних переменных функции из её под-функции, но сделать это так, что бы от изменения имён и количества этих самых переменных функции алгоритм менять не надо было бы. Это можно сделать с использованием "магии алиасов", но она отключается при завершении работы функции - вот в чём проблема. А зачем мне эти извраты с ownerParameter? Да я могу просто так написать:
Код
function a(x) {
    var args = arguments;
    alert('args[0] = 5 = ' + (args[0] = 5));
    alert('x = ' + x);
    var setX = function(newX) {
        alert('args[0] = ' + newX + ' = ' + (args[0] = newX));
        alert('x = ' + args[0]);
    }
    setX(15);
    return setX;
}
var a1 = a(10);
a1(20);


и в конце он мне выведет желанные "x = 20", при чём любые браузеры, поддерживающие ECMAScript. Но задача-то у меня не та, что бы он мне вывел этот алерт, а что бы действительно переменная x поменялась от того, что я поменял args[0]! Если я заменю вывод x на что-то другое - я не решу нужной мне задачи. Так я могу и тупо текстом прописать, что бы он мне вывел то, что мне надо. smile


--------------------
  )
 (
[_])
проф. блог

Кролики думали, что занимаются любовью, а на самом деле их просто разводили...
PM MAIL WWW Skype GTalk   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Форум для вопросов, которые имеются в справочниках, но их поиск вызвал затруднения, или для разработчика требуется совет или просьба отыскать ошибку. Напоминаем: 1) чётко формулируйте вопрос, 2) приведите пример того, что уже сделано, 3) укажите явно, нужен работающий пример или подсказка о том, где найти информацию.
 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | JavaScript: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.1234 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.