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

js에서 참조와 복사(전달 값과 전달 주소)에 대해 간단히 설명

일반적으로 사람들이 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"

이렇게 교환을 성공적으로 수행했습니다. 

다시 js의 블록 수준 스코프를 언급해야 합니다. 어떤 언어에서는 정의되지 않은 오류가 발생할 것입니다. js는 블록 수준 스코프가 없기 때문에, change에서 a, b 변수를 찾을 수 없으면 자동으로 상위 계층으로 찾습니다. 따라서 여기서의 a, b는 전역 변수의 참조입니다.

그리고 위의 a, b는 change 함수의 변수이며, 함수를 호출할 때 a, b의 참조를 전달하여 이 두 변수에 할당했습니다. 그러나 전역의 a, b를 변경할 수 없습니다. 다른 이름으로 바꾸면 더 이해하기 쉽습니다.

이게 조금만 언급해야 할 것 같습니다. 벗어난 것 같습니다...

참조와 복사에 대한 것으로 돌아가서, 비교 연산에서 주의해야 할 사항

전달 값을 비교할 때는 숫자를 비교하며, 전달 주소를 비교할 때는 참조를 비교합니다. 참조가 다르면 숫자가 같아도 다릅니다.

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

클로저에서...

클로저는 js에서 가장 복잡한 것 중 하나입니다. 우리 부서의 인터뷰에서 반복되는 기본 질문, 항상 유효합니다...

여기서는 클로저에 대해 말하지 않고, 전달 값과 참조에 대한 부분만 설명하겠습니다. 그런 날에 명확한 규칙, 간결한 언어, 생동감 넘치는 예제로 그것을 완전히 설명할 수 있다고 확신하면, 이 제js에서는 언급할 수 없는 존재에 대해 자세히 설명하겠습니다...

클로저에서는, 내부 함수가 외부 함수의 지역 변수를 참조 방식으로 사용하며 복사하지 않습니다.

실제로 이것은 클로저를 이해하는 매우 중요한 부분입니다. 이를 통해 매우 경典적인 클로저 현상을 설명할 수 있습니다. 클로저를 설명할 때 많은 곳에서 사용하는 예제입니다.

/*함수를 생성하여 배열의 노드에 이벤트 처리기를 설정합니다. 노드를 클릭할 때, 노드의 순번을 alert합니다.*/
var add_handlers = function (nodes) {
  var i;
  for (i = 0, l = nodes.length; i < l; i ++) {
    nodes[i].onclick = function (e) {
      alert(i);  // 물론, 여기의 결과는 항상 노드 총 수가 alert되는 것입니다...
    };
  };
};

왜 항상 노드 총 수가 아니라 예상한 순번이 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의 값의 복사라는 것입니다. 실제로는 일반 함수와 동일합니다. 클로저를 추가했기 때문에 혼란스러워하지 마시고, 원천으로 돌아가 생각하면 이해됩니다. 원천은 위에서 설명한 전달 주소의 전달입니다.

다만, 클로저라는 이상한 이름에 막혀서는 안 됩니다. 실제로는 우리가 일상적으로 사용하는 함수 원리와 동일합니다. '更长의 생명주기', 'private 변수를 보호하는' 등 클로저의 주장된 특성을 잊고, 일반 함수로 생각하면 쉽게 이해할 수 있습니다. (또는 전체 함수를 특별한 클로저로 볼 수도 있습니다.)

중요한 것은 모든 화려함을 내려놓고 가장본질로 돌아가는 것입니다... 다시 틀린 길을 걸었습니다...

이 글은 js에서의 참조와 복사(전달 값과 전달 주소)에 대한 간단한 이야기를 나누고자 합니다. 이를 통해 여러분께 참고가 되길 바랍니다. 또한, 나락教程에 많은 지지를 부탁드립니다.

좋아하는 것