Насколько я понимаю: в Javascript объекты и массивы передаются как ссылки, а не значения для аргументов функции. Группа jQuery является объектом и, следовательно, должна передаваться как ссылка.

Однако в приведенном ниже тестовом сценарии я обнаружил, что происходит что-то странное; группа jQuery ведет себя как значение, а не ссылка, если только она не заключена в другой объект ... кто-нибудь может это объяснить?

<html>
<head>
 <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>
</head>
<body>
<script>

 function test(arg){
   arg = arg.add($('<span/>'))
   console.log(arg);
 };

 ele = $('<div/>');
 test(ele);  // div + span in the group as expected
 console.log(ele); // only the div - the 'arg' param in function was a copy

 function test2(arg){
   arg.a = arg.a.add($('<span/>'));
   console.log(arg.a);
 };

 obj = {a:ele};
 test2(obj); // div + span in the group as expected
 console.log(obj.a); // both in the group - arg acted like a reference!

</script>
</body>
</html>
6
MachineElf 14 Сен 2010 в 18:19

2 ответа

Лучший ответ

Это «особенность» метода .add(). Он не изменяет исходный объект jQuery, а возвращает новый объект с добавленным значением.

В вашем первом примере вам нужно будет вернуть переменную arg и перезаписать ele.

 function test(arg){
   arg = arg.add($('<span/>'))
   console.log(arg);
   return arg;  // return the new jQuery object stored in "arg"
 };

 ele = $('<div/>');
 ele = test(ele);  // overwrite the original "ele" with the returned value
 console.log(ele); 

РЕДАКТИРОВАТЬ: Чтобы дать еще одну иллюстрацию, используя ваш код, но с .push(), который изменяет исходный объект, вы увидите, что правильное значение обновлено в ele.

 function test(arg){
   arg = arg.push($('<span/>')[0])
   console.log(arg);  // Because .push() is being used, "arg" will reference 
                      //   the new length of the array.
 };

 ele = $('<div/>');
 test(ele);  
 console.log(ele); // Will reference jQuery object with both elements

РЕДАКТИРОВАТЬ: Однажды последняя иллюстрация. Поскольку .add() возвращает новый объект, вы можете обновить обе переменные, чтобы они указывали на одно и то же значение, например:

ele = arg = arg.add($('<span/>'));

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

3
user113716 14 Сен 2010 в 15:05

Два теста, которые вы выполнили, не совпадают. Первый устанавливает переменную arg в значение arg.add(...), а второй устанавливает свойство на arg с именем a в значение arg.a.add(...). Передача «по ссылке» в JavaScript на самом деле не такая же, как в других языках (на самом деле, некоторые не согласятся, что это действительно передача по ссылке). Когда вы передаете переменную, тип которой является объектом, вы получаете ссылку на ее значение, а не на исходную переменную.

Когда вы устанавливаете arg = arg.add(...), вы устанавливаете новое значение для переменной arg и переопределяете ее предыдущее значение. Это не изменит переданную переменную, потому что у вас нет ссылки на нее, у вас есть только ссылка на ее значение (объект).

0
Andy E 14 Сен 2010 в 14:26