etc./StackOverFlow

JavaScript는 참조에 의한 전달 또는 값에 의한 전달 언어입니까?

청렴결백한 만능 재주꾼 2022. 2. 15. 08:49
반응형

질문자 :Danail Nachev


기본 유형(숫자, 문자열 등)은 값으로 전달되지만 객체는 둘 다 값으로 전달될 수 있기 때문에 알 수 없습니다(객체를 보유하는 변수가 실제로 객체에 대한 참조라고 생각하는 경우). ) 및 참조에 의해 전달(객체에 대한 변수가 객체 자체를 보유한다고 생각할 때).

결국에는 중요하지 않지만 규칙을 전달하는 인수를 제시하는 올바른 방법이 무엇인지 알고 싶습니다. 이에 관한 의미 체계를 정의하는 JavaScript 사양에서 발췌한 내용이 있습니까?



자바스크립트에서 흥미롭습니다. 다음 예를 고려하십시오.

 function changeStuff(a, b, c) { a = a * 10; b.item = "changed"; c = {item: "changed"}; } var num = 10; var obj1 = {item: "unchanged"}; var obj2 = {item: "unchanged"}; changeStuff(num, obj1, obj2); console.log(num); console.log(obj1.item); console.log(obj2.item);

이렇게 하면 출력이 생성됩니다.

 10 changed unchanged
  • obj1 이 참조가 아닌 경우 obj1.item 을 변경해도 함수 외부의 obj1 에는 영향을 미치지 않습니다.
  • 인수가 적절한 참조였다면 모든 것이 변경되었을 것입니다. num100 이고 obj2.item "changed" 읽힙니다. 대신 num10 유지되고 obj2.item "unchanged " 상태로 유지됩니다.

대신 전달된 항목이 값으로 전달되는 상황입니다. 그러나 값으로 전달되는 항목 자체 가 참조입니다. 기술적으로 이를 공유 공유 라고 합니다.

실용적인 측면에서 이것은 매개변수 자체를 변경하면( numobj2 와 같이) 매개변수에 제공된 항목에 영향을 미치지 않습니다. 그러나 매개변수의 내부 를 변경하면 다시 전파됩니다( obj1 에서처럼).


Community Wiki

항상 값으로 전달되지만 객체의 경우 변수 값은 참조입니다. 이 때문에 객체를 전달하고 해당 멤버 를 변경하면 해당 변경 사항이 함수 외부에서 유지됩니다. 이렇게 하면 참조로 전달하는 것처럼 보입니다. 그러나 실제로 개체 변수의 값을 변경하면 변경 사항이 지속되지 않는 것을 볼 수 있으며 실제로 값에 의해 전달되었음을 증명합니다.

예시:

 function changeObject(x) { x = { member: "bar" }; console.log("in changeObject: " + x.member); } function changeMember(x) { x.member = "bar"; console.log("in changeMember: " + x.member); } var x = { member: "foo" }; console.log("before changeObject: " + x.member); changeObject(x); console.log("after changeObject: " + x.member); /* change did not persist */ console.log("before changeMember: " + x.member); changeMember(x); console.log("after changeMember: " + x.member); /* change persists */

산출:

 before changeObject: foo in changeObject: bar after changeObject: foo before changeMember: foo in changeMember: bar after changeMember: bar

Tim Goodman

변수는 개체를 "보유"하지 않습니다. 그것은 참조를 보유하고 있습니다. 해당 참조를 다른 변수에 할당할 수 있으며 이제 둘 다 동일한 개체를 참조합니다. 항상 값으로 전달됩니다(해당 값이 참조인 경우에도...).

매개변수로 전달된 변수가 보유한 값을 변경할 수 있는 방법은 없습니다. JavaScript가 참조 전달을 지원하는 경우 가능합니다.


Shog9

내 2센트... 이것이 내가 이해하는 방식입니다. (틀렸다면 지적해주시면 감사하겠습니다)

값/참조로 전달에 대해 알고 있는 모든 것을 버릴 때입니다.

JavaScript에서는 값으로 전달되었는지 또는 참조로 전달되었는지 여부는 중요하지 않습니다. 중요한 것은 함수에 전달된 매개변수의 돌연변이 대 할당입니다.

알겠습니다. 최선을 다해 제가 의미하는 바를 설명하겠습니다. 몇 가지 개체가 있다고 가정해 보겠습니다.

 var object1 = {}; var object2 = {};

우리가 한 것은 "할당"입니다... 변수 "object1" 및 "object2"에 2개의 개별 빈 개체를 할당했습니다.

이제 우리가 object1을 더 좋아한다고 가정해 봅시다. 그래서 우리는 새로운 변수를 "할당"합니다.

 var favoriteObject = object1;

다음으로, 이유가 무엇이든 우리는 객체 2를 더 좋아한다고 결정합니다. 그래서 우리는 약간의 재할당을 합니다.

 favoriteObject = object2;

object1 또는 object2에는 아무 일도 일어나지 않았습니다. 우리는 데이터를 전혀 변경하지 않았습니다. 우리가 한 일은 우리가 가장 좋아하는 물건을 다시 할당하는 것뿐이었습니다. object2와 favoriteObject가 모두 동일한 개체에 할당되어 있다는 사실을 아는 것이 중요합니다. 이러한 변수 중 하나를 통해 해당 개체를 변경할 수 있습니다.

 object2.name = 'Fred'; console.log(favoriteObject.name) // Logs Fred favoriteObject.name = 'Joe'; console.log(object2.name); // Logs Joe

이제 예를 들어 문자열과 같은 기본 요소를 살펴보겠습니다.

 var string1 = 'Hello world'; var string2 = 'Goodbye world';

다시, 우리는 마음에 드는 것을 선택합니다.

 var favoriteString = string1;

우리의 favoriteString 및 string1 변수는 모두 'Hello world'에 할당됩니다. 이제 FavoriteString을 변경하려면 어떻게 해야 합니까??? 무슨 일이 일어날 것???

 favoriteString = 'Hello everyone'; console.log(favoriteString); // Logs 'Hello everyone' console.log(string1); // Logs 'Hello world'

어....무슨 일이야. FavoriteString을 변경하여 string1을 변경할 수 없었습니다. 왜죠? string 객체를 변경 하지 않았기 때문입니다. 우리가 한 모든 것은 새 문자열에 대한 favoriteString 변수 를 "RE ASSIGN"하는 것입니다. 이것은 본질적으로 string1에서 연결을 끊었습니다. 이전 예에서 객체의 이름을 변경할 때 아무 것도 할당하지 않았습니다. (글쎄요, 변수 자체가 아니라 ... 그러나 우리는 name 속성을 새 문자열에 할당했습니다.) 대신 2개의 변수와 기본 개체 간의 연결을 유지하는 개체를 변경했습니다. (우리가 문자열 객체 자체 를 수정하거나 변경 하고 싶었더라도 문자열은 JavaScript에서 실제로 변경 불가능하기 때문에 가질 수 없습니다.)

이제 함수 및 매개 변수 전달에 대해 .... 함수를 호출하고 매개 변수를 전달할 때 본질적으로 수행하는 작업은 새 변수에 대한 "할당"이며 사용하여 할당한 것과 정확히 동일하게 작동합니다. 등호(=) 기호.

이러한 예를 들어 보십시오.

 var myString = 'hello'; // Assign to a new variable (just like when you pass to a function) var param1 = myString; param1 = 'world'; // Re assignment console.log(myString); // Logs 'hello' console.log(param1); // Logs 'world'

이제 같은 기능이지만

 function myFunc(param1) { param1 = 'world'; console.log(param1); // Logs 'world' } var myString = 'hello'; // Calls myFunc and assigns param1 to myString just like param1 = myString myFunc(myString); console.log(myString); // logs 'hello'

자, 이제 함수 없이 객체를 대신 사용하는 몇 가지 예를 들어보겠습니다.

 var myObject = { firstName: 'Joe', lastName: 'Smith' }; // Assign to a new variable (just like when you pass to a function) var otherObj = myObject; // Let's mutate our object otherObj.firstName = 'Sue'; // I guess Joe decided to be a girl console.log(myObject.firstName); // Logs 'Sue' console.log(otherObj.firstName); // Logs 'Sue' // Now, let's reassign the variable otherObj = { firstName: 'Jack', lastName: 'Frost' }; // Now, otherObj and myObject are assigned to 2 very different objects // And mutating one object has no influence on the other console.log(myObject.firstName); // Logs 'Sue' console.log(otherObj.firstName); // Logs 'Jack';

자, 같은 일이지만 함수 호출로

 function myFunc(otherObj) { // Let's mutate our object otherObj.firstName = 'Sue'; console.log(otherObj.firstName); // Logs 'Sue' // Now let's re-assign otherObj = { firstName: 'Jack', lastName: 'Frost' }; console.log(otherObj.firstName); // Logs 'Jack' // Again, otherObj and myObject are assigned to 2 very different objects // And mutating one object doesn't magically mutate the other } var myObject = { firstName: 'Joe', lastName: 'Smith' }; // Calls myFunc and assigns otherObj to myObject just like otherObj = myObject myFunc(myObject); console.log(myObject.firstName); // Logs 'Sue', just like before

좋습니다. 이 전체 게시물을 읽으면 JavaScript에서 함수 호출이 작동하는 방식을 더 잘 이해할 수 있을 것입니다. 어떤 것이 참조로 전달되는지 값으로 전달되는지는 중요하지 않습니다. 중요한 것은 할당 대 돌연변이입니다.

함수에 변수를 전달할 때마다 등호(=) 기호를 사용한 것처럼 매개변수 변수의 이름이 무엇이든 "할당"합니다.

등호(=)는 할당을 의미한다는 것을 항상 기억하십시오. JavaScript에서 매개변수를 함수에 전달하는 것은 할당을 의미한다는 것을 항상 기억하십시오. 그것들은 동일하고 2개의 변수는 정확히 같은 방식으로 연결됩니다(즉, 동일한 객체에 할당된 것으로 계산하지 않는 한 그렇지 않습니다).

"변수 수정"이 다른 변수에 영향을 미치는 유일한 경우는 기본 개체가 변경된 경우입니다(이 경우 변수를 수정하지 않고 개체 자체를 수정합니다.

객체와 프리미티브를 구분하는 것은 의미가 없습니다. 마치 함수가 없고 등호를 사용하여 새 변수에 할당하는 것과 똑같은 방식으로 작동하기 때문입니다.

유일한 문제는 함수에 전달하는 변수의 이름이 함수 매개변수의 이름과 동일한 경우입니다. 이런 일이 발생하면 함수 내부의 매개변수를 함수에 대한 완전히 새로운 변수인 것처럼 처리해야 합니다.

 function myFunc(myString) { // myString is private and does not affect the outer variable myString = 'hello'; } var myString = 'test'; myString = myString; // Does nothing, myString is still 'test'; myFunc(myString); console.log(myString); // Logs 'test'

Ray Perea

이러한 구문/개념은 원래 JS가 생성되기 훨씬 전에 정의되었으며 자바스크립트의 의미를 정확하게 설명하지 않습니다. 나는 그것들을 JS에 적용하려고 하는 것이 그렇지 않은 것보다 더 많은 혼란을 야기한다고 생각한다.

따라서 "참조/값으로 전달"에 매달리지 마십시오.

다음을 고려하세요:

  1. 변수는 값에 대한 포인터 입니다.
  2. 변수를 재할당하면 해당 포인터가 새 값을 가리킬 뿐입니다.
  3. 각 변수에는 자체 포인터가 있기 때문에 변수를 재할당해도 동일한 개체를 가리키는 다른 변수에는 영향을 미치지 않습니다.

따라서 이름을 지정해야 한다면 "pass-by-pointer" 라고 말하고 싶습니다. JS에서는 포인터를 다루지 않지만 기본 엔진은 처리합니다.


 // code var obj = { name: 'Fred', num: 1 }; // illustration 'Fred' / / (obj) ---- {} \ \ 1

 // code obj.name = 'George'; // illustration 'Fred' (obj) ---- {} ----- 'George' \ \ 1

 // code obj = {}; // illustration 'Fred' (obj) {} ----- 'George' | \ | \ { } 1

 // code var obj = { text: 'Hello world!' }; /* function parameters get their own pointer to * the arguments that are passed in, just like any other variable */ someFunc(obj); // illustration (caller scope) (someFunc scope) \ / \ / \ / \ / \ / { } | | | 'Hello world'

몇 가지 최종 의견:

  • "값/참조로 전달"이라는 문구 는 언어의 동작 을 설명하는 데만 사용되며 실제 기본 구현은 아닙니다. 이러한 추상화의 결과, 적절한 설명에 필수적인 중요한 세부 사항이 손실되고, 이는 불가피하게 하나의 용어가 추가 정보 없이 실제 동작을 적절하게 설명하지 못하는 현재 상황으로 이어집니다.
  • 프리미티브 는 특별한 규칙에 의해 시행되는 반면 객체 는 그렇지 않지만 프리미티브는 단순히 포인터 체인의 끝이라고 생각하기 쉽습니다.
  • 마지막 예로서, 배열을 지우려는 일반적인 시도가 예상대로 작동하지 않는 이유를 고려하십시오.

 var a = [1,2]; var b = a; a = []; console.log(b); // [1,2] // doesn't work because `b` is still pointing at the original array



geg

함수 외부의 객체는 외부 객체에 대한 참조를 제공하여 함수로 전달됩니다.

해당 참조를 사용하여 개체를 조작하면 외부 개체가 영향을 받습니다. 그러나 함수 내부에서 참조를 다른 것으로 지정하기로 결정한 경우에는 참조를 다른 것으로 리디렉션하기만 하면 외부 개체에 전혀 영향을 미치지 않습니다.


user779764

다음과 같이 생각하십시오. 항상 가치에 의해 전달됩니다. 그러나 개체의 값은 개체 자체가 아니라 해당 개체에 대한 참조입니다.

다음은 숫자(기본 유형)를 전달하는 예입니다.

 function changePrimitive(val) { // At this point there are two '10's in memory. // Changing one won't affect the other val = val * 10; } var x = 10; changePrimitive(x); // x === 10

이것을 객체로 반복하면 다른 결과가 나타납니다.

 function changeObject(obj) { // At this point there are two references (x and obj) in memory, // but these both point to the same object. // changing the object will change the underlying object that // x and obj both hold a reference to. obj.val = obj.val * 10; } var x = { val: 10 }; changeObject(x); // x === { val: 100 }

한 가지 더 예:

 function changeObject(obj) { // Again there are two references (x and obj) in memory, // these both point to the same object. // now we create a completely new object and assign it. // obj's reference now points to the new object. // x's reference doesn't change. obj = { val: 100 }; } var x = { val: 10 }; changeObject(x); // x === { val: 10}

Phil Mander

값 및 참조에 의한 복사, 전달 및 비교에 대한 매우 자세한 설명은 "JavaScript: Definitive Guide" 책의 이 장 에 있습니다.

객체와 배열을 참조로 조작하는 주제를 떠나기 전에 명명법을 정리할 필요가 있습니다.

"참조로 전달"이라는 문구는 여러 의미를 가질 수 있습니다. 일부 독자에게 이 문구는 함수가 인수에 새 값을 할당하고 수정된 값을 함수 외부에서 볼 수 있도록 하는 함수 호출 기술을 나타냅니다. 이 책에서는 이 용어를 사용하지 않습니다.

여기서 우리는 단순히 객체 자체가 아닌 객체 또는 배열에 대한 참조가 함수에 전달된다는 것을 의미합니다. 함수는 참조를 사용하여 객체의 속성이나 배열의 요소를 수정할 수 있습니다. 그러나 함수가 참조를 새 개체 또는 배열에 대한 참조로 덮어쓰는 경우 해당 수정 사항은 함수 외부에서 볼 수 없습니다.

이 용어의 다른 의미에 익숙한 독자는 개체와 배열이 값으로 전달된다고 말하는 것을 선호할 수 있지만 전달되는 값은 실제로 개체 자체가 아니라 참조입니다.


igor

JavaScript는 항상 값으로 전달됩니다 . 모든 것이 값 유형입니다.

객체는 값이고 객체의 멤버 함수는 값 자체입니다(함수는 JavaScript에서 일급 객체임을 기억하십시오). 또한 JavaScript의 모든 것이 객체 라는 개념과 관련하여 ; 이것은 잘못된 것입니다. 문자열, 기호, 숫자, 부울, null 및 undefined는 기본 요소 입니다.

경우에 따라 기본 프로토타입에서 상속된 일부 멤버 함수와 속성을 활용할 수 있지만 이는 편의를 위한 것일 뿐입니다. 그것들이 객체 그 자체라는 의미는 아닙니다. 참조를 위해 다음을 시도하십시오.

 x = "test"; console.log(x.foo); x.foo = 12; console.log(x.foo);

console.log undefined 값을 찾을 수 있습니다.


Michael Roberts

JavaScript에서 값의 유형은 해당 값이 value-copy 또는 reference-copy에 의해 할당되는지 여부를 단독으로 제어합니다.

기본 값은 항상 value-copy에 의해 할당/전달됩니다 .

  • null
  • undefined
  • 숫자
  • 부울
  • ES6 기호

복합 값은 항상 reference-copy에 의해 할당/전달됩니다.

  • 사물
  • 배열
  • 기능

예를 들어

 var a = 2; var b = a; // `b` is always a copy of the value in `a` b++; a; // 2 b; // 3 var c = [1,2,3]; var d = c; // `d` is a reference to the shared `[1,2,3]` value d.push( 4 ); c; // [1,2,3,4] d; // [1,2,3,4]

위의 스니펫에서 2 는 스칼라 프리미티브이므로 a 는 해당 값의 초기 사본 하나를 보유하고 b 에는 값의 다른 사본이 할당됩니다. 변경하는 경우 b , 당신은의 값 변경 어떠한 방식에 a .

그러나 cd 는 모두 복합 값인 [1,2,3] 대한 별도의 참조입니다. cd [1,2,3] 값을 "소유"하지 않는다는 점에 유의하는 것이 중요합니다. 둘 다 값에 대한 동일한 피어 참조일 뿐입니다. 따라서 실제 공유 array 값 자체를 수정하기 위해 두 참조( .push(4) ) 중 하나를 사용할 때 하나의 공유 값에만 영향을 미치고 두 참조 모두 새로 수정된 값 [1,2,3,4] 참조합니다.

 var a = [1,2,3]; var b = a; a; // [1,2,3] b; // [1,2,3] // later b = [4,5,6]; a; // [1,2,3] b; // [4,5,6]

우리는 할당 할 때 b = [4,5,6] , 우리가 어디에 영향을 절대적으로 아무것도하지 않고 있습니다 a 여전히 참조하고 ( [1,2,3] ). 이를 위해, b 포인터가 될 것 오히려에 대한 참조 이상의 a array - 그러나 이러한 기능은 JS에 존재하지 않는다!

 function foo(x) { x.push( 4 ); x; // [1,2,3,4] // later x = [4,5,6]; x.push( 7 ); x; // [4,5,6,7] } var a = [1,2,3]; foo( a ); a; // [1,2,3,4] not [4,5,6,7]

우리가 인수에 전달하면 , 그것의 사본을 할당 을 참조 a a x . xa 동일한 가리키는 별도 참조로 [1,2,3] 값. 이제 함수 내에서 해당 참조를 사용하여 값 자체를 변경할 수 있습니다( push(4) ). x = [4,5,6] 할당을 할 때 a 가 가리키는 위치에 영향을 미치지 않습니다. 여전히 (현재 수정된) [1,2,3,4] 값을 가리킵니다.

값 복사로 복합 값(예: array )을 효과적으로 전달하려면 전달된 참조가 원본을 가리키지 않도록 수동으로 복사본을 만들어야 합니다. 예를 들어:

 foo( a.slice() );

reference-copy로 전달할 수 있는 복합 값(객체, 배열 등)

 function foo(wrapper) { wrapper.a = 42; } var obj = { a: 2 }; foo( obj ); obj.a; // 42

여기에서 obj 는 스칼라 기본 속성 a 대한 래퍼 역할을 합니다. foo(..) obj 참조의 복사본이 전달되고 wrapper 매개변수로 설정됩니다. 이제 wrapper 참조를 사용하여 공유 개체에 액세스하고 해당 속성을 업데이트할 수 있습니다. 함수가 완료된 후 obj.a 는 업데이트된 값 42 볼 것입니다.

원천


zangw

글쎄요, 그것은 '성능'과 '속도' 그리고 프로그래밍 언어의 '메모리 관리'라는 간단한 단어에 관한 것입니다.

자바 스크립트에서 우리는 두 개의 레이어에 값을 넣을 수 있습니다. type1 - objectstype2 stringboolean 등과 같은 다른 모든 유형의 값

메모리를 아래 사각형으로 상상하면 각 사각형에서 하나의 type2 값만 저장할 수 있습니다.

여기에 이미지 설명 입력

모든 type2-value(녹색)는 단일 정사각형이고 type1-value(파란색)는 이들의 그룹입니다 .

여기에 이미지 설명 입력

요점은 type2-value를 나타내려면 주소가 단순하지만 type1-value에 대해 동일한 작업을 수행하려는 경우 전혀 쉽지 않다는 것입니다! :

여기에 이미지 설명 입력

더 복잡한 이야기에서 :

여기에 이미지 설명 입력

여기 참조 가 우리를 구할 수 있습니다. 여기에 이미지 설명 입력

여기서 녹색 화살표는 일반 변수이고 보라색 화살표는 객체 변수이므로 녹색 화살표(전형 변수)에는 하나의 작업 (그리고 이는 일반 값을 나타냄)이 있기 때문에 해당 값을 다음과 분리할 필요가 없습니다. 그래서 우리는 그것이 가는 곳마다 그리고 모든 할당, 기능 등에서 그 값을 가진 녹색 화살표를 움직입니다 ...

하지만 보라색 화살표로 같은 작업을 수행할 수 없습니다. 여기에서 'john' 셀을 이동하거나 다른 많은 작업을 수행할 수 있습니다. 따라서 보라색 화살표가 제자리에 고정되고 할당된 일반적인 화살표만 이동합니다. ...

매우 혼란스러운 상황은 참조된 변수가 어떻게 변경되는지 인식할 수 없는 경우입니다. 아주 좋은 예를 살펴보겠습니다.

 let arr = [1, 2, 3, 4, 5]; //arr is an object now and a purple arrow is indicating it let obj2 = arr; // now, obj2 is another purple arrow that is indicating the value of arr obj let obj3 = ['a', 'b', 'c']; obj2.push(6); // first pic below - making a new hand for the blue circle to point the 6 //obj2 = [1, 2, 3, 4, 5, 6] //arr = [1, 2, 3, 4, 5, 6] //we changed the blue circle object value (type1-value) and due to arr and obj2 are indicating that so both of them changed obj2 = obj3; //next pic below - changing the direction of obj2 array from blue circle to orange circle so obj2 is no more [1,2,3,4,5,6] and it's no more about changing anything in it but we completely changed its direction and now obj2 is pointing to obj3 //obj2 = ['a', 'b', 'c']; //obj3 = ['a', 'b', 'c'];

여기에 이미지 설명 입력 여기에 이미지 설명 입력


kia nasirzadeh

이것은 값에 의한 전달과 참조에 의한 전달(JavaScript)에 대한 설명입니다. 이 개념에서 그들은 참조로 변수를 전달하고 참조로 변수를 전달하는 것에 대해 이야기하고 있습니다.

값으로 전달(기본 유형)

 var a = 3; var b = a; console.log(a); // a = 3 console.log(b); // b = 3 a=4; console.log(a); // a = 4 console.log(b); // b = 3
  • JavaScript의 모든 기본 유형(문자열, 숫자, 부울, 정의되지 않음 및 null)에 적용됩니다.
  • a에는 메모리가 할당되고(예: 0x001) b는 메모리에 값의 복사본을 만듭니다(예: 0x002).
  • 따라서 변수 값을 변경해도 두 변수는 서로 다른 두 위치에 있으므로 다른 변수에 영향을 주지 않습니다.

참조로 전달(객체)

 var c = { "name" : "john" }; var d = c; console.log(c); // { "name" : "john" } console.log(d); // { "name" : "john" } c.name = "doe"; console.log(c); // { "name" : "doe" } console.log(d); // { "name" : "doe" }
  • JavaScript 엔진은 객체를 변수 c 할당하고 일부 메모리(예: (0x012))를 가리킵니다.
  • d=c일 때 이 단계에서 d 는 동일한 위치(0x012)를 가리킵니다.
  • 값을 변경하면 두 변수 모두 값이 변경됩니다.
  • 함수는 객체다

특별한 경우, 참조로 전달(객체)

 c = {"name" : "jane"}; console.log(c); // { "name" : "jane" } console.log(d); // { "name" : "doe" }
  • equal(=) 연산자는 새 메모리 공간 또는 주소를 설정합니다.

Ashish Singh Rawat

JavaScript에서 참조에 대해 알고 있는 정보 공유

JavaScript에서 객체를 변수에 할당할 때 변수에 할당된 값은 객체에 대한 참조입니다.

 var a = { a: 1, b: 2, c: 3 }; var b = a; // bc is referencing to ac value console.log(bc) // Output: 3 // Changing value of bc bc = 4 // Also changes the value of ac console.log(ac) // Output: 4


xameeramir

의미론!! 구체적인 정의를 설정하면 같은 단어와 구문을 사용해도 같은 내용을 설명하지 않기 때문에 일부 답변과 설명이 호환되지 않을 수 있지만 혼란을 극복하는 것이 중요합니다(특히 새 프로그래머의 경우).

우선, 모든 사람이 이해하지 못하는 것처럼 보이는 여러 수준의 추상화가 있습니다. 4세대 또는 5세대 언어를 배운 새로운 프로그래머는 어셈블리나 C 프로그래머에 대해 포인터에 대한 포인터에 대한 포인터로 단계별로 설명하지 않은 개념을 이해하는 데 어려움을 겪을 수 있습니다. 참조에 의한 전달은 단순히 함수 매개변수 변수를 사용하여 참조된 개체를 변경하는 기능을 의미하지 않습니다.

변수 : 메모리의 특정 위치에 있는 값을 참조하는 기호의 결합된 개념입니다. 이 용어는 일반적으로 세부 사항을 논의할 때 단독으로 사용하기에는 너무 많습니다.

기호 : 변수를 참조하는 데 사용되는 문자열입니다(예: 변수 이름).

: 메모리에 저장되고 변수의 기호를 사용하여 참조되는 특정 비트.

메모리 위치 : 변수의 값이 저장되는 곳. (위치 자체는 해당 위치에 저장된 값과 별도의 숫자로 표시됩니다.)

함수 매개변수 : 함수 정의에 선언된 변수로, 함수에 전달된 변수를 참조하는 데 사용됩니다.

함수 인수 : 호출자가 함수에 전달하는 함수 외부의 변수입니다.

개체 변수 : 기본 기본 값이 "개체" 자체가 아니라 그 값이 개체의 실제 데이터가 저장된 메모리의 다른 위치에 대한 포인터(메모리 위치 값)인 변수입니다. 대부분의 상위 세대 언어에서 "포인터" 측면은 다양한 컨텍스트에서 자동 역참조에 의해 효과적으로 숨겨집니다.

기본 변수 : 값이 실제 값인 변수입니다. 이 개념조차도 다양한 언어의 자동 박싱 및 객체와 같은 컨텍스트로 인해 복잡할 수 있지만 일반적인 아이디어는 변수의 값이 다른 메모리 위치에 대한 포인터가 아니라 변수의 기호로 표시되는 실제 값이라는 것입니다.

함수 인수와 매개변수는 같은 것이 아닙니다. 또한 변수의 값은 변수의 객체가 아닙니다(여러 사람들이 이미 지적했지만 분명히 무시됨). 이러한 구분은 적절한 이해에 매우 중요합니다.

값에 의한 전달 또는 공유에 의한 호출(객체의 경우) : 함수 인수의 값은 함수의 매개변수 기호가 참조하는 다른 메모리 위치에 복사됩니다(스택에 있는지 힙에 있는지에 관계없이). 다시 말해서, 함수 매개변수는 전달된 인수 값의 사본을 수신했습니다... AND (중요) 인수 값은 호출 함수에 의해 업데이트/변경/변경되지 않습니다. 객체 변수의 값은 객체 자체가 아니라 객체에 대한 포인터이므로 객체 변수를 값으로 전달하면 함수 매개변수 변수에 대한 포인터가 복사됩니다. 함수 매개변수의 값은 메모리에서 정확히 동일한 객체를 가리킵니다. 객체 데이터 자체는 함수 매개변수를 통해 직접 변경할 수 있지만 함수 인수의 값은 절대 업데이트되지 않습니다. 따라서 함수 호출 전체와 후에도 계속 동일한 객체를 가리킬 것입니다(객체의 데이터가 변경되거나 함수 매개변수는 완전히 다른 객체에 할당됩니다). 참조된 객체가 함수 매개변수 변수를 통해 업데이트될 수 있다는 이유만으로 함수 인수가 참조로 전달되었다고 결론짓는 것은 올바르지 않습니다.

호출/참조에 의한 전달: 함수 인수의 값은 해당 함수 매개변수에 의해 직접 업데이트될 수 있습니다. 도움이 된다면 함수 매개변수는 인수에 대한 효과적인 "별칭"이 됩니다. 즉, 동일한 메모리 위치에서 동일한 값을 효과적으로 참조합니다. 함수 인수가 객체 변수인 경우 함수 매개변수가 여전히 인수와 동일한 객체를 가리키기 때문에 객체의 데이터를 변경하는 기능은 값으로 전달하는 경우와 다르지 않습니다. 그러나 객체 변수의 경우 함수 매개변수가 완전히 다른 객체로 설정되면 인수도 마찬가지로 다른 객체를 가리킵니다. 이는 값에 의한 전달의 경우에는 발생하지 않습니다.

JavaScript는 참조로 전달되지 않습니다. 자세히 읽어보면 반대 의견이 모두 값에 의한 전달이 의미하는 바를 잘못 이해하고 있으며 함수 매개변수를 통해 객체의 데이터를 업데이트하는 기능이 "값에 의한 전달"과 동의어라는 잘못된 결론을 내린다는 것을 알게 될 것입니다.

객체 복제/복사 : 새로운 객체를 생성하고 원본 객체의 데이터를 복사합니다. 이것은 깊은 복사 또는 얕은 복사일 수 있지만 요점은 새 개체가 생성된다는 것입니다. 개체의 복사본을 만드는 것은 값으로 전달하는 것과는 별개의 개념입니다. 일부 언어는 클래스 객체와 구조체(또는 이와 유사한 것)를 구별하며 다른 유형의 변수를 전달하기 위해 다른 동작을 가질 수 있습니다. 그러나 JavaScript는 객체 변수를 전달할 때 이와 같은 작업을 자동으로 수행하지 않습니다. 그러나 자동 개체 복제가 없다고 해서 참조로 전달되는 것은 아닙니다.


C Perkins

JavaScript는 기본 유형을 값으로 전달하고 객체 유형을 참조로 전달합니다.

이제 사람들은 "참조에 의한 전달"이 Java et al. 실제로 합니다. 요점은 이렇습니다.

  1. 개체를 전달해도 개체가 복사되지 않습니다.
  2. 함수에 전달된 개체의 멤버는 함수에 의해 수정될 수 있습니다.
  3. 함수에 전달된 기본 값은 함수에서 수정할 수 없습니다. 복사본이 만들어집니다.

내 책에서 참조로 전달이라고합니다.

Brian Bi - 참조로 전달되는 프로그래밍 언어는 무엇입니까?


업데이트

이에 대한 반박은 다음과 같다.

JavaScript에서 사용할 수 있는 "참조에 의한 전달"은 없습니다.


georgeawg

관찰: 관찰자가 엔진의 기본 메모리를 검사할 방법이 없는 경우 변경할 수 없는 값이 복사되는지 또는 참조가 전달되는지 여부를 결정할 방법이 없습니다.

JavaScript는 기본 메모리 모델에 대해 어느 정도 불가지론적입니다. 참조 ²와 같은 것은 없습니다. JavaScript에는 이 있습니다. 두 개의 변수가 동일한 값을 보유할 수 있습니다(또는 더 정확하게: 두 개의 환경 레코드 가 동일한 값을 바인딩 할 수 있음). 변경할 수 있는 유일한 값 유형은 추상 [[Get]] 및 [[Set]] 작업을 통한 개체입니다. 컴퓨터와 메모리를 잊어버린 경우 JavaScript의 동작을 설명하는 데 필요한 것은 이것뿐이며 사양을 이해할 수 있습니다.

 let a = { prop: 1 }; let b = a; // a and b hold the same value a.prop = "test"; // The object gets mutated, can be observed through both a and b b = { prop: 2 }; // b holds now a different value

이제 컴퓨터에서 두 변수가 동일한 값을 유지할 수 있는 방법을 스스로에게 물어볼 수 있습니다. 그런 다음 JavaScript 엔진의 소스 코드를 살펴보면 엔진이 작성된 언어의 프로그래머가 참조라고 부르는 것을 찾을 수 있습니다.

따라서 실제로 JavaScript는 "값에 의한 전달"이라고 말할 수 있지만 값은 공유될 수 있으며 JavaScript는 "참조에 의한 전달"이라고 말할 수 있습니다. 이는 저수준 언어의 프로그래머에게 유용한 논리적 추상화일 수 있습니다. 행동을 "공유에 의한 호출"이라고 부를 수 있습니다.

JavaScript에는 참조라는 것이 없기 때문에 이 모든 것이 틀리지도 않고 요점도 아닙니다. 따라서 답변이 검색에 특히 유용하다고 생각하지 않습니다.

² 사양에서 참조 라는 용어는 전통적인 의미의 참조가 아닙니다. 객체의 컨테이너이자 속성의 이름이며 중간 값입니다(예: abReference { value = a, name = "b" } 평가됨). 참조 라는 용어는 때때로 관련 없는 섹션의 사양에 나타납니다.


Jonas Wilms

이것을 이해하는 나의 간단한 방법은 ...

  • 함수를 호출할 때 변수 자체가 아니라 인수 변수의 내용(참조 또는 값)을 전달하는 것입니다.

     var var1 = 13; var var2 = { prop: 2 }; //13 and var2's content (reference) are being passed here foo(var1, var2);
  • 함수 내에서 매개변수 변수 inVar1inVar2 는 전달되는 내용을 수신합니다.

     function foo(inVar1, inVar2){ //changing contents of inVar1 and inVar2 won't affect variables outside inVar1 = 20; inVar2 = { prop: 7 }; }
  • inVar2 { prop: 2 } 참조를 받았으므로 객체의 속성 값을 변경할 수 있습니다.

     function foo(inVar1, inVar2){ inVar2.prop = 7; }

dpp

JavaScript에서 함수에 인수를 전달하는 것은 C에서 포인터 값으로 매개변수를 전달하는 것과 유사합니다.

 /* The following C program demonstrates how arguments to JavaScript functions are passed in a way analogous to pass-by-pointer-value in C. The original JavaScript test case by @Shog9 follows with the translation of the code into C. This should make things clear to those transitioning from C to JavaScript. function changeStuff(num, obj1, obj2) { num = num * 10; obj1.item = "changed"; obj2 = {item: "changed"}; } var num = 10; var obj1 = {item: "unchanged"}; var obj2 = {item: "unchanged"}; changeStuff(num, obj1, obj2); console.log(num); console.log(obj1.item); console.log(obj2.item); This produces the output: 10 changed unchanged */ #include <stdio.h> #include <stdlib.h> struct obj { char *item; }; void changeStuff(int *num, struct obj *obj1, struct obj *obj2) { // make pointer point to a new memory location // holding the new integer value int *old_num = num; num = malloc(sizeof(int)); *num = *old_num * 10; // make property of structure pointed to by pointer // point to the new value obj1->item = "changed"; // make pointer point to a new memory location // holding the new structure value obj2 = malloc(sizeof(struct obj)); obj2->item = "changed"; free(num); // end of scope free(obj2); // end of scope } int num = 10; struct obj obj1 = { "unchanged" }; struct obj obj2 = { "unchanged" }; int main() { // pass pointers by value: the pointers // will be copied into the argument list // of the called function and the copied // pointers will point to the same values // as the original pointers changeStuff(&num, &obj1, &obj2); printf("%d\n", num); puts(obj1.item); puts(obj2.item); return 0; }

John Sonderson

프로그래밍 언어 변호사의 경우 ECMAScript 5.1(최신 버전보다 읽기 쉽습니다)의 다음 섹션을 살펴보고 ECMAScript 메일링 리스트에 요청하기까지 했습니다.

TL;DR : 모든 것은 값으로 전달되지만 Objects의 속성은 참조이며 표준에서는 Object 정의가 소름 끼치게 부족합니다.

인수 목록의 구성

섹션 11.2.4 "인수 목록"은 단 하나의 인수로 구성된 인수 목록 생성에 대해 다음과 같이 설명합니다.

프로덕션 ArgumentList : AssignmentExpression은 다음과 같이 평가됩니다.

  1. ref를 AssignmentExpression을 평가한 결과라고 하자.
  2. arg를 GetValue(ref)라고 합니다.
  3. 유일한 항목이 arg인 목록을 반환합니다.

이 섹션은 인수 목록에 0 또는 >1 인수가 있는 경우도 열거합니다.

따라서 모든 것이 참조로 전달됩니다.

개체 속성 액세스

섹션 11.2.1 "속성 접근자"

프로덕션 MemberExpression : MemberExpression [ 표현식 ]은 다음과 같이 평가됩니다.

  1. baseReference를 MemberExpression을 평가한 결과로 둡니다.
  2. baseValue를 GetValue(baseReference)로 설정합니다.
  3. propertyNameReference를 Expression 평가 결과로 둡니다.
  4. propertyNameValue를 GetValue(propertyNameReference)로 설정합니다.
  5. CheckObjectCoercible(baseValue)을 호출합니다.
  6. propertyNameString을 ToString(propertyNameValue)으로 설정합니다.
  7. 평가되는 구문 생성이 엄격 모드 코드에 포함되어 있으면 strict를 true로 설정하고, 그렇지 않으면 strict를 false로 설정합니다.
  8. 기본 값이 baseValue이고 참조된 이름이 propertyNameString이고 엄격 모드 플래그가 strict인 Reference 유형의 값을 반환합니다.

따라서 개체의 속성은 항상 참조로 사용할 수 있습니다.

참고로

섹션 8.7 "참조 사양 유형"에 설명되어 있습니다. 참조는 언어의 실제 유형이 아닙니다. 삭제, 유형 및 할당 연산자의 동작을 설명하는 데만 사용됩니다.

"객체"의 정의

5.1 버전에서는 "객체는 속성 모음"으로 정의되어 있습니다. 따라서 개체의 값이 컬렉션이라고 유추할 수 있지만 컬렉션의 값이 무엇인지에 대해서는 사양에 제대로 정의되어 있지 않고 이해 하는 데 약간의 노력이 필요합니다.


DannyNiu

MDN 문서는 너무 장황하지 않고 명확하게 설명합니다.

함수 호출의 매개변수는 함수의 인수 입니다. 인수는 으로 함수에 전달됩니다. 함수가 인수 값을 변경하는 경우 이 변경 사항은 전역적으로 또는 호출하는 함수에 반영되지 않습니다. 그러나 객체 참조도 값이며 특별합니다. 함수가 참조된 객체의 속성을 변경하면 해당 변경 사항은 함수 외부에서 볼 수 있습니다. (...)

출처: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions#Description


miguelr

내가 찾은 가장 간결한 설명은 AirBNB 스타일 가이드에 있습니다 .

  • 프리미티브 : 프리미티브 유형에 액세스하면 해당 값에 대해 직접 작업합니다.

    • 숫자
    • 부울
    • 없는
    • 찾으시는 주소가 없습니다

예:

 var foo = 1, bar = foo; bar = 9; console.log(foo, bar); // => 1, 9
  • 복합 : 복합 유형에 액세스할 때 해당 값에 대한 참조 작업을 수행합니다.

    • 물체
    • 정렬
    • 기능

예:

 var foo = [1, 2], bar = foo; bar[0] = 9; console.log(foo[0], bar[0]); // => 9, 9

즉, 기본 유형은 값으로 전달되고 복합 유형은 참조로 전달됩니다.


lid

이 답변을 여러 번 읽었지만 Barbara Liskov가 말한 "공유를 통한 통화" 의 기술적 정의에 대해 배울 때까지 실제로 이해하지 못했습니다.

공유에 의한 호출의 의미는 함수 내에서 함수 인수에 대한 할당이 호출자에게 표시되지 않는다는 점에서 참조에 의한 호출과 다릅니다. 호출자의 범위에서 해당 변수에 대한 할당을 시뮬레이션합니다. 그러나 함수는 호출자와 동일한 객체에 액세스할 수 있기 때문에(복사본이 생성되지 않음) 해당 객체에 대한 돌연변이는 객체가 변경 가능한 경우 함수 내에서 호출자가 볼 수 있으며 이는 값에 의한 호출과 다르게 나타날 수 있습니다. 의미론. 함수 내에서 변경 가능한 객체의 돌연변이는 객체가 복사되거나 복제되지 않고 공유되기 때문에 호출자에게 표시됩니다.

즉, 매개변수 값 자체에 액세스하여 매개변수 참조를 변경할 수 있습니다. 반면에 매개변수에 대한 할당은 평가 후에 사라지고 함수 호출자가 액세스할 수 없습니다.


steviesh

저수준 언어에서 참조로 변수를 전달하려면 함수 생성 시 특정 구문을 사용해야 합니다.

 int myAge = 14; increaseAgeByRef(myAge); function increaseAgeByRef(int &age) { *age = *age + 1; }

&age myAge 대한 참조 *age 사용하여 참조를 변환해야 합니다.

JavaScript는 이러한 변환을 수행하는 고급 언어입니다.

따라서 개체가 참조로 전달되더라도 언어는 참조 매개변수를 값으로 변환합니다. 참조로 전달하기 위해 함수 정의에서 & 를 사용할 필요가 없으며 참조를 값으로 변환하기 위해 함수 본문에서 *

그렇기 때문에 함수 내부의 객체를 변경하려고 할 때 값(예: age = {value:5} )을 바꾸면 변경 사항이 지속되지 않지만 속성을 변경하면(예: age.value = 5 ), 그렇습니다.

더 알아보기


Narayon

나는 Underscore.js 라이브러리 의 확장 메소드 가 수정되거나 완전히 대체될 수 있는 매개변수로 객체를 전달하고자 할 때 매우 유용하다는 것을 발견했습니다.

 function replaceOrModify(aObj) { if (modify) { aObj.setNewValue('foo'); } else { var newObj = new MyObject(); // _.extend(destination, *sources) _.extend(newObj, aObj); } }

Jack

나는 그것이 pass-by-copy라고 말하고 싶다 -

인수와 변수 객체는 함수 호출의 시작 부분에서 생성된 실행 컨텍스트 동안 생성된 객체이며 함수에 전달된 실제 값/참조는 이 인수 + 변수 객체에 저장됩니다.

간단히 말해서 기본 유형의 경우 값이 함수 호출 시작 부분에 복사되고 객체 유형의 경우 참조가 복사됩니다.


lyslim

  1. 문자열, 숫자와 같은 원시 유형 변수는 항상 값으로 전달됩니다.
  2. Array 및 Object는 이 두 조건에 따라 참조로 전달 또는 값으로 전달됩니다.

    • 새 개체 또는 배열로 해당 개체 또는 배열의 값을 변경하는 경우 값으로 전달됩니다.

      object1 = {item: "car"}; array1=[1,2,3];

    여기에서 새 객체 또는 배열을 이전 객체에 할당합니다. 이전 객체의 속성 값을 변경하지 않으므로 값으로 전달됩니다.

    • 객체 또는 배열의 속성 값을 변경하는 경우 참조로 전달됩니다.

      object1.key1= "car"; array1[0]=9;

    여기에서 이전 객체의 속성 값을 변경하고 있습니다. 새 객체 또는 배열을 이전 객체에 할당하지 않으므로 참조로 전달됩니다.

암호

 function passVar(object1, object2, number1) { object1.key1= "laptop"; object2 = { key2: "computer" }; number1 = number1 + 1; } var object1 = { key1: "car" }; var object2 = { key2: "bike" }; var number1 = 10; passVar(object1, object2, number1); console.log(object1.key1); console.log(object2.key2); console.log(number1); Output: - laptop bike 10

Mukund Kumar

여기 에 JavaScript에서 "참조로 전달"이라는 용어의 사용에 대한 몇 가지 논의가 있지만 귀하의 질문에 대답하기 위해:

객체는 구체적으로 명시할 필요 없이 참조에 의해 자동으로 전달됩니다.

(위에 언급된 기사에서.)


Jack Sleight

어떤 것이 "참조에 의한 전달"인지 여부를 결정하는 쉬운 방법은 "교환" 기능을 작성할 수 있는지 여부입니다. 예를 들어 C에서는 다음을 수행할 수 있습니다.

 void swap(int *i, int *j) { int t; t = *i; *i = *j; *j = t; }

JavaScript에서 이에 상응하는 작업을 수행할 수 없다면 "참조로 전달"이 아닙니다.


Ross

  1. 프리미티브(숫자, 부울 등)는 값으로 전달됩니다.
    • 문자열은 변경할 수 없으므로 실제로 중요하지 않습니다.
  2. 개체는 참조로 전달됩니다(참조는 값으로 전달됨).

uriz

함수 내부의 단순한 값은 함수 외부의 값을 변경하지 않는 반면(값으로 전달됨) 복잡한 값은 변경됩니다(참조로 전달됨).

 function willNotChange(x) { x = 1; } var x = 1000; willNotChange(x); document.write('After function call, x = ' + x + '<br>'); // Still 1000 function willChange(y) { y.num = 2; } var y = {num: 2000}; willChange(y); document.write('After function call y.num = ' + y.num + '<br>'); // Now 2, not 2000

Olivera Kovacevic

출처 : http:www.stackoverflow.com/questions/518000/is-javascript-a-pass-by-reference-or-pass-by-value-language

반응형