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

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> function 
V
    Опции темы
Се ля ви
Дата 15.8.2008, 12:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


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


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

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



Продолжаю экспериментировать с тонкостями JS в свободное время.

На этот раз объектом исследования стало использование ключевого слова 'function'.

Т.к. в JS всё является объектом, неудивительно, что и функция сама по себе является специфическим видом объекта тоже и с этих позиций более правильно и наглядно было, что бы не путаться и называть вещи своими именами, всегда писать вместо

Код
function A(){
    //...Some operations
}

вот так:
Код
var A = new Function('<operations>');


Однако это не очень наглядно и на самом деле, как будет показано ниже, не является одним и тем же.


Специфика этого объекта довольно сильная. Так, например, операция typeof вообще не признает функцию объектом:
Код
alert(typeof function(){alert('!!')}) // Выведет 'function', а не 'Object'!


Тем не менее, это не примитив, ибо операция instanceof однозначно свидейтельствует, что это экземпляр, созданный конструктором Function:
Код

alert(function(){alert('!!')} instanceof Function) //Выводит 'true'!


Почему я поставил перед объявлением var? Проверим:
Код
function A(){
    function B(){alert('!');};
    B();
}
var a = new A; //выводит '!'
//a.B(); // Выводит ошибку 'a.B is not a function'
//A.B(); //Выводит ошибку 'A.B is not a function'
//B(); //Выводит ошибку 'B is not defined'

Т.е. внутренняя функция доступна только внутри closure, где расположена, как и переменные, объявленные с ключевым словом 'var'

Так в чём же отличие? В том, что во втором случае мы не задействуем closure:
Код
function A(){
    
    var x = 5;
    function B(){alert('x = ' + x);};
    B(); //Выводит 'x = 5'
    
    var C = new Function('alert(\'x = \' + x);');
    C(); //Выводит ошибку 'x is not defined'
}
var a = new A();


Так что в нашем распоряжении прекрасный метод борьбы с closure в случаях, когда оно нам не нужно. Правда, удобен для восприятия он только в случае небольших функций, ибо писать, а тем более сопровождать сложный код, разполагающийся внутри такой декларации представляется довольно затруднительным...


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

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


Опытный
**


Профиль
Группа: Участник
Сообщений: 565
Регистрация: 8.9.2007
Где: Saint-Petersburg

Репутация: 19
Всего: 26



Цитата(Се ля ви @  15.8.2008,  12:05 Найти цитируемый пост)
Так что в нашем распоряжении прекрасный метод борьбы с closure в случаях, когда оно нам не нужно


Да нет, тут дело в том, что функции, созданные через конструктор Function, работаю с глобальным скопом: "Pass in a scope chain consisting of the *global object as the Scope* parameter." - ECMAScript specification, 15.3.2.1.

Поэтому:

Код

function test() {
var a = 10;
var b = Function('alert(a);');
b(); // падает по эксепшену, "а" - не определена
}


Если же, приплюсовать значение переменной "а" к строке - var b = Function('alert(' + a + ');'); - то все нормально. Данное строковое тело функции парсится каждый раз (в отличии от function () {...}), поэтому этот метод (Function('param', 'parsableFunctionBody')) менее эффективен в скорости (да и работает с глобальным скопом).

Или же (т.к. Function(...) в качестве скопа имеет глобальный объект) - объявить var a = 10; - глобально:

Код

var a = 10;
function test() {
var b = Function('alert(a);');
b(); // все ок - 10
}


Цитата(Се ля ви @  15.8.2008,  12:05 Найти цитируемый пост)
//a.B(); // Выводит ошибку 'a.B is not a function'
//A.B(); //Выводит ошибку 'A.B is not a function'
//B(); //Выводит ошибку 'B is not defined'


Формальные параметры, var'ы и внутренние декларации функций - становятся свойствами variable object'a функции (VO) (10.1.3 - уже отмечалось не раз), а не самой функции. Т.е., если где и искать B, то в A.VO.B(); (утрированно, ествественно =)). 

Цитата(Се ля ви @  15.8.2008,  12:05 Найти цитируемый пост)
Т.е. внутренняя функция доступна только внутри closure, где расположена, как и переменные, объявленные с ключевым словом 'var'


Почему это только внутри? Ее же можно вернуть и она будет доступна снаружи.

Код

function a() {
  return function b() {
    alert(1); 
  };
}
var fn = a();
fn();


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

Код

(function a() {
  (function b() {alert(1);});
  b(); // b - undefined?
})();


Подсказка (вернее, можно считать ответом =)): все дело в различном воздействии function-declaration и function-expression на variable object функции.


Это сообщение отредактировал(а) dsCode - 15.8.2008, 16:43


--------------------
the .code inside
:my music
PM MAIL WWW ICQ Jabber   Вверх
Zeroglif
Дата 15.8.2008, 17:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Цитата(dsCode @  15.8.2008,  16:32 Найти цитируемый пост)
строковое тело функции парсится каждый раз (в отличии от function () {...}), поэтому этот метод (Function('param', 'parsableFunctionBody')) менее эффективен в скорости (да и работает с глобальным скопом).


Теоретически парсится также, как и любое выражение (каждый раз или не каждый... э... построчно, в общем), также как и, например, var x = function () {};...

Цитата(dsCode @  15.8.2008,  16:32 Найти цитируемый пост)
все дело в различном воздействии function-declaration и function-expression на variable object функции


IE-юзвери пример не поймут. ;) 

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


Опытный
**


Профиль
Группа: Участник
Сообщений: 565
Регистрация: 8.9.2007
Где: Saint-Petersburg

Репутация: 19
Всего: 26



Цитата(Zeroglif @  15.8.2008,  17:10 Найти цитируемый пост)
Теоретически парсится также, как и любое выражение (каждый раз или не каждый... э... построчно, в общем), также как и, например, var x = function () {};...


Хм... Ну да, тут, смотря с какой стороны смотреть (а как в спецификации написано? - я что-то упустил это) - понятно, что все интерпретируется построчно при вызове. Ну а все же - есть разница? С одной стороны - уже готовый к вызову callable-объект (функция), с другой - строка - которую нужно сначала превратить в этот объект, а потом уже начинать выполнять построчно. Или... Что? Как только парсится первая строчка (в большой строке кода), - она сразу выполняется?

Цитата(Zeroglif @  15.8.2008,  17:10 Найти цитируемый пост)
IE-юзвери пример не поймут. ;)


а IE вообще function-expression не различает в этом отношении (в плане скопа)? =) Или все-таки есть случаи, когда IE соответствует спецификации в этом месте? - я посмотрел - любой из видов function-expression доступен для вызова за пределами объявления.

Это сообщение отредактировал(а) dsCode - 16.8.2008, 00:10


--------------------
the .code inside
:my music
PM MAIL WWW ICQ Jabber   Вверх
Се ля ви
Дата 19.8.2008, 12:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


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


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

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



Цитата(dsCode @  15.8.2008,  16:32 Найти цитируемый пост)
Цитата(Се ля ви @  15.8.2008,  12:05 Найти цитируемый пост)
Так что в нашем распоряжении прекрасный метод борьбы с closure в случаях, когда оно нам не нужно

Да нет, тут дело в том, что функции, созданные через конструктор Function, работаю с глобальным скопом

Я это и имел в виду smile


Цитата(dsCode @  15.8.2008,  16:32 Найти цитируемый пост)
Если же, приплюсовать значение переменной "а" к строке - var b = Function('alert(' + a + ');'); - то все нормально. Данное строковое тело функции парсится каждый раз (в отличии от function () {...}), поэтому этот метод (Function('param', 'parsableFunctionBody')) менее эффективен в скорости (да и работает с глобальным скопом).

А вот это интересно...


Цитата(dsCode @  15.8.2008,  16:32 Найти цитируемый пост)
Или же (т.к. Function(...) в качестве скопа имеет глобальный объект) - объявить var a = 10; - глобально:

Ну тогда весь смысл теряется. Я же играюсь с инкапсуляцией smile


Цитата(dsCode @  15.8.2008,  16:32 Найти цитируемый пост)
Формальные параметры, var'ы и внутренние декларации функций - становятся свойствами variable object'a функции (VO) (10.1.3 - уже отмечалось не раз), а не самой функции. Т.е., если где и искать B, то в A.VO.B(); (утрированно, ествественно =)).

Ну да, то, что я называю private`ами. Об том и речь smile

Цитата(dsCode @  15.8.2008,  16:32 Найти цитируемый пост)
Почему это только внутри? Ее же можно вернуть и она будет доступна снаружи.

Так любой private-объект, если его вернуть, будет доступен снаружи - кто бы сомневался. Просто возможность его скрыть и не зацепить при этом в closure то, что не нужно, представляет особый интерес smile
Цитата(dsCode @  15.8.2008,  16:32 Найти цитируемый пост)
И более того, не все функции (вернее сказать, не все типы функций) доступны внутри функции. Се ля ви, как ты объяснишь это поведение?:
    
Код
(function a() {
  (function b() {alert(1);});
  b(); // b - undefined?
})();


Подсказка (вернее, можно считать ответом =)): все дело в различном воздействии function-declaration и function-expression на variable object функции.

Ух ты! А вот это действительно интересная штука... Надо будет с ней покопаться, как время найду. Спасибо! smile


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

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


Опытный
**


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

Репутация: нет
Всего: 4



Цитата(Се ля ви @  19.8.2008,  12:10 Найти цитируемый пост)
 играюсь с инкапсуляцией

проблема с private была решена в base2, если не ошибаюсь.
PM ICQ   Вверх
S.A.P.
Дата 24.8.2008, 22:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



На основе этих рассуждений появилась бредовая идея как бороться со столько ненавистными нам замыканиями:
Код

function newFunction (body)
{
    return new Function ('return ('+String(body)+').apply(this, arguments);');
}

var f1 = newFunction(function (a)
{
    return a*2;
});

alert(f1(4));


создаваемые функции не используют глобальный скоп и при этом не лезут в наше замыкание + лишены приведённого недостатка с написанием и сопровождением.

Но всё равно както жутковато  smile 
PM MAIL   Вверх
JSman
Дата 17.9.2008, 00:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

Репутация: нет
Всего: 4



кстати, еще хотел бы просто дополнить в тему по поводу копирования и ссылок на функции.

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


 




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


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

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