JavaScript에서 참조로 변수를 전달하는 방법은 무엇입니까? 여러 작업을 수행하려는 3 개의 변수가 있으므로 for 루프에 넣고 각 작업을 수행하려고합니다.
의사 코드 :
myArray = new Array(var1, var2, var3);
for (var x = 0; x < myArray.length; x++){
//do stuff to the array
makePretty(myArray[x]);
}
//now do stuff to the updated vars
가장 좋은 방법은 무엇입니까?
답변
JavaScript에는 “참조로 전달”이 없습니다. 객체를 전달하면 (즉, 객체에 대한 값을 기준으로 전달할 수 있음) 함수가 객체 내용을 수정하도록 할 수 있습니다.
function alterObject(obj) {
obj.foo = "goodbye";
}
var myObj = { foo: "hello world" };
alterObject(myObj);
alert(myObj.foo); // "goodbye" instead of "hello world"
숫자 인덱스를 사용하여 배열의 속성을 반복하고 원하는 경우 배열의 각 셀을 수정할 수 있습니다.
var arr = [1, 2, 3];
for (var i = 0; i < arr.length; i++) {
arr[i] = arr[i] + 1;
}
“by-by-by-reference”는 매우 구체적인 용어입니다. 단순히 수정 가능한 객체에 대한 참조를 전달할 수 있다는 의미는 아닙니다. 대신, 함수가 호출 컨텍스트 에서 해당 값을 수정할 수 있도록 간단한 변수를 전달할 수 있음을 의미합니다 . 그래서:
function swap(a, b) {
var tmp = a;
a = b;
b = tmp; //assign tmp to b
}
var x = 1, y = 2;
swap(x, y);
alert("x is " + x + ", y is " + y); // "x is 1, y is 2"
C ++과 같은 언어 에서는 언어 가 참조 기준 을 가지기 때문에 그렇게 할 수 있습니다 .
편집 -최근 (2015 년 3 월) 아래에서 언급 한 것과 유사한 블로그 게시물을 통해 Reddit을 다시 살펴 보았습니다. Reddit에서 앞뒤로 읽는 동안 혼란의 큰 부분은 “참조”라는 단어와 관련된 불행한 충돌에서 비롯된 것입니다. “참조로 전달”및 “값으로 전달”이라는 용어는 프로그래밍 언어에서 “개체”를 다루는 개념보다 우선합니다. 그것은 실제로 객체에 관한 것이 아닙니다. 함수 매개 변수, 특히 함수 매개 변수가 호출 환경에 “연결된”방법에 관한 것입니다. 특히,JavaScript에서와 똑같이 보입니다. 그러나 호출 환경에서 객체 참조를 수정할 수도 있으며 이것이 JavaScript에서 수행 할 수없는 핵심 사항입니다 . 참조 별 언어는 참조 자체가 아니라 참조에 대한 참조를 전달 합니다.
편집 – 여기 주제에 대한 블로그 게시물이 있습니다. (이 게시물에 대한 주석은 C ++에 실제로 참조를 통한 전달이 없음을 설명합니다. 사실입니다. 그러나 C ++의 기능은 함수 시점에서 명시 적으로 일반 변수에 대한 참조를 생성하는 기능입니다 포인터를 생성하기위한 호출 또는 인수 유형 서명이 수행되어야하는 함수를 호출 할 때 암시 적으로 호출합니다. JavaScript가 지원하지 않는 주요 기능입니다.)
답변
- 문자열 및 숫자와 같은 기본 유형 변수는 항상 값으로 전달됩니다.
-
배열과 객체는 다음 조건에 따라 참조 또는 값으로 전달됩니다.
-
객체 또는 배열의 값을 설정하는 경우 Pass by Value입니다.
object1 = {prop: "car"};
array1 = [1,2,3]; -
객체 또는 배열의 속성 값을 변경하는 경우 참조로 전달입니다.
object1.prop = "car";
array1[0] = 9;
-
암호
function passVar(obj1, obj2, num) {
obj1.prop = "laptop"; // will CHANGE original
obj2 = { prop: "computer" }; //will NOT affect original
num = num + 1; // will NOT affect original
}
var object1 = {
prop: "car"
};
var object2 = {
prop: "bike"
};
var number1 = 10;
passVar(object1, object2, number1);
console.log(object1); //output: Object {item:"laptop"}
console.log(object2); //output: Object {item:"bike"}
console.log(number1); //ouput: 10
답변
참조로 변수를 전달하는 해결 방법 :
var a = 1;
inc = function(variableName) {
window[variableName] += 1;
};
inc('a');
alert(a); // 2
편집하다
,, 실제로 당신은 글로벌 액세스없이 할 수 있습니다
inc = (function () {
var variableName = 0;
var init = function () {
variableName += 1;
alert(variableName);
}
return init;
})();
inc();
답변
간단한 객체
var ref = { value: 1 };
function Foo(x) {
x.value++;
}
Foo(ref);
Foo(ref);
alert(ref.value); // Alert: 3
커스텀 객체
목적 rvar
function rvar (name, value, context) {
if (this instanceof rvar) {
this.value = value;
Object.defineProperty(this, 'name', { value: name });
Object.defineProperty(this, 'hasValue', { get: function () { return this.value !== undefined; } });
if ((value !== undefined) && (value !== null))
this.constructor = value.constructor;
this.toString = function () { return this.value + ''; };
} else {
if (!rvar.refs)
rvar.refs = {};
if (!context)
context = window;
// Private
rvar.refs[name] = new rvar(name, value);
// Public
Object.defineProperty(context, name, {
get: function () { return rvar.refs[name]; },
set: function (v) { rvar.refs[name].value = v; },
configurable: true
});
return context[name];
}
}
변수 선언
rvar('test_ref');
test_ref = 5; // test_ref.value = 5
또는:
rvar('test_ref', 5); // test_ref.value = 5
테스트 코드
rvar('test_ref_number');
test_ref_number = 5;
function Fn1 (v) { v.value = 100; }
console.log("rvar('test_ref_number');");
console.log("test_ref_number = 5;");
console.log("function Fn1 (v) { v.value = 100; }");
console.log('test_ref_number.value === 5', test_ref_number.value === 5);
console.log(" ");
Fn1(test_ref_number);
console.log("Fn1(test_ref_number);");
console.log('test_ref_number.value === 100', test_ref_number.value === 100);
console.log(" ");
test_ref_number++;
console.log("test_ref_number++;");
console.log('test_ref_number.value === 101', test_ref_number.value === 101);
console.log(" ");
test_ref_number = test_ref_number - 10;
console.log("test_ref_number = test_ref_number - 10;");
console.log('test_ref_number.value === 91', test_ref_number.value === 91);
console.log(" ");
console.log("---------");
console.log(" ");
rvar('test_ref_str', 'a');
console.log("rvar('test_ref_str', 'a');");
console.log('test_ref_str.value === "a"', test_ref_str.value === 'a');
console.log(" ");
test_ref_str += 'bc';
console.log("test_ref_str += 'bc';");
console.log('test_ref_str.value === "abc"', test_ref_str.value === 'abc');
테스트 콘솔 결과
rvar('test_ref_number');
test_ref_number = 5;
function Fn1 (v) { v.value = 100; }
test_ref_number.value === 5 true
Fn1(test_ref_number);
test_ref_number.value === 100 true
test_ref_number++;
test_ref_number.value === 101 true
test_ref_number = test_ref_number - 10;
test_ref_number.value === 91 true
---------
rvar('test_ref_str', 'a');
test_ref_str.value === "a" true
test_ref_str += 'bc';
test_ref_str.value === "abc" true
답변
참조에 의해 (로컬, 프리미티브) 변수를 전달하는 또 다른 방법은 변수를 “바로”클로저로 래핑하는 것 eval
입니다. “엄격한 사용”에서도 작동합니다. (참고 : eval
JS 옵티 마이저에게는 친숙하지 않으며 변수 이름 주위에 따옴표가 없으면 예기치 않은 결과가 발생할 수 있습니다)
"use strict"
//return text that will reference variable by name (by capturing that variable to closure)
function byRef(varName){
return "({get value(){return "+varName+";}, set value(v){"+varName+"=v;}})";
}
//demo
//assign argument by reference
function modifyArgument(argRef, multiplier){
argRef.value = argRef.value * multiplier;
}
(function(){
var x = 10;
alert("x before: " + x);
modifyArgument(eval(byRef("x")), 42);
alert("x after: " + x);
})()
답변
실제로 꽤 해결책이 있습니다.
function updateArray(context, targetName, callback) {
context[targetName] = context[targetName].map(callback);
}
var myArray = ['a', 'b', 'c'];
updateArray(this, 'myArray', item => {return '_' + item});
console.log(myArray); //(3) ["_a", "_b", "_c"]
답변
다양한 프로그래밍 언어에서 제공하는 “참조로 전달”기능을 개인적으로 싫어합니다. 아마도 그것은 함수형 프로그래밍의 개념을 발견하기 때문일 수도 있지만 부작용을 일으키는 함수 (참조로 전달되는 매개 변수 조작과 같은)를 볼 때 항상 구즈 범프를 얻습니다. 나는 개인적으로 “단일 책임”원칙을 강하게 받아들입니다.
IMHO, 함수는 return 키워드를 사용하여 하나의 결과 / 값만 반환해야합니다. 매개 변수 / 인수를 수정하는 대신 수정 된 매개 변수 / 인수 값을 반환하고 원하는 재 할당을 호출 코드까지 남겨 두었습니다.
그러나 때로는 (아주 드물게) 동일한 함수에서 두 개 이상의 결과 값을 반환해야합니다. 이 경우 모든 결과 값을 단일 구조 또는 객체에 포함하도록 선택합니다. 다시 할당을 처리하는 것은 호출 코드에 달려 있습니다.
예:
인수 목록에서 ‘ref’와 같은 특수 키워드를 사용하여 전달 매개 변수를 지원한다고 가정하십시오. 내 코드는 다음과 같습니다.
//The Function
function doSomething(ref value) {
value = "Bar";
}
//The Calling Code
var value = "Foo";
doSomething(value);
console.log(value); //Bar
대신 실제로 다음과 같은 작업을 선호합니다.
//The Function
function doSomething(value) {
value = "Bar";
return value;
}
//The Calling Code:
var value = "Foo";
value = doSomething(value); //Reassignment
console.log(value); //Bar
여러 값을 반환하는 함수를 작성해야 할 때 참조로 전달 된 매개 변수도 사용하지 않습니다. 따라서 다음과 같은 코드를 피할 것입니다.
//The Function
function doSomething(ref value) {
value = "Bar";
//Do other work
var otherValue = "Something else";
return otherValue;
}
//The Calling Code
var value = "Foo";
var otherValue = doSomething(value);
console.log(value); //Bar
console.log(otherValue); //Something else
대신 실제로 객체 내부에 다음과 같이 두 가지 새로운 값을 반환하는 것을 선호합니다.
//The Function
function doSomething(value) {
value = "Bar";
//Do more work
var otherValue = "Something else";
return {
value: value,
otherValue: otherValue
};
}
//The Calling Code:
var value = "Foo";
var result = doSomething(value);
value = result.value; //Reassignment
console.log(value); //Bar
console.log(result.otherValue);
이 코드 예제는 매우 간단하지만 개인적으로 이러한 작업을 처리하는 방법을 대략적으로 보여줍니다. 올바른 장소에서 다양한 책임을 지도록 도와줍니다.
행복한 코딩. 🙂