Андрей Параничев, да, я сразу не заметил, но
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]: а по поводу выделения памяти каждый раз (вместо уже существующей - не важно - в глобальном контексте, или же в прототипе конструктора, как я отмечал) - это уже другой вопрос совсем. И не зачем подменять понятия, говоря, что работает быстрее - "обращение к локальной или глобальной переменной?". Я и сам отметил (о хранении однотипного объекта в одном месте).