English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

Краткое объяснение ссылок и копирования в JavaScript (передача значений и адресов)

Кажется, что很少有人 рассказывает о ссылке и копировании в JavaScript, но понимание этой концепции может помочь понять многое

Сначала давайте рассмотрим очень основное, посмотрим, что передается в JavaScript различных типов данных

Ссылка: объекты, массивы, функции

Копирование: числа, булевы

Строки требуют отдельного рассмотрения, так как они имеют特殊性, не всегда можно определить, передается ли ссылка или копия значения (поскольку значение строки изменить нельзя, обсуждение этого вопроса также не имеет смысла), но显然 при сравнении они передаются по значению (более подробно о сравнении будет сказано позже)

Ниже мы рассмотрим конкретное проявление при использовании

Самый обычный способ использования - это присваивание

var a = 1;
var b = a;  // Назначается копия значения a
b ++;
alert(a);  //"1"  Изменения b не влияют на a
/****************************************/
var a = [1];
var b = a;   // Назначается ссылка на a 
b[0] ++;
alert(a); //"2"  Изменения b также действуют на a, но, конечно, b = [2]; это изменение не действует на a

Параметры функции

Передача по значению: Переданной функции является копия значения, изменения, которые вносит функция, не видны снаружи

var a = 1;
var b = 2;
function change(a,b) {
 var c = a;
 a = b;   // Использование новой ссылки для замены
 b = c;
 alert(a);  //"2"     
 alert(b);  //"1"
};
change(a,b);
alert(a);  //"1"     
alert(b);  //"2"

Передача по ссылке:Переданной функции является ссылка на значение, изменения свойств, которые вносит функция, видны снаружи, но при замене новым указателем они не видны снаружи, например

var a = [1, 2, 3];
var b = [5, 6];
function change(a,b) {
 a[0] = 4;  // Изменение свойств видимо снаружи 
 var c = a;
 a = b;   // Использование новой ссылки для замены
 b = c;
 alert(a); // "5,6"     
 alert(b); // "4,2,3"
};
change(a,b);
alert(a);  // "4,2,3"
alert(b);   // "5,6"

Из результатов можно看出, что a и b не были обменены, потому что новая ссылка покрыла внешнюю невидимую ссылку. Это естественно, потому что функция только получила ссылку и не имеет права изменять ссылку.

Теперь это уже по-другому.

var a = [1, 2, 3];
var b = [5, 6];
function change() {
 var c = a;
 a[0] = 4;
 a = b;
 b = c;
};
change();
alert(a); // "5,6"
alert(b); // "4,2,3"

Мы успешно обменяли их. 

Должна упомянуть и о блоковом охвате в JavaScript. В некоторых языках это вызовет ошибку, так как JavaScript не имеет блокового охвата. Поэтому, когда в change не находят переменные a, b, он автоматически ищет их в上一层, поэтому a, b — это ссылки на глобальные переменные.

А上面的 a, b — это переменные функции change. При вызове функции передается ссылка на a, b, и они передаются этим переменным, но это не позволяет изменить глобальные a, b. Если изменить имя, это будет clearer.

Я кратко упомяну это, чтобы не отклоняться от темы...

Вернемся к вниманию при сравнении ссылок и копированию.

При сравнении传值的比较比较的是数值,而传址的比较比较的是引用,即使数值相同,引用不同也不相等。

1 == 1; // true
1 === 1; // true
[0] == [0]; // false
[0][0] == [0][0]; // true
[0][0] === [0][0]; // true
[0].toString() == [0].toString(); // true 

В closures...

Closures — это одна из самых сложных вещей в JavaScript. Это классический вопрос на собеседовании в нашей компании, который часто задают и не утомляются.

Я не буду сейчас говорить о closures, а только о части, связанной с передачей значений и ссылок. Когда-нибудь, когда я смогу объяснить это ясно, кратко и с примерами, я подробно расскажу о этом важном элементе JavaScript.

В closures, внутренние функции используют локальные переменные внешних функций через ссылку, а не через копирование.

Это действительно важная часть для понимания closures, которую можно использовать для объяснения одной из самых классических явлений closures, пример, который часто используется для объяснения closures.

/*Создайте функцию, чтобы установить обработчики событий для узлов массива, когда нажимается узел, alert выводит номер узла*/
var add_handlers = function (nodes) {
  var i;
  for (i = 0, l = nodes.length; i < l; i++) {
    nodes[i].onclick = function (e) {
      alert(i); // Naturally, the result here must be the total number of nodes each time……
    };
  };
};

Почему каждый раз alert являются узлы总数的, а не ожидаемого номера, это можно легко объяснить с помощью копий и ссылок

Потому что внутренние функции используют ссылки на внешние переменные, а не копии, то есть когда я устанавливаю onclick событие для каждого узла, я передаю ссылку на i в alert, когда я нажимаю на узел и вызывается onclick событие, значение i уже стало总数 узлов……

var add_handlers = function (nodes) {
  var i;
  for (i = 0, l = nodes.length; i < l; i++) {
    nodes[i].onclick = function (i) {
      return function() {
      alert(i);  
      };
 }(i);
  };
};

Так как после этого исправления правильно, потому что в настоящее время传入的是i значения копии, на самом деле это как обычная функция, не нужно путаться из-за closures, вернемся к истокам, чтобы понять, и истоки - это выше提到的 передача адреса.

Просто хочу добавить, не пугайтесь странного названия closures, на самом деле они такие же, как и функции, которые мы используем каждый день, отложите в сторону такие свойства closures, как «длинная жизнь» и «защита частных переменных», и легко понять их, если их посмотреть как обычные функции (или можно换个角度 и看待全局 функции как特殊的 closures), легко понять.

Важно放下所有的虚荣,回归最本质的……又跑题了……

Этот краткий обзор ссылки и копирования (передача значений и адресов) в JavaScript, который я хочу поделиться с вами,希望能 стать для вас参考,и希望大家多多支持呐喊教程。

Основной учебник
Вам может понравиться