在 JavaScript 中按引用传递变量

Pass variables by reference in JavaScript

提问人:BFTrick 提问时间:10/13/2011 最后编辑:Peter MortensenBFTrick 更新时间:11/20/2023 访问量:586863

问:

如何在 JavaScript 中通过引用传递变量?

我想对三个变量执行多个操作,因此我想将它们放在 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 variables

最好的方法是什么?

JavaScript 变量 按引用传递

评论

37赞 jfriend00 10/13/2011
您说的是“通过引用传递”,但是您的示例中没有函数调用,因此您的示例中根本没有传递。请澄清您要做什么。
1赞 BFTrick 10/17/2011
很抱歉造成混乱。我没有特别需要编写函数,所以“通过引用传递”是一个糟糕的词语选择。我只是希望能够在不写入的情况下对变量执行一些操作makePretty(var1); makePretty(var2); makePretty(var3); ...
1赞 dylnmc 5/18/2017
根据您的评论: -- 您只需要将 Back 返回的值存储到数组中的插槽中即可。arr = [var1, var2, var3]; for (var i = 0, len = arr.length; i < len; i++) { arr[i] = makePretty(arr[i]); }makePretty
1赞 Erenor Paz 12/1/2020
对于那些在 Javascript 中搜索“传递引用”或“传递值”时来自 Google 的人来说,一篇来自 Medium 的好文章是:medium.com/@TK_CodeBear/......
1赞 Patanjali 6/21/2023
@ErenorPaz。中篇文章已经走上了死鹦鹉的路!

答:

532赞 Pointy 10/13/2011 #1

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; 
}

需要注意的是,“通过引用”是一个非常具体的术语。这并不意味着可以传递对可修改对象的引用。相反,这意味着可以传递一个简单的变量,以允许函数在调用上下文中修改该值。所以:

 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 上炸开了锅,这篇博文类似于下面提到的一篇博文,尽管在这种情况下是关于 Java 的。在阅读 Reddit 评论的来回时,我突然想到,很大一部分混淆源于涉及“参考”一词的不幸碰撞。术语“按引用传递”和“按值传递”早于编程语言中具有“对象”的概念。这真的与物体无关;它是关于函数参数的,特别是函数参数如何“连接”(或不连接)到调用环境。特别要注意的是,在真正的引用传递语言中——一种确实涉及对象的语言——人们仍然能够修改对象内容,而且它看起来与在 JavaScript 中几乎完全相同。但是,人们也可以在调用环境中修改对象引用,这是您在 JavaScript 中无法做到的关键事情。引用传递语言不会传递引用本身,而是传递对引用的引用

编辑这是一篇关于该主题的博客文章。 (请注意该帖子的评论,该评论解释了 C++ 实际上没有通过引用。这是真的。然而,C++ 确实具有创建对普通变量的引用的能力,无论是在函数调用点显式创建指针,还是在调用其参数类型签名要求执行此操作的函数时隐式引用。这些是 JavaScript 不支持的关键内容。

评论

12赞 jfriend00 10/13/2011
您可以传递对对象或数组的引用,这允许您更改原始对象或数组,我相信这是 OP 实际询问的内容。
9赞 Travis Webb 12/3/2013
按值传递引用与按引用传递不同,尽管在某些情况下可能会出现这种情况。
6赞 EML 10/30/2014
你的博主对C++的看法是错误的,它确实是通过引用传递的,他的帖子没有任何意义。初始化后无法更改引用的值无关紧要;这与“通过引用传递”无关。他所说的“'通过引用传递'语义可以追溯到 C#”应该敲响警钟。
33赞 crownlessking 6/20/2017
@Pointy 这是一个可怕的答案。如果我需要帮助,我最不想要的就是有人教我语义。“按引用传递”只是意味着,“函数在某种程度上可以更改作为参数传入的变量的值。(在问题的上下文中)它真的没有你想象的那么复杂。
5赞 Artur Carvalho 3/17/2021
我是唯一一个认为“通过参考”的顶级答案是由一个叫 Pointy 的人回答的太巧合了吗?:)
30赞 user2410595 5/23/2013 #2

通过引用传递变量的解决方法:

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

评论

0赞 dkloke 3/28/2015
@Phil,注意全局/窗口值是件好事,但在某些时候,我们在浏览器中所做的一切都是窗口对象的子对象或后代。在 nodejs 中,一切都是 GLOBAL 的后代。在编译对象语言中,这是一个隐式(如果不是显式)的父对象,因为否则会使堆管理更加复杂(以及为了什么?
1赞 Phil 3/30/2015
@dkloke:是的,最终窗口对象需要被触摸 - 就像jQuery使用window.$/window.jQuery和其他方法一样。我说的是全局命名空间的污染,你向它添加了很多变量,而不是将它们放在一个统一的命名空间下。
9赞 SOReader 3/24/2016
我找不到好的词来表达这种方法有多糟糕;(
0赞 John Boe 9/7/2016
我喜欢最后一个解决方案(编辑版本),即使它没有通过引用传递变量。这是优点,因为您可以直接访问变量。
19赞 Eduardo Cuomo 2/1/2014 #3

简单对象

function foo(x) {
  // Function with other context
  // Modify `x` property, increasing the value
  x.value++;
}

// Initialize `ref` as object
var ref = {
  // The `value` is inside `ref` variable object
  // The initial value is `1`
  value: 1
};

// Call function with object value
foo(ref);
// Call function with object value again
foo(ref);

console.log(ref.value); // Prints "3"


自定义对象

对象rvar

/**
 * Aux function to create by-references variables
 */
function rvar(name, value, context) {
  // If `this` is a `rvar` instance
  if (this instanceof rvar) {
    // Inside `rvar` context...

    // Internal object value
    this.value = value;

    // Object `name` property
    Object.defineProperty(this, 'name', { value: name });

    // Object `hasValue` property
    Object.defineProperty(this, 'hasValue', {
      get: function () {
        // If the internal object value is not `undefined`
        return this.value !== undefined;
      }
    });

    // Copy value constructor for type-check
    if ((value !== undefined) && (value !== null)) {
      this.constructor = value.constructor;
    }

    // To String method
    this.toString = function () {
      // Convert the internal value to string
      return this.value + '';
    };
  } else {
    // Outside `rvar` context...

    // Initialice `rvar` object
    if (!rvar.refs) {
      rvar.refs = {};
    }

    // Initialize context if it is not defined
    if (!context) {
      context = this;
    }

    // Store variable
    rvar.refs[name] = new rvar(name, value, context);

    // Define variable at context
    Object.defineProperty(context, name, {
      // Getter
      get: function () { return rvar.refs[name]; },
      // Setter
      set: function (v) { rvar.refs[name].value = v; },
      // Can be overrided?
      configurable: true
    });

    // Return object reference
    return context[name];
  }
}

// Variable Declaration

// Declare `test_ref` variable
rvar('test_ref_1');

// Assign value `5`
test_ref_1 = 5;
// Or
test_ref_1.value = 5;

// Or declare and initialize with `5`:
rvar('test_ref_2', 5);

// ------------------------------
// Test Code

// Test Function
function Fn1(v) { v.value = 100; }

// Test
function test(fn) { console.log(fn.toString()); console.info(fn()); }

// Declare
rvar('test_ref_number');

// First assign
test_ref_number = 5;
test(() => test_ref_number.value === 5);

// Call function with reference
Fn1(test_ref_number);
test(() => test_ref_number.value === 100);

// Increase value
test_ref_number++;
test(() => test_ref_number.value === 101);

// Update value
test_ref_number = test_ref_number - 10;
test(() => test_ref_number.value === 91);

评论

0赞 Anton Shepelev 3/14/2021
你的例子似乎做出了一些你没有陈述的假设。当我在在线 JavaScript 解释器中运行它时,我收到一个错误:/workspace/Main.js:43 context = window; ReferenceError: window is not defined
1赞 Eduardo Cuomo 3/17/2021
@Ant_222代码已修复。
1赞 Anton Shepelev 3/25/2021
感谢您的修复。现在它起作用了,但我觉得投票支持你的答案是慈善的,因为我咨询的专业 JavaScript 程序员认为你的解决方案是可憎的。我自己意识到这是相当危险的,因为变量不是它们看起来的样子。尽管如此,您的解决方案无疑具有教育价值。rvar
4赞 Adam Wise 5/15/2014 #4

我一直在尝试语法来做这种事情,但它需要一些有点不寻常的帮助程序。它首先根本不使用“var”,而是一个简单的“DECLARE”帮助程序,它创建一个局部变量,并通过匿名回调为其定义一个范围。通过控制变量的声明方式,我们可以选择将它们包装到对象中,以便它们基本上始终可以通过引用传递。这与上面 Eduardo Cuomo 的答案之一类似,但下面的解决方案不需要使用字符串作为变量标识符。下面是一些展示这个概念的最小代码。

function Wrapper(val){
    this.VAL = val;
}
Wrapper.prototype.toString = function(){
    return this.VAL.toString();
}

function DECLARE(val, callback){
    var valWrapped = new Wrapper(val);    
    callback(valWrapped);
}

function INC(ref){
    if(ref && ref.hasOwnProperty('VAL')){
        ref.VAL++; 
    }
    else{
        ref++;//or maybe throw here instead?
    }

    return ref;
}

DECLARE(5, function(five){ //consider this line the same as 'let five = 5'
console.log("five is now " + five);
INC(five); // increment
console.log("five is incremented to " + five);
});

评论

0赞 Andrew 3/24/2023
这种方法的问题在于,它实际上并不等同于 ,因为它没有在外部上下文中设置变量,它只能在函数内部使用。这就是为什么你不需要使用字符串。尽管如此,还是赞成使用闭包的唯一目的是进行引用,并在该引用中存储和本地化值的新想法。不过,这可以只用一个或一个对象来完成。然后,您可以存储引用对象并将其用于更通用的用途,而不仅仅是 .为我的一个项目做这件事。let five = 5;classINC(ref)
181赞 Mukund Kumar 10/28/2014 #5
  1. 字符串和数字等基元类型变量始终按值传递。
  2. 数组和对象基于以下条件通过引用或值传递:
  • 如果要设置对象或数组的值,则为“按值传递”。

     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 { prop: "laptop" }
console.log(object2); // output: Object { prop: "bike" }
console.log(number1); // ouput: 10

评论

37赞 Pointy 3/24/2015
这不是“通过引用传递”的意思。该术语实际上与对象无关,而是与被调用函数中的参数与调用环境中的变量之间的关系有关。
19赞 Matthew Read 3/22/2017
一切都是按值传递的。对于非基元,传递的值是引用。分配给引用会更改该引用(自然会更改该引用,因为它是一个值),因此无法更改最初引用的其他对象。通过改变指向的对象,对引用所指向的对象进行变异,其行为与预期完全相同。这两种情况是完全一致的,并且都没有通过回到过去并改变它们传递到函数中的方式来神奇地改变 JavaScript 的工作方式。
19赞 Pap 10/25/2017
这个答案澄清了前一个答案,尽管它有更多的票数(在撰写本文时为 287 票,而且它也是被接受的票数),但对于如何在 JS 中通过引用实际通过它还不够清楚。简而言之,这个答案中的代码有效,而获得更多选票的答案则无效。
2赞 Rafiki 1/27/2022
这些答案确实触及了可以做什么和不能做什么来满足 OP 的需求。与其争论“通过引用传递”的含义,我认为我们都可以同意这个术语很糟糕,并希望在不久的将来创造一个更好的术语。虽然@Pointy的回答让我理解了更多的概念,但那个回答帮助我完成了工作
3赞 Yin Cognyto 8/2/2022
很好的答案。避免在语义、术语和“OP 的含义”(现在出现在一些 SO 答案中,以使它们完整并帮助寻找赞成票和所有),并给出非常明确的例子,说明哪些有效,哪些无效。在这种情况下,为什么问题和一种或另一种方式之间的语义差异就不那么重要了,因为由于 Javascript 的编写方式,您首先无法以另一种方式处理它。
2赞 user257319 5/5/2015 #6

实际上,这真的很容易。问题在于,一旦传递了经典参数,你就会被限制在另一个只读区域中。

解决方案是使用 JavaScript 的面向对象设计传递参数。这与将参数放在全局/范围变量中相同,但更好......

function action(){
  /* Process this.arg, modification allowed */
}

action.arg = [["empty-array"], "some string", 0x100, "last argument"];
action();

您还可以承诺享受知名连锁店: 这是整个事情,具有类似承诺的结构

function action(){
  /* Process this.arg, modification allowed */
  this.arg = ["a", "b"];
}

action.setArg = function(){this.arg = arguments; return this;}

action.setArg(["empty-array"], "some string", 0x100, "last argument")()

或者更好的是......

action.setArg(["empty-array"],"some string",0x100,"last argument").call()

评论

1赞 Eduardo Cuomo 3/8/2018
this.arg仅适用于实例。这是行不通的。action
0赞 Andrew 3/24/2023
@EduardoCuomo 您可以简单地使用 代替 来解决这个问题。我发现关键字是 JS 中提供功能的主要目的。classthisclass
6赞 Pavlo Mur 1/16/2017 #7

另一种通过引用传递任何(局部、原始)变量的方法是将变量包装起来,并“动态”地使用闭包。这也适用于“use strict”。(注意:请注意,这对 JavaScript 优化器不友好,并且变量名称周围缺少引号可能会导致不可预测的结果)evaleval

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

现场示例:https://jsfiddle.net/t3k4403w/

评论

0赞 Anton Shepelev 3/14/2021
好主意,但我决定不这样做,因为对于仅输出变量,传递箭头函数实际上更短,而双向输入输出参数通常不需要。请参阅我对另一种基于方法的重复问题的回答,在这种方法中,您可以传递变量名称并评估整个函数的结果。x=>value=xeval
4赞 Mateus Araújo 7/15/2017 #8

实际上有一个漂亮的解决方案:

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

评论

3赞 Peter Mortensen 10/16/2020
它以什么方式漂亮?
5赞 Bart Hofland 4/23/2018 #9

我个人不喜欢各种编程语言提供的“引用传递”功能。也许那是因为我刚刚发现函数式编程的概念,但是当我看到引起副作用的函数(例如操作引用传递的参数)时,我总是起鸡皮疙瘩。我个人强烈拥护“单一责任”原则。

恕我直言,函数应该只使用 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);

这些代码示例非常简化,但它大致演示了我个人如何处理这些东西。它帮助我将各种责任放在正确的位置。

祝您编码愉快。:)

评论

0赞 Elise van Looij 8/13/2019
分配和重新分配东西(也没有任何类型检查)让我起鸡皮疙瘩。至于责任,我希望 doSomething() 做那件事,而不是做那件事,加一个对象加号并将我的变量分配给属性。假设我有一个需要搜索的数组。我想将匹配的项目放在第二个数组中,我想知道找到了多少个。一个标准的解决方案是调用这样的函数:'var foundArray;if ((findStuff(inArray, &foundArray)) > 1) { // 处理 foundArray}'。在这种情况下,没有任何地方是可取或需要的新的、未知的对象。
0赞 Bart Hofland 8/13/2019
@ElisevanLooij 在您的示例中,我宁愿简单地返回结果数组。你也必须声明一个变量,所以我会直接将生成的数组分配给它:.这将 1) 使调用代码更具可读性/可理解性,以及 2) 大大简化方法的内部功能(从而也简化了可测试性),使其在不同的(重新)用例/场景中实际上更加灵活。findStufffoundArrayvar foundArray = findStuff(inArray); if (foundArray.length > 0) { /* process foundArray */ }findStuff
0赞 Bart Hofland 8/13/2019
@ElisevanLooij 但是,我确实同意重新分配(就像我的回答一样)确实是一种“代码味”,我实际上也希望尽可能避免这些。我会考虑编辑(甚至重新制定)我的答案,以便更好地反映我对这个问题的实际看法。感谢您的反应。:)
0赞 Andrew 3/24/2023
很好的答案。帮我解决了我需要的东西,谢谢。想要避免按字符串传递变量并传递其上下文(用于自动重新赋值),并且缺少其他显而易见的“只需在当时和那里分配它”(duh)。
0赞 funct7 5/23/2018 #10

我完全明白你的意思。在 Swift 中做同样的事情不会有问题。底线是使用,而不是。letvar

事实上,基元是按值传递的,但迭代点的值没有被复制到匿名函数中,至少可以说是相当令人惊讶的。var i

for (let i = 0; i < boxArray.length; i++) {
  boxArray[i].onclick = function() { console.log(i) }; // Correctly prints the index
}
2赞 Michiel van der Blonk 10/29/2018 #11

JavaScript 可以修改函数中的数组项(它作为对对象/数组的引用传递)。

function makeAllPretty(items) {
   for (var x = 0; x < myArray.length; x++){
      // Do stuff to the array
      items[x] = makePretty(items[x]);
   }
}

myArray = new Array(var1, var2, var3);
makeAllPretty(myArray);

下面是另一个示例:

function inc(items) {
  for (let i=0; i < items.length; i++) {
    items[i]++;
  }
}

let values = [1,2,3];
inc(values);
console.log(values);
// Prints [2,3,4]
1赞 Shira Joseph 7/15/2019 #12

撇开参考传递讨论不谈,那些仍在寻找所述问题解决方案的人可以使用:

const myArray = new Array(var1, var2, var3);
myArray.forEach(var => var = makePretty(var));

评论

3赞 Peter Mortensen 10/16/2020
解释是什么?它与其他答案有何不同/更好?
0赞 Magnus 7/27/2020 #13

我喜欢通过引用来解决 JavaScript 中缺少的问题,就像这个例子所示。

这样做的本质是你不要尝试通过引用创建一个。您可以改用返回功能,并使其能够返回多个值。因此,无需在数组或对象中插入值。

var x = "First";
var y = "Second";
var z = "Third";

log('Before call:',x,y,z);
with (myFunc(x, y, z)) {x = a; y = b; z = c;} // <-- Way to call it
log('After call :',x,y,z);


function myFunc(a, b, c) {
  a = "Changed first parameter";
  b = "Changed second parameter";
  c = "Changed third parameter";
  return {a:a, b:b, c:c}; // <-- Return multiple values
}

function log(txt,p1,p2,p3) {
  document.getElementById('msg').innerHTML += txt + '<br>' + p1 + '<br>' + p2 + '<br>' + p3 + '<br><br>'
}
<div id='msg'></div>

评论

0赞 Andrew 3/24/2023
这种方法需要大量的标识符和赋值来处理一个基本的、基本的问题,并且它没有解决人们明确需要参考来解决他们的问题的情况。一些示例包括在引用上创建新属性或从引用中删除属性,将引用传递给大量函数,更改类型或将引用完全换成其他内容等。因此,在JS世界中,这个问题的理想解决方案将涉及具有一种或另一种对象的蝇量级模式。
0赞 Andrew 3/24/2023
这里讨论了这种方法。另外,在 JS 对象中传递变量时,没有必要做 ,等等,你可以做 .最后,您可以在函数调用行上使用 Destructuring Assignment,而无需使用 .(如果使用 ,建议改用作用域括号。{ a: a, b: b, c: c }{ a, b, c }withwith{}
0赞 0x00001F 8/8/2020 #14

如果要通过引用传递变量,更好的方法是在对象中传递参数,然后使用以下方法开始更改值:window

window["varName"] = value;

例:

// Variables with first values
var x = 1, b = 0, f = 15;


function asByReference (
    argumentHasVars = {},   // Passing variables in object
    newValues = [])         // Pass new values in array
{
    let VarsNames = [];

    // Getting variables names one by one
    for(let name in argumentHasVars)
        VarsNames.push(name);

    // Accessing variables by using window one by one
    for(let i = 0; i < VarsNames.length; i += 1)
        window[VarsNames[i]] = newValues[i]; // Set new value
}

console.log(x, b, f); // Output with first values

asByReference({x, b, f}, [5, 5, 5]); // Passing as by reference

console.log(x, b, f); // Output after changing values

评论

1赞 Peter Mortensen 10/16/2020
但是全局(别名?)对象(?)(在 Web 浏览器上下文中)。因此,有效地在全局变量(?)中传回信息。window
1赞 Andrew 3/24/2023
@PeterMortensen 这就是为什么我喜欢这个答案,建议简单地手动分配/重新分配内联变量,无论它用于什么上下文。但是,如果需要,他们也可以传递他们希望变量存在的上下文/命名空间/对象,并将其作为默认值(避免仅限 Web 浏览器的问题),尽管不幸的是,这种方法要求将变量名称作为字符串传入。globalThis
0赞 Adam Sassano 3/4/2021 #15

这里使用解构是一个示例,我有 3 个变量,在每个变量上我执行多个操作:

  • 如果值小于 0,则更改为 0,
  • 如果大于 255,则更改为 1,
  • 否则,将数字潜水 255,从 0-255 的范围转换为 0-1 的范围。
let a = 52.4, b = -25.1, c = 534.5;
[a, b, c] = [a, b, c].map(n => n < 0 ? 0 : n > 255 ? 1 : n / 255);
console.log(a, b, c); // 0.20549019607843136 0 1
2赞 Michael Trullas Garcia 7/6/2021 #16

由于我们没有 javascript 通过引用传递功能,因此执行此操作的唯一方法是让函数返回值并让调用者分配它:

所以

"makePretty(myArray[x]);"

应该是

"myArray[x] = makePretty(myArray[x]);"

这是为了防止您需要在函数内部进行赋值,如果只需要突变,那么传递对象并改变它就足够了

评论

0赞 Joachim Lous 11/20/2023
这几乎总是一个更好的设计,除非它存在明显的性能问题:功能性、无状态设计产生的复杂性较低。如果调用者想要使用结果来改变某些内容,那是他们的调用,但函数没有强制执行的业务。
0赞 Joachim Lous 11/20/2023 #17

这可能无法回答上述确切问题,但对于许多出现主题的情况,功能性更强的设计是一种富有成效的途径,实际上可以降低复杂性,而不是添加它:

result = new Array(var1, var2, var3)
    .map(makePretty)

评论

0赞 Joachim Lous 11/20/2023
我保留了问题的命名,但按照口头禅“动词是为了副作用”,应用的转换最好命名为“漂亮”