我想将一个变量传递给一个函数并让该函数改变该值。

我知道我可以将其作为一个对象来执行此操作,但我想知道是否有一些我还没有想到的方法可以做到这一点。

这就是我想要做的,但它当然不能按照我想要的方式进行:

function test1(vari) {
    vari = 2;
}
var myvar1 = 1;
test1(myvar1);
console.log(myvar1); //1

这可行,但我并不真正想将所有变量都变成对象:

function test2(vari) {
    vari.val = 2;
}
var myvar2 = { val: 1 };
test2(myvar2);
console.log(myvar2.val); //2

这也有效,但不是一个可接受的解决方案:

function test3(vari) {
    eval(vari + ' = 2;');
}
var myvar3 = 1;
test3('myvar3');
console.log(myvar3); //2

还有比这些更好的选择吗?

更新

我想做的一个更好的例子:

function test5(vari, onblur) {
    document.querySelector('body').innerHTML += `<input id="ctl_${vari}" type="text" value="${vari}">`;
    el = document.getElementById(`ctl_${vari}`);
    el.addEventListener('blur', function(e) {
        vari = e.target.value; //Doesn't update original variable
        onblur(e);
    });
    return el;
}
var myvar5 = 'test';
var ele = test5(
    myvar5,
    function(e) {
        //Could set myvar5 = e.target.value but not wanting to do this for every single field
        console.log(myvar5);
    }
);

9

  • 9
    无法通过引用传递变量。stackoverflow.com/questions/518000/


    – 

  • 4
    这看起来很像一个 XY 问题。


    – 

  • 返回新值的myVar = myFunc(myVar);地方有什么问题?myFunc()


    – 

  • 3
    @johna 那么你就无法做到这一点;JavaScript 根本没有这样的功能。


    – 

  • 1
    @johna 请告诉我们更多关于您的限制的信息。您的是什么?“我真的不想让所有变量都成为对象”——为什么不呢?有多少个变量?把它们都放在一个对象中。“有没有比这些更好的选择? ”——闭包和回调可能看起来更自然,但您的简化示例并没有表明您是否能够使用它们。


    – 



最佳答案
4

就像,你不能在 JavaScript 中传递引用。传递给函数的所有参数都是按值传递的。对象也是如此。虽然你可以改变作为参数传递的对象,但你不能重新分配它(使其成为按值传递)。有关详细信息,请参阅:(也适用于 JavaScript)。

您可以使用数组返回多个值:

function test(a, b) {
  return [a + b, a - b];
}

let a = 5, b = 2;
[a, b] = test(a, b);

的最终值a7b3

请注意,后面的分号let a = 5, b = 2;是必需的,否则它将被执行,let a = 5, b = 2[a, b] = test(a, b);在这种情况下会导致“未捕获的 ReferenceError:在初始化之前无法访问词法声明‘b’”。

但是在您的特定场景中,您可以简单地将所需的值onblur作为参数传递给函数,以避免myvar5 = e.target.value在每个函数定义中都这样做。

function test5(vari, onblur) {
    document.querySelector('body').innerHTML += `<input id="ctl_${vari}" type="text" value="${vari}">`;
    const el = document.getElementById(`ctl_${vari}`);
    el.addEventListener('blur', function(e) {
        onblur(e, e.target.value);
    });
    return el;
}

// best matching the question code
var myvar5 = 'test';
var ele = test5(myvar5, function(e, myvar5) {
    console.log(myvar5);
});

// probably preferable given the current question code
var ele = test5('test', function(e, value) {
    console.log(value);
});

1

  • 看起来我将要处理模糊处理程序中的值的更新,因为这是最干净的方法。


    – 

这可能不是您想要的,但也许可以尝试以下方法:

function test1(vari) {
    return vari += 2;
}

var myvar1 = test1(myvar1);

console.log(myvar1);

3

  • 我的例子只是简化的例子,但在我的例子中我不能使用返回。


    – 

  • 1
    您的意思是,对于您的项目,您不能使用 return ,因为它不合适,或者当您尝试使用它时出现错误?


    – 

  • 它不合适。


    – 

在 JS 中,只有对象元素通过引用传递。

所以不要指望用一个简单的变量就能做到这一点。

但是,由于所有变量都属于窗口对象,所以

您可以这样对待它,
但这是本世纪最糟糕的想法

function fx(varName)
  {
  window[varName]++;
  }

var myVar = 5;
fx('myVar');
console.log( myVar ); // 6

4

  • 2
    对象是通过引用传递的。 ” – 不,不是。它们可能是引用值,但它们仍然是通过值传递的。


    – 

  • @Bergi 对的,我重新表述了这句话。


    – 


  • 第二糟糕?eval会更糟糕,对吧?


    – 

  • 1
    我没有想到这个选项,虽然这不是一个好的做法,但它比 eval 更好,所以谢谢你的回答。应该注意,这只会获取全局变量。


    – 


在您的例子中,我假设该参数vari是一个原始值。以下是一些修复它的方法:

  • 用对象包装值
  • 不将其用作参数(将其从函数声明中删除)

number像和 这样的原始值string是通过值传递的

其他人喜欢object并被array“引用副本”传递

以下是一些示例:

let primitiveVar = 1;

let function1 = (primitiveParam) => {
  primitiveParam = 3;
};

// not work for primitive values
function1(primitiveVar);
console.log(primitiveVar); // 1
let primitiveVar2 = 1;

let function2 = (primitiveParam) => {
  return primitiveParam + 3;
};

// due to primitive value immutability we need to reassign
primitiveVar2 = function2(primitiveVar2);
console.log(primitiveVar2); // 4
let objectVar = {
  val: 1,
};

let function3 = (objectParam) => {
  // objectParam has the same ref as objectVar
  objectParam.val = 2;
};

function3(objectVar);
console.log(objectVar.val); // 2
let objectVar2 = {
  val: 1,
};

let function4 = (objectParam) => {
  // objectParam ref is now point to a different object
  objectParam = { val: 3 };
};

function4(objectVar2);
console.log(objectVar2.val); // 1

工作场地:

1

  • 2
    其他的,比如对象和数组,都是通过引用传递的” – 不,它们不是。它们是通过值传递的引用值。


    –