나는 최근에 흥미로운 질문에 직면했다.
이 문제를 분석하기 전에 값으로 부름받은 내용과 참조로 호출되는 것을 이해해야합니다. 컴퓨터 과학 에서이 부분을 평가 전략이라고합니다. 함수를 호출 할 때 변수, 실제 매개 변수와 공식 매개 변수간에 값이 전달되는 방법을 결정합니다.
값 대 통과 대 참조로 통과하십시오
값으로 전화는 가장 일반적으로 사용되는 평가 전략입니다. 함수의 공식 매개 변수는 호출 할 때 통과 한 실제 매개 변수의 사본입니다. 공식 매개 변수의 값을 수정하면 실제 매개 변수에 영향을 미치지 않습니다.
참조 별 (참조로 호출)를 통과 할 때 함수의 공식 매개 변수는 사본이 아닌 실제 매개 변수의 암시 적 참조를받습니다. 즉, 함수 매개 변수의 값이 수정되면 실제 매개 변수도 수정됩니다. 둘 다 같은 값을 가리 킵니다.
참조별로 통과하면 기능 호출 추적이 더 어렵고 때로는 미묘한 버그가 발생합니다.
복제본이 매번 복제되므로 합격 가치별로는 복잡한 유형의 경우 성능이 낮습니다. 값을 전달하는 두 방법 모두 고유 한 문제가 있습니다.
먼저 C 예제를 살펴 보겠습니다.
코드 사본은 다음과 같습니다.
void modify (int p, int * q)
{
p = 27; // pass py value는 실제 매개 변수 a의 사본이며 p 만 수정됩니다.
*Q = 27; // Q는 B에 대한 참조이며 Q와 B는 모두 수정됩니다.
}
int main ()
{
int a = 1;
int b = 1;
수정 (a, & b); // A Pass By Value, B 참조 별 패스,
// A는 변경되지 않았으며 B가 변경되었습니다
반환 (0);
}
여기에서 볼 수 있습니다.
a => p가 값으로 전달되면 공식 매개 변수 p의 값을 수정하면 실제 매개 변수 a에 영향을 미치지 않으며 P는 a의 사본 일뿐입니다.
b => q는 참조로 전달됩니다. 공식 매개 변수 Q의 값을 수정할 때 실제 매개 변수 값에도 영향을 미칩니다. b.
JS 값이 어떻게 통과되는지 탐색하십시오
JS의 기본 유형은 값으로 전달됩니다.
코드 사본은 다음과 같습니다.
var a = 1;
함수 foo (x) {
x = 2;
}
foo (a);
Console.log (a); // 여전히 1, x = 2의 할당에 영향을받지 않습니다.
대상을 보자 :
코드 사본은 다음과 같습니다.
var obj = {x : 1};
기능 foo (o) {
ox = 3;
}
foo (obj);
Console.log (obj.x); // 3, 수정!
O와 OBJ는 동일한 대상이며 O는 OBJ의 사본이 아닙니다. 따라서 가치가 전달되지 않습니다. 그러나 이것은 JS 객체가 참조로 전달된다는 것을 의미합니까? 다음 예를 살펴 보겠습니다.
코드 사본은 다음과 같습니다.
var obj = {x : 1};
기능 foo (o) {
o = 100;
}
foo (obj);
Console.log (obj.x); // 여전히 1, OBJ는 100으로 수정되지 않았습니다.
참조로 전달되면 공식 매개 변수 O의 값을 수정하면 실제 매개 변수에 영향을 미칩니다. 그러나 여기에서 o의 값을 수정하는 것은 OBJ에 영향을 미치지 않습니다. 따라서 JS의 객체는 참조로 전달되지 않습니다. 그렇다면 객체의 값은 JS에서 어떻게 전달됩니까?
공유로 통화를 통과하십시오
정확하게 말하면, JS의 기본 유형은 값으로 전달되며 객체 유형은 공유에 의해 전달됩니다 (공유로 호출, 객체에 의해 호출되고 개체별로 공유). Barbara Liskov가 처음 제안했습니다. 1974 년 GLU 언어. 이 평가 전략은 Python, Java, Ruby, JS 및 기타 언어에 사용됩니다.
이 전략의 요점은 함수가 인수를 통과 할 때 함수는 객체의 실제 인수 참조의 사본을 받아 들인다는 것입니다 (값이 전달 된 객체의 사본이나 참조로 전달되는 암시 적 참조). 그것과 참조별로 전달되는 차이점은 공유 패스에서 함수 매개 변수의 할당이 실제 매개 변수의 값에 영향을 미치지 않는다는 것입니다. 다음 예에서와 같이, 공식 매개 변수 O의 값을 수정하여 OBJ의 값을 수정할 수 없습니다.
코드 사본은 다음과 같습니다.
var obj = {x : 1};
기능 foo (o) {
o = 100;
}
foo (obj);
Console.log (obj.x); // 여전히 1, OBJ는 100으로 수정되지 않았습니다.
그러나 참조는 사본이지만 참조 된 객체는 동일합니다. 동일한 객체를 공유하므로 공식 매개 변수 개체의 속성 값을 수정하면 실제 매개 변수의 속성 값에도 영향을 미칩니다.
코드 사본은 다음과 같습니다.
var obj = {x : 1};
기능 foo (o) {
ox = 3;
}
foo (obj);
Console.log (obj.x); // 3, 수정!
객체 유형의 경우 객체가 변이하기 때문에 객체 자체를 수정하면 객체의 참조 및 참조 사본의 공유에 영향을 미칩니다. 기본 유형의 경우, 둘 다 불변이기 때문에 공유 및 값을 통과하는 것 (값으로 호출) 사이에는 차이가 없으므로 JS 기본 유형은 가치를 통과하고 공유 통과와 일치합니다.
코드 사본은 다음과 같습니다.
var a = 1; // 1은 유형 번호, 불변의 var b = a입니다. B = 6;
공유가 통과 한 평가 전략에 따르면 A와 B는 두 가지 다른 참조 (B는 a의 참조 사본)이지만 동일한 값을 참조합니다. 여기서 기본 유형 번호 1은 불변이기 때문에 가치를 통과하는 것과 여기에서 공유를 통과하는 것에는 차이가 없습니다.
기본 유형의 불변의 속성
기본 유형은 불변이며 객체 만 변경할 수 있습니다. 예를 들어, 숫자 값 100, 부울 값은 true, false이며 이러한 값을 수정하는 것 (예 : 1을 3으로 바꾸고 100으로 바꾸는 것)은 의미가 없습니다. 오해하기 쉬운 것은 JS의 문자열입니다. 때때로 우리는 문자열의 내용을 "변경"하려고 시도하지만 JS에서는 문자열 값으로 보이는 "수정"작업이 실제로 새 문자열 값을 생성하는 것입니다.
코드 사본은 다음과 같습니다.
var str =“abc”;
str [0]; //“A”
str [0] = "d";
str; // 여전히 "ABC"; 과제는 유효하지 않습니다. 문자열의 내용을 수정할 방법이 없습니다.
객체는 다르고 객체는 가변적입니다.
코드 사본은 다음과 같습니다.
var obj = {x : 1};
obj.x = 100;
var o = obj;
ox = 1;
obj.x; // 1, 수정
o = 참;
obj.x; // 1, o = true로 인해 변경되지 않습니다.
여기서 변수 OBJ가 정의되고 값은 객체이며 OBJ.x 속성의 값은 100으로 설정됩니다. 그런 다음 다른 변수 O를 정의하고 값은 여전히이 개체 객체입니다. 이 시점에서 두 변수의 값은 OBJ 및 O가 동일한 객체를 가리 킵니다 (동일한 객체에 대한 참조 공유). 따라서 객체의 내용을 수정하면 OBJ와 O에 영향을 미칩니다. 그러나 객체는 참조로 전달되지 않습니다. O의 값은 O = true로 수정되며 OBJ에 영향을 미치지 않습니다.