Javascript-基本类型与引用类型

Javascript-基本类型与引用类型,javascript,pass-by-reference,Javascript,Pass By Reference,在下面的代码中,我们正在传递一个对象。因此,根据javascript,我们正在传递一个引用并进行操作 var a = new Number(10); x(a); alert(a); function x(n) { n = n + 2; } 但警报是10,而不是12。为什么? var a = new Number(10); x(a); alert(a); function x(n) { n = n + 2; // NOT VALID as this would essenti

在下面的代码中,我们正在传递一个对象。因此,根据javascript,我们正在传递一个引用并进行操作

var a = new Number(10);
x(a);
alert(a);

function x(n) {
n = n + 2;
}
但警报是10,而不是12。为什么?

var a = new Number(10);    
x(a);
alert(a);

function x(n) {
    n = n + 2; // NOT VALID as this would essentially mean 10 = 10 + 2 since you are passing the 'value' of a and not 'a' itself
}
您需要编写以下内容才能使其正常工作

var a = new Number(10);
x(a);
alert(a);

function x(n) {
    a = n + 2; // reassign value of 'a' equal to the value passed into the function plus 2
}

JavaScript参数传递的工作原理与Java类似。单个值通过值传递,但对象属性通过其指针值通过引用传递。函数中不会修改值本身,但会修改对象的属性

考虑以下代码:

function doThis(param1, param2) {
    param1++;
    if(param2 && param2.value) {
        param2.value++;
    }
}

var initialValue = 2;
var initialObject = {value: 2};

doThis(initialValue, initialObject);

alert(initialValue); //2
alert(initialObject.value); //3

让我试着用例子来回答这个问题:

function modify(obj) {
    // modifying the object itself
    // though the object was passed as reference
    // it behaves as pass by value
    obj = {c:3};
}

var a = {b:2}
modify(a);
console.log(a)
// Object {b: 2}

function increment(obj) {
    // modifying the value of an attribute
    // working on the same reference
    obj.b = obj.b + 1;
}

var a = {b:2}
increment(a);
console.log(a)
// Object {b: 3}

function augument(obj) {
    // augument an attribute
    // working on the same reference
    obj.c = 3;
}

var a = {b:2}
augument(a);
console.log(a)
// Object {b: 2, c: 3}

请参阅工作演示。

n
x
的本地,首先它被设置为与全局
a
相同的引用。然后,右侧
n+2
被计算为一个数字(原语)。 作业的左侧
n
,永远不会被计算,它只是一个标识符。因此,我们的局部变量现在设置为右侧的原始值。
a
引用的值实际上从未修改过。看

var a = new Number(10);
x(a);
alert(a);  // 10

function x(n) {
  alert(typeof n);  // object
  n = n + 2;
  alert(typeof n);  // number
}
当你计算的时候

n + 2
即使
n
确实是
number
对象实例,这也会产生一个新的“本机编号”

赋值给
n
只会更改局部变量
n
引用的内容,而不会更改
编号
对象实例。你可以看到这一点

n = new Number(10);
console.log(typeof n);     // ---> "object"
console.log(n + 2);        // ---> 12
console.log(typeof (n+2)); // ---> "number"
n = n + 2;
console.log(typeof n);     // ---> "number"
在Javascript(或Python或Lisp)中,无法传递变量的“地址”,以便调用的函数对其进行变异。你唯一能做的就是传递一个setter函数。。。例如:

function foo(setter) {
    setter(42);
}

funciton bar() {
    var x = 12;
    foo(function(newx){x = newx;});
    console.log(x); // ---> 42
}

答案相当简单:因为ECMAScript是按值传递的,而不是按引用传递的,您的代码证明了这一点。(更准确地说,它是共享调用,这是一种特定的传递值。)

请参阅以获取更多信息

ECMAScript使用按值传递,或者更准确地说,是按值传递的一种特殊情况,其中传递的值始终是指针。这种特殊情况有时也称为按共享调用、按对象调用共享或按对象调用

这与Java(用于对象)、C#(默认情况下用于引用类型)、Smalltalk、Python、Ruby以及几乎所有创建的面向对象语言所使用的约定相同

注意:某些类型(例如,
Number
s)实际上是通过值直接传递的,而不是通过中间指针。然而,由于这些是不可变的,在这种情况下,传递值和按对象调用共享之间没有明显的行为差异,因此您可以通过简单地将所有内容视为按对象调用共享来大大简化您的心智模型。只需将这些特殊情况解释为不需要担心的内部编译器优化

下面是一个简单的示例,您可以运行它来确定ECMAScript(或任何其他语言,在翻译后)的参数传递约定:

函数isEcmascriptPassByValue(foo){
push('更准确地说,它是由对象共享调用的!');
foo='否,ECMAScript是通过引用传递的。';
返回;
}
var bar=[“是的,当然,ECMAScript*是*传递值!”;
isEcmascriptPassByValue(bar);
控制台日志(bar);
//当然,ECMAScript*是*按值传递!,

//更准确地说,它是由对象共享调用的我不是在寻找工作代码。您的第一组解释“10=10+2”不正确。此等式无效。因为左边是一个数字,右边是。你是对的。这个答案可能会帮助你理解javascript中的“通过引用传递”,所以数字是不可变的,对吗?如果
x=新编号(5)
x=5
,则不存在使
x
保持相同参考但具有不同值的操作。当我执行
console.log(新数字(5))
时,它给出
Number{[[PrimitiveValue]]:5}
。但是我假设你不能改变
[[PrimitiveValue]]
,对吗?@soktinpk:是的,数字和字符串在Javascript中是不可变的。但是,您可以使用
valueOf()
方法创建一个对象,该方法的行为类似于数学表达式中的数字,但具有可控制的可变状态。Java(和JS)对象按名称传递(对对象的引用按值传递)。对象参数(不是属性)不是通过引用传递的。术语很重要。”java中的“属性”具有与“字段”不同的特定含义,请参见