【问题标题】:value of javascript object not changing (pass by reference)javascript 对象的值不变(通过引用传递)
【发布时间】:2016-09-27 03:45:15
【问题描述】:
function outerFunction(x){
    return function(y){
        x=x+1;
        console.log(x+y);
    }
}
var myVal = new Number(2); //myVal is an object
console.log(myVal); //prints Number{[[PrimitiveValue]]: 2}

var innerFunction  = outerFunction(myVal); //I'm passing myVal obj
innerFunction(10)   //13
innerFunction(10)   //14
innerFunction(10)   //15

console.log(myVal);  //prints Number{[[PrimitiveValue]]: 2} instead of 5?

我预计最后一个console.log 会打印Number{[[PrimitiveValue]]: 5},因为我将myVal object 传递给outerFunction 并且在JS 对象中是通过引用传递的,为什么它没有打印5?

【问题讨论】:

  • Re:“在 JS 中的对象是通过引用传递的”:这不是真的(正如您的代码所演示的那样)。
  • @ruakh 我将代码更改为 var myObj = {a:2} 并将 myObj 传递给外部函数..并且 x.a = x.a +1 ;并且 console.log 确实更改为 {a:5} 确认对象是通过引用传递的
  • @ruakh 对象作为引用的副本传递,因此您必须区分突变和重​​新分配
  • @WildWidow:这不是“通过引用传递”的意思。是的,只有一个对象(不像在 C++ 中,函数会获取对象的副本);但变量本身是不同的。 (不要难过;这实际上是一个非常常见的混淆来源。)
  • (在 C++ 术语中:在 JavaScript 中,您只有一个指向每个对象的隐式指针;无法直接引用对象,也无法获取显式指针。因此该函数具有distinct 指向 same 对象的指针。它类似于 pass-by-reference,直到您尝试重新分配局部变量并发现这只具有局部效果。)跨度>

标签: javascript closures pass-by-reference


【解决方案1】:

使用 console.log 的简单解释(在这种情况下,请检查 javascript 在控制台中打印的内容):

function outerFunction(x){

    return function(y){

        console.log("type of x", typeof x); 
        console.log("value x:",x);
        console.log("value y:",y);

        x=x+1;
        console.log(x+y);
    }

}


var myVal = new Number(2); //myVal is an object
console.log(myVal); //prints Number{[[PrimitiveValue]]: 2}

var innerFunction  = outerFunction(myVal); //I'm passing myVal obj
innerFunction(10)   //13
innerFunction(10)   //14
innerFunction(10)   //15

console.log("type of myval",typeof myVal);

console.log(myVal);  //prints Number{[[PrimitiveValue]]: 2} instead of 5?// 

您的代码中发生了什么。

==> 首先,您不能使用 + 运算符在 javascript 中添加两个对象。因此 javascript 将其转换为数字或字符串(在本例中为数字,因为您正在传递数字本身,这是一种原始类型)

==> 您返回的内部函数具有来自外部函数的 X 外部引用。 (因为关闭)

==> 每次增加 X 时,外部函数范围内的 x 值都会发生变化,但它现在对全局“myVal”变量(类型对象)没有影响,因为 javascript 将本地 X 视为原始类型(第一点解释过,是传值而不是引用)

==> 所以全局值保持不变,内部函数访问的 X 不断变化,这就是为什么你看到 13,14,15 作为答案

希望对你有帮助

【讨论】:

  • 这叫做柯里化
  • @Wild 这是一个不充分的响应myVal 不是函数而是对象。对象通过共享引用的副本来传递。因此,正确的评估策略是通过共享传递。所以 OP 的假设几乎是正确的,Objects 由(a 的副本)引用传递。使用这种评估策略,您必须区分突变let n = new Number(2); n.x = true; 和重新分配let n = new Number(2); n = 3;
  • @lven ,您能详细说明一下您的观点吗?我的观点也有一个打字错误。 3 我已经更正了。
猜你喜欢
  • 2012-07-16
  • 1970-01-01
  • 2011-09-27
  • 2013-06-27
  • 2015-09-19
  • 1970-01-01
  • 1970-01-01
  • 2011-03-18
  • 2015-06-18
相关资源
最近更新 更多