Skip to main content
 首页 » 编程设计

javascript之在被调用函数中重新初始化数组

2025年05月04日25mfryf

数组在 javascript 中通过引用传递。这意味着数组是可变的,可以在调用的函数中更改。为什么我无法在调用的函数中重新初始化数组?

对于python也是如此

function calling(){ 
    var arr = [1,2] 
    console.log(arr); //prints [1,2] 
    called(arr); 
    console.log(arr); //prints [1,2,3,4],but I was expecting [5,6] 
 
} 
 
function called(arr){ 
    arr.push(3) 
    arr.push(4) 
    arr = [5,6] 
} 
 
calling() 

更新 我正在寻找(可变性、通过引用传递、通过赋值传递和重新初始化数组)的理由 请不要发布问题的解决方法和解决方案。我知道如何让 arr 打印 [5,6]

请您参考如下方法:

Arrays are passed by reference in javascript.

不,他们不是。 ECMAScript/JavaScript 是严格按值传递的。 (更准确地说,是共享调用,它是按值传递的一种特殊情况。)

That means arrays are mutable and can be changed in called function.

不,这不是它的意思。它的意思正是它所说的:调用者范围内对数组的引用作为参数传递给函数,而不是值。

数组 是否可变与按引用传递还是按值传递无关。 ECMAScript 不是纯函数式语言,大多数对象都可以改变。 Number、Symbol 和 String 是一个异常(exception)。

Why am I not able to Re-initialization an array in called function?

您正在尝试修改调用方范围内的引用。这仅适用于传递引用。 ECMAScript 不是按引用传递,无论谁告诉你那都是错误的。

This is also true for python

Python 在这方面的行为与 ECMAScript 相同,是的,它也是按值传递。

您的困惑源于您错误地认为 ECMAScript/JavaScript 是按引用传递的,而实际上它不是。

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

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

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

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

function isEcmascriptPassByValue(foo) { 
  foo.push('More precisely, for reference types it is call-by-object-sharing, which is a special case of pass-by-value!'); 
  foo = 'No, ECMAScript is pass-by-reference.'; 
  return; 
} 
 
var bar = ['Yes, of course, ECMAScript *is* pass-by-value!']; 
 
isEcmascriptPassByValue(bar); 
 
console.log(bar); 
// Yes, of course, ECMAScript *is* pass-by-value!, 
// More precisely, for reference types it is call-by-object-sharing, which is a special case of pass-by-value!

def is_python_pass_by_value(foo): 
    foo[0] = 'More precisely, for reference types it is call-by-object-sharing, which is a special case of pass-by-value!' 
    foo = ['Python is not pass-by-reference.'] 
 
quux = ['Yes, of course, Python *is* pass-by-value!'] 
 
is_python_pass_by_value(quux) 
 
print(quux[0]) 
# More precisely, for reference types it is call-by-object-sharing, which is a special case of pass-by-value! 

如果您熟悉 C#,这是了解值类型和引用类型的按值传递和按引用传递之间的区别的一个很好的方法,因为 C# 支持所有 4 种组合:值类型的值(“传统的按值传递”),引用类型的按值传递(按共享调用,按对象调用,ECMAScript 中的按对象共享调用),传递 -引用类型按引用传递,值类型按引用传递。

(实际上,即使您不了解 C#,这也不难理解。)

// In C#, struct defines a value type, class defines a reference type 
struct MutableCell 
{ 
    public string value; 
} 
 
class Program 
{ 
    // the ref keyword means pass-by-reference, otherwise it's pass-by-value 
    // You must explicitly request pass-by-reference both at the definition and the call 
    static void IsCSharpPassByValue(string[] foo, MutableCell bar, ref string baz, ref MutableCell qux) 
    { 
        foo[0] = "More precisely, for reference types it is call-by-object-sharing, which is a special case of pass-by-value."; 
        foo = new string[] { "C# is not pass-by-reference." }; 
 
        bar.value = "For value types, it is *not* call-by-sharing."; 
        bar = new MutableCell { value = "And also not pass-by-reference." }; 
 
        baz = "It also supports pass-by-reference if explicitly requested."; 
 
        qux = new MutableCell { value = "Pass-by-reference is supported for value types as well." }; 
    } 
 
    static void Main(string[] args) 
    { 
        var quux = new string[] { "Yes, of course, C# *is* pass-by-value!" }; 
 
        var corge = new MutableCell { value = "For value types it is pure pass-by-value." }; 
 
        var grault = "This string will vanish because of pass-by-reference."; 
 
        var garply = new MutableCell { value = "This string will vanish because of pass-by-reference." }; 
 
        // the first two are passed by value, the other two by reference 
        IsCSharpPassByValue(quux, corge, ref grault, ref garply); 
 
        Console.WriteLine(quux[0]); 
        // More precisely, for reference types it is call-by-object-sharing, which is a special case of pass-by-value. 
 
        Console.WriteLine(corge.value); 
        // For value types it is pure pass-by-value. 
 
        Console.WriteLine(grault); 
        // It also supports pass-by-reference if explicitly requested. 
 
        Console.WriteLine(garply.value); 
        // Pass-by-reference is supported for value types as well. 
    } 
}