8wDlpd.png
8wDFp9.png
8wDEOx.png
8wDMfH.png
8wDKte.png

JavaScript 是按引用传递语言还是按值传递语言?

Rcfullscale 2月前

234 0

基本类型(数字、字符串等)通过值传递。然而,对象是未知的,因为它们都可以通过值传递(在这种情况下,我们认为保存对象的变量是

基本类型(数字、字符串等)通过值传递。但对象是未知的,因为它们既可以通过值传递(在这种情况下,我们认为保存对象的变量是对象的引用),也可以通过引用传递(我们认为对象的变量保存对象本身)。

虽然最终这并不重要,但我想知道传递参数约定的正确方式是什么。是否有 JavaScript 规范摘录,其中定义了关于此的语义应该是什么?

帖子版权声明 1、本帖标题:JavaScript 是按引用传递语言还是按值传递语言?
    本站网址:http://xjnalaquan.com/
2、本网站的资源部分来源于网络,如有侵权,请联系站长进行删除处理。
3、会员发帖仅代表会员个人观点,并不代表本站赞同其观点和对其真实性负责。
4、本站一律禁止以任何方式发布或转载任何违法的相关信息,访客发现请向站长举报
5、站长邮箱:yeweds@126.com 除非注明,本帖由Rcfullscale在本站《arrays》版块原创发布, 转载请注明出处!
最新回复 (0)
  • 我认为你不小心颠倒了按值传递和按引用传递的定义......\'按值传递(如果我们认为保存对象的变量实际上是对该对象的引用)和按引用传递(当我们认为对象的变量保存对象本身时)\'

  • 是的。无论语法如何,在任何编程语言的任何函数调用中,按引用传递意味着在传递给函数时不会复制与传递变量相关的数据,因此函数对传递变量所做的任何修改都将在函数调用终止后保留在程序中。按值传递意味着在传递给函数时实际复制与变量相关的数据,并且当函数返回时变量超出函数主体的范围时,该函数对该变量所做的任何修改都将丢失。

  • @DanailNachev 遗憾的是,这个术语令人困惑。问题是,“按值传递”和“按引用传递”是早于许多更现代的编程语言特性的术语。“值”和“引用”这两个词指的是

  • @DanailNachev \'通过引用传递\'具体意味着如果你有

  • JavaScript 中很有趣。考虑以下示例:

    function changeStuff(a, b, c)
    {
      a = a * 10;
      b.item = "changed";
      c = {item: "changed"};
    }
    
    var num = 10;
    var obj1 = {item: "unchanged"};
    var obj2 = {item: "unchanged"};
    
    changeStuff(num, obj1, obj2);
    
    console.log(num);
    console.log(obj1.item);
    console.log(obj2.item);

    输出结果如下:

    10
    changed
    unchanged
    
    • 如果 obj1 根本不是引用,那么更改 obj1.item 就不会对 obj1 函数外部产生任何影响。
    • 如果参数是适当的引用,那么一切都会改变。 num 将是 100 ,并且 obj2.item 将读作 "changed" 。相反, num 保持不变 10 obj2.item 保持 "unchanged \'。

    相反,情况是传入的项是按值传递的。但按值传递的项 本身 一个引用。从技术上讲,这称为 共享调用 .

    从实际角度来说,这意味着如果您更改参数本身(如 num obj2 ),则不会影响输入到参数中的项。但如果您更改 内部结构 ,则更改将传播回去(如 obj1 )。

  • 这与 C# 完全相同(或至少在语义上)。对象有两种类型:值(原始类型)和引用。

  • 真正的原因是,在 changeStuff 中,num、obj1 和 obj2 是引用。当您更改 obj1 引用的对象的 item 属性时,您正在更改最初设置为 \'unchanged\' 的 item 属性的值。当您为 obj2 分配一个值 {item: \'changed\'} 时,您正在将引用更改为一个新对象(该对象在函数退出时立即超出范围)。如果您将函数参数命名为 numf、obj1f 和 obj2f 之类的东西,就会更清楚地看到发生了什么。然后您会看到参数隐藏了外部变量名称。

  • @BartoNaz 不是。你想要的是按引用传递引用,而不是按值传递引用。但 JavaScript 总是按值传递引用,就像它按值传递其他所有内容一样。(相比之下,C# 具有与 JavaScript 和 Java 类似的按值传递引用行为,但允许你使用 ref 关键字指定按引用传递引用。)通常你只会让函数返回新对象,并在调用函数时进行赋值。例如,foo = GetNewFoo(); 而不是 GetNewFoo(foo);

  • 虽然这个答案是最受欢迎的,但它可能会有点令人困惑,因为它指出“如果它是纯值传递”。JavaScript 是纯值传递。但传递的值是一个引用。这根本不局限于参数传递。您可以简单地通过 var obj1 = { item: 'unchanged' }; var obj2 = obj1; obj2.item = 'changed'; 复制变量,并会观察到与您的示例相同的效果。因此,我个人参考 Tim Goodman 的答案

  • 它总是按值传递,但对于对象来说,变量的值是引用。因此,当您传递一个对象并更改其 成员 ,这些更改会在函数外部持续存在。这使得它 看起来 像按引用传递。但如果您实际更改对象变量的值,您将看到更改不会持续存在,证明它确实是按值传递。

    例子:

    function changeObject(x) {
      x = { member: "bar" };
      console.log("in changeObject: " + x.member);
    }
    
    function changeMember(x) {
      x.member = "bar";
      console.log("in changeMember: " + x.member);
    }
    
    var x = { member: "foo" };
    
    console.log("before changeObject: " + x.member);
    changeObject(x);
    console.log("after changeObject: " + x.member); /* change did not persist */
    
    console.log("before changeMember: " + x.member);
    changeMember(x);
    console.log("after changeMember: " + x.member); /* change persists */

    输出:

    before changeObject: foo
    in changeObject: bar
    after changeObject: foo
    
    before changeMember: foo
    in changeMember: bar
    after changeMember: bar
    
  • @daylight:实际上,你错了;如果它是通过 const ref 传递的,尝试执行 changeObject 会导致错误,而不仅仅是失败。尝试在 C++ 中为 const 引用分配一个新值,编译器会拒绝它。从用户的角度来说,这就是通过值传递和通过 const 引用传递之间的区别。

  • @daylight:这不是常量引用。在 changeObject 中,我已将 x 更改为包含对新对象的引用。x = {member:\'bar\'}; 相当于 x = new Object(); x.member = \'bar\'; 顺便说一句,我说的也适用于 C#。

  • Yato 2月前 0 只看Ta
    引用 14

    @daylight:对于 C#,您可以从函数外部看到这一点,如果您使用 ref 关键字,您可以通过引用传递引用(而不是默认的通过值传递引用),然后指向新 Object() 的更改将会持续存在。

  • @adityamenon 很难回答“为什么”,但我要指出,Java 和 C# 的设计者也做出了类似的选择;这不仅仅是 JavaScript 的一些怪异之处。实际上,它非常一致地按值传递,让人感到困惑的是值可以是引用。这与在 C++ 中传递指针(按值)然后取消引用它以设置成员没有太大区别。没有人会对这种变化持续存在感到惊讶。但由于这些语言抽象出指针并默默地为您执行取消引用,因此人们会感到困惑。

  • 引用 16

    换句话说,这里令人困惑的不是按值传递/按引用传递。一切都是按值传递,句号。令人困惑的是,您不能传递对象,也不能将对象存储在变量中。每次您认为您正在这样做时,您实际上是在传递或存储对该对象的引用。但是当您访问其成员时,会发生无声的取消引用,这延续了您的变量保存实际对象的虚构。

  • 变量并不“保存”对象;它保存的是引用。您可以将该引用分配给另一个变量,现在它们都引用同一个对象。它始终按值传递(即使该值是引用...)。

    无法改变作为参数传递的变量所持有的值,如果 JavaScript 支持通过引用传递,则可以实现这一点。

  • 作者的意思是,通过传递引用,您传递的是引用值(另一种思考方式是传递内存地址的值)。这就是为什么如果您重新声明对象,原始对象不会改变,因为您正在不同的内存位置创建一个新对象。如果您更改属性,原始对象会发生变化,因为您在原始内存位置(未重新分配)更改了它。

  • “通过值传递引用”这个短语似乎不必要地令人困惑和多余。传递引用时当然必须传递一些值。虽然从技术上讲是正确的,但大多数人可能默认认为除非另有说明,否则任何东西都是通过值传递的。因此,除非引用本身是通过引用传递的(有点像 C 语言中指向指针的指针),否则引用当然是通过值传递的,但在这种情况下,Javascript 甚至不支持这一点,所以我认为它无助于使概念更清晰

  • lavi 2月前 0 只看Ta
    引用 20

    JavaScript 令人困惑的地方在于它没有提供任何选择,@geg:复杂类型总是被间接处理,简单类型总是被直接处理。没有办法获取对整数的引用,也没有办法阻止传递对元组的引用。这……有时会很尴尬。

返回
作者最近主题: