BFT*_*ick 269 javascript variables pass-by-reference
如何在JS中通过引用传递变量?我有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
Run Code Online (Sandbox Code Playgroud)
做这个的最好方式是什么?
Poi*_*nty 392
JavaScript中没有"通过引用传递".您可以传递一个对象(也就是说,您可以按值传递对对象的引用),然后让函数修改对象内容:
function alterObject(obj) {
obj.foo = "goodbye";
}
var myObj = { foo: "hello world" };
alterObject(myObj);
alert(myObj.foo); // "goodbye" instead of "hello world"
Run Code Online (Sandbox Code Playgroud)
现在,就你而言,就我所知,你还没有传递任何东西.您可以使用数字索引迭代数组的属性,并根据需要修改数组的每个单元格.
值得注意的是,"传递参考"是一个非常具体的术语.它并不仅仅意味着可以将引用传递给可修改的对象.相反,它意味着可以以允许函数在调用上下文中修改该值的方式传递一个简单变量.所以:
var arr = [1, 2, 3];
for (var i = 0; i < arr.length; i++) {
arr[i] = arr[i] + 1;
}
Run Code Online (Sandbox Code Playgroud)
在像C++语言,有可能这样做,因为这种语言做(排序的)有传址引用.
编辑 - 最近(2015年3月)再次通过类似于我下面提到的博客帖子在Reddit上爆炸,尽管在这种情况下是关于Java的.我在Reddit的评论中反复阅读时发现,混淆的很大一部分源于涉及"参考"一词的不幸碰撞.术语"通过引用传递"和"通过值传递"早于在编程语言中使用"对象"的概念.它根本不是关于物体的; 它是关于函数参数,特别是函数参数如何"连接"(或不连接)到调用环境.特别要注意的是,在一个真正的pass-by-reference语言中 - 一个确实涉及对象的语言 - 人们仍然可以修改对象内容,它看起来就像在JavaScript中一样.但是,也可以在调用环境中修改对象引用,这是您在JavaScript中无法做到的关键事情.传递引用语言不会传递引用本身,而是引用引用.
编辑 - 这是关于该主题的博客文章.(注意那篇文章的评论,解释说C++实际上没有传递引用.这是事实.但是,C++所具有的是能够在函数点明确地创建对纯变量的引用.调用创建指针,或者在调用参数类型为trace的函数时隐式调用.这些是JavaScript不支持的关键内容.)
Muk*_*mar 96
数组和对象通过引用或基于以下条件的值传递:
如果要设置对象或数组的值,则为"按值传递".
object1 = {prop: "car"};
array1 = [1,2,3];
如果要更改对象或数组的属性值,则它是Pass by Reference.
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: 10Run Code Online (Sandbox Code Playgroud)
小智 24
通过引用传递变量的解决方法:
var a = 1;
inc = function(variableName) {
window[variableName] += 1;
};
inc('a');
alert(a); // 2
Run Code Online (Sandbox Code Playgroud)
编辑
是的,实际上你可以在没有访问全局的情况下做到
inc = (function () {
var variableName = 0;
var init = function () {
variableName += 1;
alert(variableName);
}
return init;
})();
inc();
Run Code Online (Sandbox Code Playgroud)
Edu*_*omo 11
var ref = { value: 1 };
function Foo(x) {
x.value++;
}
Foo(ref);
Foo(ref);
alert(ref.value); // Alert: 3
Run Code Online (Sandbox Code Playgroud)
rvarfunction 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];
}
}
Run Code Online (Sandbox Code Playgroud)
rvar('test_ref');
test_ref = 5; // test_ref.value = 5
Run Code Online (Sandbox Code Playgroud)
要么:
rvar('test_ref', 5); // test_ref.value = 5
Run Code Online (Sandbox Code Playgroud)
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');
Run Code Online (Sandbox Code Playgroud)
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
Run Code Online (Sandbox Code Playgroud)
另一种通过引用传递任何(本地,原始)变量的方法是通过包装带有"动态"闭包的变量eval.这也适用于"use strict".(注意:请注意,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);
})()
Run Code Online (Sandbox Code Playgroud)
实时样本https://jsfiddle.net/t3k4403w/
我个人不喜欢各种编程语言提供的“按引用传递”功能。也许这是因为我刚刚发现函数式编程的概念,但当我看到导致副作用的函数(例如操作通过引用传递的参数)时,我总是会起鸡皮疙瘩。我个人强烈拥护“单一责任”原则。
恕我直言,函数应该使用 return 关键字仅返回一个结果/值。我不会修改参数/参数,而是返回修改后的参数/参数值,并将任何所需的重新分配留给调用代码。
但有时(希望很少),需要从同一函数返回两个或多个结果值。在这种情况下,我会选择将所有这些结果值包含在单个结构或对象中。同样,处理任何重新分配都应该由调用代码决定。
例子:
假设通过在参数列表中使用特殊关键字(如“ref”)来支持传递参数。我的代码可能看起来像这样:
//The Function
function doSomething(ref value) {
value = "Bar";
}
//The Calling Code
var value = "Foo";
doSomething(value);
console.log(value); //Bar
Run Code Online (Sandbox Code Playgroud)
相反,我实际上更愿意做这样的事情:
//The Function
function doSomething(value) {
value = "Bar";
return value;
}
//The Calling Code:
var value = "Foo";
value = doSomething(value); //Reassignment
console.log(value); //Bar
Run Code Online (Sandbox Code Playgroud)
当我需要编写一个返回多个值的函数时,我也不会使用通过引用传递的参数。所以我会避免这样的代码:
//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
Run Code Online (Sandbox Code Playgroud)
相反,我实际上更愿意在对象内返回两个新值,如下所示:
//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);
Run Code Online (Sandbox Code Playgroud)
这些代码示例非常简单,但它大致演示了我个人将如何处理此类内容。它帮助我将各种责任放在正确的位置。
快乐编码。:)
| 归档时间: |
|
| 查看次数: |
353811 次 |
| 最近记录: |