Тема: Зацените
Показать сообщение отдельно
  #61 (permalink)  
Старый 11.08.2008, 01:34
Профессор
Отправить личное сообщение для Dmitry A. Soshnikov Посмотреть профиль Найти все сообщения от Dmitry A. Soshnikov
 
Регистрация: 25.02.2008
Сообщений: 707

Андрей Параничев, да, я сразу не заметил, но ZoNT, возможно, просто не знаком с контекстами и не видит, что глобальная переменная для объекта Global (в браузере Global === window) будет (относительно scope'a) играть такую роль же, как локальная переменная в функции. Поэтому, чтобы проводить опыты, чтобы эмпирически подтверждать теорию, надо конкретно, однозначно определить - какие переменные (какого скопа) участвуют в тестах.

Сообщение от ZoNT
На него заходят нубы и задают вопросы. И им надо разжовывать.
ZoNT, разжевываю:

var a = 10; - глобальная переменная
alert(window['a']); // это свойство объекта Global (window)

function test() {
  var c = 20; - локальная переменная
  alert([c, a]);
}


Переменная "c" стала свойством объекта variable object (10.1.3) - этот объект имеется у каждой функции и хранит все локальные переменные, все формальные параметры, а также все декларации функций. Т.е. в нашем случае variable object (далее для сокращения - VO) функции "test" имеет одно свойство "c". Схематично отобразим так:

VO(test) = {c: 20};


Далее, мы видим alert([c, a]);. Спрашивается, откуда выдается "20,10", если VO(test) не имеет у себя свойства "а"? А дело в scope chain'e (10.1.4) - цепи скопов (variable object'ов, начиная от VO функции и вверх до родительских скопов), которые хранит функция. Это еще один объект (хранится во внутреннем свойстве [[scope]]), который ассоциирован с каждой функцией. Т.е. схематически [[scope]] функции test будет таким:

[[scope]](test) = {
  VO(Global): {
    a: 10
  },
  VO(test): {
    c: 20;
  }
};


А далее - самое интересное (опять же - смотреть в 10.1.4). При обращении к переменной внутри функции она ищется в скоп-чейне последовательно вверх, начиная от VO самой функции. Все. Больше никаких чудес нет.

Поэтому ясно видно, что: alert(c); сработает быстрее, т.к. свойство "c" будет сразу же найдено в первом просматриваемом скопе.

Что же касается alert(a):

- смотрим в VO(test); - не нашли;
- смотрим в VO(Global) - нашли.

Два действия против одного (поиск в двух скопах (обращение к глобальной переменной) против моментального нахождения в первом скопе (обращение к локальной переменной)). Есть разница? Ну вот и замечательно.

Поэтому, еще раз - обращение из абстрактного локального скопа к глобальной переменной всегда (всегда!) будет медленней, чем обращение к локальной. Точка.

P.S.: VO(Global) - это утрированно, на самом деле сам Global уже является variable object'ом для глобальных переменных.

P.S.[2]: еще раз (уже зная теорию) смотрите результаты своего же примера:

<html>
<body>
<script type="text/javascript">

// local var
function F1(){
  var arr = [];
  // здесь идет обращение к *локальной* переменной
  // arr
  for (var i=0;i<1000;i++) arr.push(i);
}

var start = new Date();
for (var i=0;i<1000;i++) F1();
var res1 = (new Date())-start;
//**********************************


// Global var

function F2(){
  for (var i=0;i<1000;i++) arr.push(i);
}

var start = new Date();
var arr = [];
for (var i=0;i<1000;i++) F2();
var res2 = (new Date())-start;

// test 3

var start = new Date();
var arr2 = [];
for (var i=0;i<1000;i++) {
  for (var k=0;k<1000;k++) arr.push(k);
}
var res3 = (new Date())-start;

//**********************************


alert([res1, res2, res3]);

</script>
</body>
</html>


P.S.[3]: ZoNT, я пока закрываю глаза на все твои переходы на личности (в надежде, что мои подробные разъяснения помогут тебе более детально понять, как работает JavaScript), но это последнее предупреждение. Общаться - давай общаться, но рассуждать тут о нубстве и о возрастах, когда ты сам не далеко ушел от нубства в данном конкретном вопросе - это излишне.

P.S.[4]: а по поводу выделения памяти каждый раз (вместо уже существующей - не важно - в глобальном контексте, или же в прототипе конструктора, как я отмечал) - это уже другой вопрос совсем. И не зачем подменять понятия, говоря, что работает быстрее - "обращение к локальной или глобальной переменной?". Я и сам отметил (о хранении однотипного объекта в одном месте).
__________________
Тонкости ECMAScript

Последний раз редактировалось Dmitry A. Soshnikov, 11.08.2008 в 01:58.
Ответить с цитированием