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

Feb 06 2009

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

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

답변

1665 deworde Sep 04 2010 at 00:17

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".

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

실제적으로 이것은 매개 변수 자체를 변경하는 경우 ( num및에서와 같이 obj2) 매개 변수에 공급 된 항목에 영향을주지 않음을 의미합니다. 그러나 매개 변수 의 INTERNALS 를 변경하면 백업이 전파됩니다 (에서와 같이 obj1).

493 TimGoodman Mar 15 2011 at 23:38

항상 값으로 전달되지만 객체의 경우 변수 값이 참조입니다. 이 때문에 객체를 전달하고 해당 멤버를 변경할 때 이러한 변경 사항은 함수 외부에서 유지됩니다. 이것은 참조에 의한 통과처럼 보입니다 . 그러나 실제로 개체 변수의 값을 변경하면 변경 사항이 지속되지 않고 실제로 값에 의해 전달된다는 것을 확인할 수 있습니다.

예:

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
156 Shog9 Feb 06 2009 at 04:37

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

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

115 RayPerea Aug 04 2014 at 18:06

내 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을 변경할 수 없습니다 ... 왜 ?? 문자열 object를 변경 하지 않았기 때문 입니다. 우리가 한 것은 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'
75 geg Sep 26 2015 at 11:06

다음을 고려하세요:

  1. 변수는 메모리의 값에 대한 포인터 입니다.
  2. 변수를 다시 할당하면 해당 포인터가 새 값을 가리킬뿐입니다.
  3. 변수를 재 할당해도 동일한 객체를 가리키는 다른 변수에는 영향을주지 않습니다.

따라서 "참조 / 값에 의한 전달"을 잊어 버리십시오 . 다음과 같은 이유로 "참조 / 값에 의한 전달"에 매달리지 마십시오.

  1. 이 용어는 언어 의 동작 을 설명하는 데만 사용되며 실제 기본 구현 일 필요는 없습니다. 이러한 추상화의 결과로 적절한 설명에 필수적인 중요한 세부 정보가 손실되어 단일 용어로 실제 동작을 적절하게 설명하지 못하고 추가 정보를 제공해야하는 현재 상황이 불가피하게 발생합니다.
  2. 이러한 개념은 원래 특히 자바 스크립트를 설명하려는 의도로 정의 된 것이 아니기 때문에 혼란을 더할 때만 사용해야한다고 생각하지 않습니다.

질문에 답하려면 포인터가 전달됩니다.


// 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
24 user779764 Jun 03 2011 at 06:04

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

이 참조를 사용하여 개체를 조작하면 외부 개체가 영향을받습니다. 그러나 함수 내부에서 참조를 다른 것을 가리 키기로 결정한 경우 참조를 다른 것으로 리디렉션했기 때문에 외부의 개체에 전혀 영향을주지 않았습니다.

22 PhilMander Feb 13 2015 at 18:00

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

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

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}
20 igor May 13 2011 at 05:20

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

참조로 객체와 배열을 조작하는 주제를 떠나기 전에 명명법의 요점을 정리해야합니다.

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

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

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

18 MichaelRoberts Feb 06 2009 at 04:49

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

객체는 값이고 객체의 멤버 함수는 값 자체입니다 (함수는 JavaScript에서 일류 객체라는 점을 기억하십시오). 또한 JavaScript의 모든 것이 객체 라는 개념에 관해서는 ; 이것은 잘못되었습니다. 문자열, 기호, 숫자, 부울, 널 및 정의되지 않은 것은 기본 요소 입니다.

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

x = "test";
alert(x.foo);
x.foo = 12;
alert(x.foo);

두 경고 모두에서 정의되지 않은 값을 찾을 수 있습니다.

13 zangw Dec 30 2015 at 09:20

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

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

  • null
  • undefined
  • 번호
  • 부울
  • 기호 ES6

복합 값은 항상 참조 사본에 의해 할당 / 전달됩니다.

  • 사물
  • 배열
  • 함수

예를 들면

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.

그러나 c및 둘 다 d동일한 공유 값에 대한 별도의 참조 [1,2,3]이며 복합 값입니다. 값을 "소유" c하지도 않고 둘 다 값에 대한 동등한 피어 참조 일 뿐이 d라는 점에 유의해야 [1,2,3]합니다. 따라서 두 참조를 사용 .push(4)하여 실제 공유 array값 자체 를 수정 ( ) 하면 하나의 공유 값에만 영향을 미치며 두 참조 모두 새로 수정 된 값을 참조합니다 [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포인터가되어야 하지만 JS에는 그러한 기능이 없습니다!aarray

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() );

참조 복사로 전달할 수있는 복합 값 (객체, 배열 등)

function foo(wrapper) {
    wrapper.a = 42;
}

var obj = {
    a: 2
};

foo( obj );

obj.a; // 42

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

출처

10 kianasirzadeh Nov 14 2019 at 07:48

글쎄요, 그것은 '성능'과 '속도'에 관한 것이고 프로그래밍 언어에서 '메모리 관리'라는 단순한 단어로 표현됩니다.

: 자바 스크립트에서는 두 층의 값을 넣을 수있는 타입 1 - objectsTYPE2 같은 값 - 모든 다른 유형 stringboolean및 기타

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

모든 유형 2 값 (녹색)은 단일 정사각형이고 유형 1 값 (파란색)은 이들의 그룹입니다 .

요점은 type2 값을 표시하고 싶다면 주소는 평범하지만 type1 값에 대해 동일한 작업을 원한다면 전혀 쉽지 않습니다! :

그리고 더 복잡한 이야기에서 :

그래서 여기 참조 는 우리를 구할 수 있습니다.

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

하지만 보라색 화살표로는 똑같은 일을 할 수 없습니다. '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'];

8 AshishSinghRawat Sep 26 2018 at 00:31

이것은 값에 의한 전달과 참조에 의한 전달 (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의 모든 기본 유형에 적용됩니다 (문자열, 숫자, 부울, 정의되지 않음 및 널).
  • 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 (=) 연산자는 새 메모리 공간 또는 주소를 설정합니다.
6 ZameerAnsari Aug 10 2017 at 19:43

JavaScript에서 내가 아는 참조를 공유

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

var a = {
  a: 1,
  b: 2,
  c: 3
};
var b = a;

// b.c is referencing to a.c value
console.log(b.c) // Output: 3
// Changing value of b.c
b.c = 4
// Also changes the value of a.c
console.log(a.c) // Output: 4

4 CPerkins Dec 24 2016 at 01:43

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

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

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

기호 : 변수를 가리키는 문자열 (예 : 변수 명).

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

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

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

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

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

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

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

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

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

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

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

4 georgeawg Jul 25 2018 at 22:47

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

이제 사람들은 "참조에 의한 전달"이 Java 등을 설명하는 올바른 방법인지에 대해 끝없이 논쟁을 벌이고 있습니다. 실제로합니다. 요점은 다음과 같습니다.

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

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

- 브라이언 바이은 - 프로그래밍 어떤 언어 참조에 의해 전달된다?


최신 정보

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

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

3 dpp Sep 16 2014 at 16:19

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

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

    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; 
    }
    
3 JohnSonderson Nov 01 2014 at 19:43

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;
}
3 DannyNiu Jul 28 2017 at 20:17

언어 변호사 프로그래밍, 나는의 한은 (최신 버전을보다 쉽게 읽을 수) 인 ECMAScript 5.1의 다음 섹션을 통해 가서만큼 멀리 갈 묻는 ECMA 스크립트의 메일 링리스트에 있습니다.

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

인수 목록 구성

섹션 11.2.4 "인수 목록"은 단 하나의 인수로만 구성된 인수 목록을 생성 할 때 다음과 같이 말합니다.

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

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

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

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

개체 속성 액세스

섹션 11.2.1 "속성 접근 자"

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

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

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

참조에

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

"개체"의 정의

5.1 버전에서 "객체는 속성의 모음"으로 정의되어 있습니다. 따라서 우리는 객체의 가치가 컬렉션이라고 추론 할 수 있지만 컬렉션의 가치는 사양에 잘못 정의되어 있으며 이해 하는 데 약간의 노력 이 필요합니다 .

3 miguelr Apr 20 2019 at 13:06

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

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

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

2 JonasWilms Jul 26 2020 at 22:32

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

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는 "참조에 의한 전달"이라고 말할 수 있습니다. 이는 저수준 언어의 프로그래머에게 유용한 논리적 추상화가 될 수 있습니다. 행동을 "공유하여 전화"라고 부를 수 있습니다. 자바 스크립트에는 참조와 같은 것이 없기 때문에이 모든 것이 잘못되거나 정확한 것이 아닙니다. 따라서 나는 그 대답이 검색에 특히 유용하다고 생각하지 않습니다.

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

1 lid May 17 2014 at 08:01

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

  • Primitives : 기본 유형에 액세스하면 해당 값에 대해 직접 작업합니다.

    • 번호
    • 부울
    • 없는
    • 찾으시는 주소가 없습니다

예 :

var foo = 1,
    bar = foo;

bar = 9;

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

    • 목적
    • 정렬
    • 함수

예 :

var foo = [1, 2],
    bar = foo;

bar[0] = 9;

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

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

1 steviejay Oct 29 2016 at 21:50

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

공유에 의한 호출의 의미는 함수 내의 함수 인수에 대한 할당이 호출자에게 표시되지 않는다는 점에서 참조에 의한 호출과 다릅니다 (참조 의미와 달리) [인용 필요]. 예를 들어 변수가 전달 된 경우에는 불가능합니다. 호출자의 범위에서 해당 변수에 대한 할당을 시뮬레이션합니다. 그러나 함수가 호출자와 동일한 객체에 액세스 할 수 있기 때문에 (복사되지 않음) 해당 객체에 대한 변형이 객체가 변경 가능한 경우 함수 내에서 호출자가 볼 수 있으며 이는 값별 호출과 다른 것처럼 보일 수 있습니다. 의미론. 함수 내에서 변경 가능한 객체의 변형은 객체가 복사되거나 복제되지 않고 공유되기 때문에 호출자에게 표시됩니다.

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

1 Narayon Oct 19 2016 at 19:07

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

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

&age에 대한 참조입니다 myAge,하지만 당신은 값을 원하는 경우 사용하여 참조를 변환해야합니다 *age.

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

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

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

더 알아보기