推荐关注
› Meteor
› JSLint - a JavaScript code quality tool
› jsFiddle
› D3.js
› WebStorm
推荐书目
› JavaScript 权威指南第 5 版
› Closure: The Definitive Guide
zero3412

神奇的 Javascript,谁能告诉我为什么

  •  1
     
  •   zero3412 · May 5, 2021 · 8605 views
    This topic created in 2012 days ago, the information mentioned may be changed or developed.
    let data = [
    {x:0, y:1},
    {x:2, y:3},
    ];

    let A = data[0];
    let B = data[1];

    A.x = B.x;
    A.y = B.y;

    console.log(data, A, B)

    为什么 data[0].x == 2 ???
    明明申请了变量 A,我只想改变变量 A,怎么连 data 的值都变了
    这是什么原理,搞 PHP 的搞不明白啊
    53 replies  •  2021-05-06 17:54:43 +08:00
    across
    across
    May 5, 2021
    1
    不懂 php 。
    {}是 object 类型,A 是做了 data[0]引用,改 A 就是改 data[0]
    zero3412
    zero3412
    OP
    May 5, 2021
    2
    @across 至少在 PHP 里,A 变量就是个完全独立的值了,只是复制了一份 data[0],直接蒙逼了哇,这操作太神奇了。
    across
    across
    May 5, 2021
    3
    @zero3412 php 不知道,但我接触的大语言,都是自定义类型按引用传递,基础类型按值传递的····
    dzdh
    dzdh
    May 5, 2021
    4
    PHP 的话是这样的:

    ```
    php > $a = new StdClass();
    php > $a->a = new StdClass();
    php > $b = $a->a;
    php > $b->ee = 3;
    php > var_dump($a);
    object(stdClass)#1 (1) {
    ["a"]=>
    object(stdClass)#2 (1) {
    ["ee"]=>
    int(3)
    }
    }
    ```
    aijam
    aijam
    May 5, 2021
    5
    搞清楚“对象”和“引用”的关系。列表和变量存的都是引用,而通过引用改变的都是同一个对象。
    ashong
    ashong
    May 5, 2021
    6
    let A = Object.assign({}, data[0]);
    zero3412
    zero3412
    OP
    May 5, 2021❤️1
    7
    @across @dzdh @aijam @ashong

    谢谢各位,找了一篇文章学习了一下 https://segmentfault.com/a/1190000014724227
    特别是 “列表和变量存的都是引用,而通过引用改变的都是同一个对象。” 精辟
    ericgui
    ericgui
    May 5, 2021
    8
    JavaScript 是 pass by reference
    Jirajine
    Jirajine
    May 5, 2021 via Android
    9
    @across 全部都是按引用传递,所谓“按值传递”是一种 inline 优化,对程序员是透明的,这些语言没有 deref 操作。
    JerryCha
    JerryCha
    May 5, 2021❤️2
    10
    data[0]传递的实际是指针,小伙子 C 没学好吧
    Rocketer
    Rocketer
    May 5, 2021 via iPhone
    11
    实际上传指针才是主流,PHP 那种默认传值,加了&才传指针的,属于少数派
    HashV2
    HashV2
    May 5, 2021
    12
    很多语言都这样吧,引用
    godbasin
    godbasin
    May 5, 2021
    13
    因为 A 拿到的是 data[0] 的引用
    ipwx
    ipwx
    May 5, 2021❤️4
    14
    大部分语言,C#, Java, Javascript, Scala, Python 都是这个逻辑。PHP 是少数。

    C++ 程序员不会有这个疑问,因为他们天天和 T* T& T 打交道
    InternetExplorer
    InternetExplorer
    May 5, 2021❤️1
    15
    php 的数组是值类型,而且是写是复制,大数组赋值起来很快,改到的时候才会真正复制值。
    js 的对象 { }(包括数组 [ ] ) 是引用类型,赋值就是传一下引用,都是指向同一个对象的。
    hejingyuan199
    hejingyuan199
    May 5, 2021
    16
    我平时基本只用 php,但我感觉 JavaScript 这个才更符合编程本质吧。

    没深入研究过 php 这个问题。
    Justfakemoz
    Justfakemoz
    May 5, 2021
    17
    。。。除了基础类型,赋值都是引用
    zjsxwc
    zjsxwc
    May 5, 2021
    18
    感觉楼主在抹黑 php 。

    php 里你用对象照样也和 js 得到一样的结果。

    无非是 js 里面 {} 表示对象,php 里面 [] 表示数组不是对象。
    jeffwcx
    jeffwcx
    May 5, 2021
    19
    看得我一脸懵逼,我还以为有啥问题呢
    jonsun30
    jonsun30
    May 5, 2021
    20
    Everthing using a dot in JS is an object.

    When you store a non-primitive value some where or you pass it to a function, it is passed by reference, you are passing a pointer to it.
    fcmio
    fcmio
    May 5, 2021 via iPhone
    21
    不懂 php,pythoner 感觉没毛病啊……
    Rache1
    Rache1
    May 5, 2021
    22
    PHP 里面对象也是引用的,数组不是
    darknoll
    darknoll
    May 5, 2021
    23
    这不是最基础的东西?
    charlie21
    charlie21
    May 5, 2021
    24
    1

    JAVASCRIPT
    let arr1 = [1,2,3,4];
    let arr2 = arr1;
    arr2[0] = 99;
    console.log(arr2); // [99,2,3,4]
    console.log(arr1); // [99,2,3,4]

    JAVASCRIPT
    let arr1 = [1,2,3,4];
    let arr2 = [...arr1];
    arr2[0] = 99;
    console.log(arr2); // [99,2,3,4]
    console.log(arr1); // [1,2,3,4]

    JAVASCRIPT
    let d1 = { x: 1, y:2 };
    let d2 = d1;
    d2.x = 80;
    console.log(d2); // { x: 80, y: 2 }
    console.log(d1); // { x: 80, y: 2 }

    JAVASCRIPT
    let d1 = { x: 1, y:2 };
    let d2 = {...d1};
    d2.x = 80;
    console.log(d2); // { x: 80, y: 2 }
    console.log(d1); // { x: 1, y: 2 }

    关键词 js spread operator

    2

    PHP
    $arr1 = [1,2,3,4];
    $arr2 = $arr1;
    $arr2[0] = 99;
    var_export($arr2); // [99,2,3,4]
    var_export($arr1); // [1,2,3,4]

    PHP
    $arr1 = [1,2,3,4];
    $arr2 = &$arr1;
    $arr2[0] = 99;
    var_export($arr2); // [99,2,3,4]
    var_export($arr1); // [99,2,3,4]

    3

    C#
    int[] arr1 = new int[]{1,2,3,4};
    int[] arr2 = arr1;
    arr2[0] = 99;
    Console.WriteLine(String.Join(" ", arr2)); // 99 2 3 4
    Console.WriteLine(String.Join(" ", arr1)); // 99 2 3 4

    C#
    using System.Collections.Generic;
    List<int> list1 = new List<int>{1,2,3,4};
    List<int> list2 = new List<int>(list1);
    list2[0] = 99;
    list2.ForEach(Console.WriteLine); // 99 2 3 4
    list1.ForEach(Console.WriteLine); // 1 2 3 4

    C#
    using System.Collections.Generic;
    List<int> list1 = new List<int>{1,2,3,4};
    List<int> list2 = list1;
    list2[0] = 99;
    list2.ForEach(Console.WriteLine); // 99 2 3 4
    list1.ForEach(Console.WriteLine); // 99 2 3 4
    icanfork
    icanfork
    May 5, 2021 via iPhone
    25
    面试面基础还是很有必要的,即使是八股文
    很多人即使自己不知道为什么,也不尝试去弄清楚为什么
    OHyn
    OHyn
    May 5, 2021
    26
    这个在 java 、c 里头也是一样的呀。。。传值和传引用嘛
    iyaozhen
    iyaozhen
    May 5, 2021
    27
    PHP 虽然说是传值,但实际也是引用。然后有个写死复制的机制,就是当发现要修改 A 时,是复制了一份。
    省去了需要自己 copy 的问题,比较符合人的思维
    WillBC
    WillBC
    May 5, 2021 via iPhone
    28
    等你感受一下 deep clone
    Nitroethane
    Nitroethane
    May 5, 2021
    29
    @JerryCha data[0] 不一定传引用啊,得看 data 的数据类型,如果是 char* data[],那 data[0] 就传的是指针,如果是 char data[],data[0] 照样传值
    anguiao
    anguiao
    May 5, 2021 via Android
    30
    虽然 JS 确实很神奇,但是这个是常规操作。
    Yvette
    Yvette
    May 6, 2021
    31
    JS 里除了 primitive types 是 pass by value 之外,其余所有的都是 reference
    xuanbg
    xuanbg
    May 6, 2021
    32
    因为
    let A = data[0];
    let B = data[1];

    所以 data 的值变成 [
    {x:2, y:3},
    {x:2, y:3},
    ];
    xuanbg
    xuanbg
    May 6, 2021
    33
    因为
    let A = data[0];
    let B = data[1];

    A.x = B.x;
    A.y = B.y;

    所以 data 的值变成 [
    {x:2, y:3},
    {x:2, y:3},
    ];
    Marszm
    Marszm
    May 6, 2021
    34
    这种需要深拷贝.....PHP 这波属于非主流操作
    itechify
    itechify
    May 6, 2021 via Android
    35
    JAVA 的路过,要不是这样的结果才奇怪😳
    luckyboy6
    luckyboy6
    May 6, 2021
    36
    js 按值传递和 按引用传递的区别 let A = data[0] 时,A 只是一个指针 指向堆区的 data[0] : {x:0,y:1},所以改变 A.x 时改变的是 data[0]。
    meloncc
    meloncc
    May 6, 2021
    37
    这个问题与 Javascript 没有关系
    gtanyin
    gtanyin
    May 6, 2021
    38
    果然学编程应该从 C 学起,不然连指针的概念都要惊讶半天
    liuky
    liuky
    May 6, 2021❤️1
    39
    楼主高级黑
    misaka19000
    misaka19000
    May 6, 2021
    40
    这是来黑 PHP 的吧
    Leiothrix
    Leiothrix
    May 6, 2021
    41
    JavaScript 浅拷贝和深拷贝的区别,浅拷贝两个对象指向同一个地址,深拷贝是新开栈,两个对象指向不同的地址。可使用 JSON.parse(JSON.stringify(obj))进行深拷贝,修改后不会影响到原对象数据。
    ganbuliao
    ganbuliao
    May 6, 2021
    42
    object 对象默认是引用 知道这个就清楚了
    est
    est
    May 6, 2021
    44
    楼主低级黑
    zhuweiyou
    zhuweiyou
    May 6, 2021
    45
    我感觉你在黑 PHP
    zhengfan2016
    zhengfan2016
    May 6, 2021
    46
    为什么我看着觉得很正常,我第一门语言是 python,有没有老哥给我讲讲哪儿不正常 233
    IvanLi127
    IvanLi127
    May 6, 2021
    47
    我记得 php 里也有引用传参啊,楼主用的啥版本的 php,代码放出来我们品品?
    ozzzm
    ozzzm
    May 6, 2021
    48
    指针啊
    AoEiuV020
    AoEiuV020
    May 6, 2021
    49
    深拷贝,浅拷贝,js 无关,一般都有这些区别,
    vueli
    vueli
    May 6, 2021
    50
    前面的 = 是指向
    ruike007
    ruike007
    May 6, 2021
    51
    这不是深浅拷贝的问题吗?基础啊,大哥
    karott7
    karott7
    May 6, 2021
    52
    这不前端正常操作?赋值对象都是引用
    fescover
    fescover
    May 6, 2021
    53
    正常操作,还有更 bt 的,猜猜下面输出什么
    NaN===NaN
    null===null
    null==NaN
    {}==={}
    []===[]
    ""===""
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Privacy   ·   Solana   ·   889 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 135ms · UTC 18:11 · PVG 02:11 · LAX 10:11 · JFK 13:11
    ♥ Do have faith in what you're doing.