Javascript-форум (https://javascript.ru/forum/)
-   Общие вопросы Javascript (https://javascript.ru/forum/misc/)
-   -   Переприсвоение переменной (https://javascript.ru/forum/misc/72666-pereprisvoenie-peremennojj.html)

Михаил Хе 16.02.2018 10:03

Переприсвоение переменной
 
Доброго,

Встречается такой код:

function foo(arg1) {
  arg1 = arg1 || 'что-то опциональное';
  ...
}


Все работает отлично, но вопрос. Будет ли такое переприсвоение иметь негативные последствия, допустим, утечки памяти? Вообще, будет ли заново выделяться память под ту же самую переменную? Или все зашибись, не надо париться?

Спасибо.

ksa 16.02.2018 10:09

Цитата:

Сообщение от Михаил Хе
Или все зашибись, не надо париться?

Все зашибись. :victory:

Dilettante_Pro 16.02.2018 10:10

Михаил Хе,
А вот такая ситуация вас не волнует?
for (var i = 0; i < 1000; i++) { ... }

Счетчику переприсваивается значение:-E

Переприсвоение ничем не отличается от обычного присвоения - значение присваивается одной и той же переменной

Михаил Хе 16.02.2018 11:09

Цитата:

Сообщение от Dilettante_Pro (Сообщение 478323)
Михаил Хе,
А вот такая ситуация вас не волнует?
for (var i = 0; i < 1000; i++) { ... }

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

Меня насторожило, что именно происходит при переприсвоении переменной обратно на себя, может ли движок правильно "ничего не сделать, не париться попусту".

ksa 16.02.2018 11:13

Цитата:

Сообщение от Михаил Хе
но тут другое

Отнюдь! :D
Все это "одно и то же дело". Вот тебе еще одно...

var s=0;
var val=10;
s=s+val;

И такого сплошь и рядом! :D
Если бы твои опасения были не напрасны - в мире JS наступил бы крах! :cray:

Dilettante_Pro 16.02.2018 11:17

Михаил Хе,
Цитата:

Сообщение от Михаил Хе
спасибо, но тут другое и должно меняться

чем i = i + 1 логически другое по сравнению с arg1 = arg1 || 'что-то опциональное' ?
Кому и что оно должно?

Михаил Хе 16.02.2018 12:25

Давайте без эмоций, я понимаю, что дело плевое и вроде как проблем нет, но мой пример кардинально отличается от этого:

var s=0;
var val=10;
s=s+val;


и от этого
i = i + 1;


В этих двух примерах движок JS реально делает действия по изменению состояния переменных.

В логическом случае с
var1 = var1;


движок не должен ничего делать. Я правильно разъяснил?

Давайте вникать.

Dilettante_Pro 16.02.2018 12:29

Михаил Хе,
Цитата:

Сообщение от Михаил Хе
движок не должен ничего делать

Он делает то, что написано в операторе - берет значение переменной var1 и присваивает его переменной var1.

Dilettante_Pro 16.02.2018 12:37

Кстати, в вашем начальном примере возможно даже изменение типа переменной
function foo(arg1) {
  arg1 = arg1 || 'что-то опциональное';
  alert(arg1);
}
foo(0);
foo(1);
foo('что-то');

Alexandroppolus 16.02.2018 12:54

Цитата:

Сообщение от Михаил Хе
arg1 = arg1 || 'что-то опциональное';

Вообще, будет ли заново выделяться память под ту же самую переменную?

память выделится в случае, если arg1 пустое значение и надо создать строку. Вот под строку и выделится (хотя под капотом тут все не так просто, например, эта строка может создаться только один раз и использоваться многократно, поскольку неизменяема).

Если arg1 не пустое, до операции со строкой дело не дойдет, остается arg1 = arg1.
здесь память тоже не выделяется, она уже выделена на стеке, arg1 обычная стековая переменная, просто записываются данные в ячейку памяти.

Михаил Хе 16.02.2018 12:57

Цитата:

Сообщение от Dilettante_Pro (Сообщение 478361)
Михаил Хе,
Он делает то, что написано в операторе - берет значение переменной var1 и присваивает его переменной var1.

Да, делает, но по факту (как мне вы все тут вразумили) никаких изменений в памяти, в указателях не должно происходить, как-будто строки вообще не было.

Пример

arg1 = arg1 || '';


аналогичный, при условии, что arg1 истина - тоже ничего не должно происходить (по факту состояния среды всего и всея движка).

Nexus 16.02.2018 12:59

Вероятно после оптимизации строка "arg1 = arg1" вообще будет удалена, т.к. смысла в ней нет.

Alexandroppolus 16.02.2018 13:05

Цитата:

Сообщение от Nexus (Сообщение 478367)
Вероятно после оптимизации строка "arg1 = arg1" вообще будет удалена, т.к. смысла в ней нет.

если она записана именно как "arg1 = arg1", то конечно будет выкинута.
в случае "arg1 = arg1 || '...'", возможно, компилятор переосмыслит её как
if (!arg1) {
 arg1 = '...';
}

Михаил Хе 16.02.2018 13:06

Цитата:

Сообщение от Alexandroppolus (Сообщение 478364)

Если arg1 не пустое, до операции со строкой дело не дойдет, остается arg1 = arg1.
здесь память тоже не выделяется, она уже выделена на стеке, arg1 обычная стековая переменная, просто записываются данные в ячейку памяти.

Т.е. у переменной перезапишется указатель на значение

Михаил Хе 16.02.2018 13:12

Цитата:

Сообщение от Nexus (Сообщение 478367)
Вероятно после оптимизации строка "arg1 = arg1" вообще будет удалена, т.к. смысла в ней нет.

Я привел усугубленный пример, допустим:

function foo(arg){ ...; return arg;}
var var1 = {};
var1 = foo(var1);

ksa 16.02.2018 13:18

Цитата:

Сообщение от Михаил Хе
Давайте вникать.

Было бы во что...

ksa 16.02.2018 13:20

Цитата:

Сообщение от Михаил Хе
допустим:

function foo(arg){ ...; return arg;}
var var1 = {};
var1 = foo(var1);

Да хоть, что допускай. Это все основы языка. Они работают беспроблемно не только в JS, а вообще в любом ЯП.

MallSerg 18.02.2018 00:55

Что за гадания на кофейной гуще. Все исходники в открытом доступе.
https://github.com/v8/v8/tree/f165df...rc/interpreter
Код не сложный и ни сказать что бы слишком большой. вполне по силам среднему разработчику.

Первое что делает интерпретатор строит лексическое дерево и на основании него генерирует байткод.
Никаких оптимизаций в этот момент не производится. Байткод сразу же готов к работе в своей вм.
Лексическое дерево разбивается на области видимости. Константы и логика в виде байт кода хранится отдельно а переменные параметры возвращаемое значение ссылки на другие области видимости хранятся в отдельной таблице ключ значение дальше в куче. смещение на эту кучу передается блоку кода при вызове ( Именно по этому работает такое понятие как поднятие переменных т.к. на момент исполнения блока кода имя переменной уже есть в таблице ключ значение для этого блока кода.). Данные хранятся отдельно от блока кода для того что бы работали такие вещи как замыкания и рекурсия.

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

Если блок кода (функция) вызывается часто или выполняется долго (интерпретатор считает время исполнения) то этот блок передается оптимизатору а там все сложно =).


Часовой пояс GMT +3, время: 22:39.