神奇的 Javascript,谁能告诉我为什么 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐关注
Meteor
JSLint - a Javascript code quality tool
jsFiddle
D3.js
WebStorm
推荐书目
Javascript 权威指南第 5 版
Closure: The Definitive Guide
zero3412
V2EX    Javascript

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

  •  1
     
  •   zero3412 2021-05-05 14:08:42 +08:00 7590 次点击
    这是一个创建于 1626 天前的主题,其中的信息可能已经有所发展或是发生改变。
    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 条回复    2021-05-06 17:54:43 +08:00
    across
        1
    across  
       2021-05-05 14:11:05 +08:00
    不懂 php 。
    {}是 object 类型,A 是做了 data[0]引用,改 A 就是改 data[0]
    zero3412
        2
    zero3412  
    OP
       2021-05-05 14:12:28 +08:00
    @across 至少在 PHP 里,A 变量就是个完全独立的值了,只是复制了一份 data[0],直接蒙逼了哇,这操作太神奇了。
    across
        3
    across  
       2021-05-05 14:13:59 +08:00
    @zero3412 php 不知道,但我接触的大语言,都是自定义类型按引用传递,基础类型按值传递的
    dzdh
        4
    dzdh  
       2021-05-05 14:14:24 +08:00
    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
        5
    aijam  
       2021-05-05 14:15:37 +08:00
    搞清楚“对象”和“引用”的关系。列表和变量存的都是引用,而通过引用改变的都是同一个对象。
    ashong
        6
    ashong  
       2021-05-05 14:15:45 +08:00
    let A = Object.assign({}, data[0]);
    zero3412
        7
    zero3412  
    OP
       2021-05-05 14:23:02 +08:00   1
    @across @dzdh @aijam @ashong

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

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

    没深入研究过 php 这个问题。
    Justfakemoz
        17
    Justfakemoz  
       2021-05-05 15:31:32 +08:00
    。。。除了基础类型,赋值都是引用
    zjsxwc
        18
    zjsxwc  
       2021-05-05 15:38:08 +08:00
    感觉楼主在抹黑 php 。

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

    无非是 js 里面 {} 表示对象,php 里面 [] 表示数组不是对象。
    jeffwcx
        19
    jeffwcx  
       2021-05-05 16:04:17 +08:00
    看得我一脸懵逼,我还以为有啥问题呢
    jonsun30
        20
    jonsun30  
       2021-05-05 16:07:44 +08:00
    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.
    ShuoHui
        21
    ShuoHui  
       2021-05-05 16:12:27 +08:00 via iPhone
    不懂 php,pythoner 感觉没毛病啊……
    Rache1
        22
    Rache1  
       2021-05-05 16:42:04 +08:00
    PHP 里面对象也是引用的,数组不是
    darknoll
        23
    darknoll  
       2021-05-05 16:47:45 +08:00
    这不是最基础的东西?
    charlie21
        24
    charlie21  
       2021-05-05 16:55:39 +08:00
    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
        25
    icanfork  
       2021-05-05 17:15:21 +08:00 via iPhone
    面试面基础还是很有必要的,即使是八股文
    很多人即使自己不知道为什么,也不尝试去弄清楚为什么
    OHyn
        26
    OHyn  
       2021-05-05 17:23:15 +08:00
    这个在 java 、c 里头也是一样的呀。。。传值和传引用嘛
    iyaozhen
        27
    iyaozhen  
       2021-05-05 19:39:41 +08:00
    PHP 虽然说是传值,但实际也是引用。然后有个写死复制的机制,就是当发现要修改 A 时,是复制了一份。
    省去了需要自己 copy 的问题,比较符合人的思维
    WillBC
        28
    WillBC  
       2021-05-05 22:03:59 +08:00 via iPhone
    等你感受一下 deep clone
    Nitroethane
        29
    Nitroethane  
       2021-05-05 22:14:38 +08:00
    @JerryCha data[0] 不一定传引用啊,得看 data 的数据类型,如果是 char* data[],那 data[0] 就传的是指针,如果是 char data[],data[0] 照样传值
    anguiao
        30
    anguiao  
       2021-05-05 22:38:50 +08:00 via Android
    虽然 JS 确实很神奇,但是这个是常规操作。
    Yvette
        31
    Yvette  
       2021-05-06 04:51:24 +08:00
    JS 里除了 primitive types 是 pass by value 之外,其余所有的都是 reference
    xuanbg
        32
    xuanbg  
       2021-05-06 06:39:25 +08:00
    因为
    let A = data[0];
    let B = data[1];

    所以 data 的值变成 [
    {x:2, y:3},
    {x:2, y:3},
    ];
    xuanbg
        33
    xuanbg  
       2021-05-06 06:40:16 +08:00
    因为
    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
        34
    Marszm  
       2021-05-06 08:46:20 +08:00
    这种需要深拷贝.....PHP 这波属于非主流操作
    itechify
        35
    itechify  
    PRO
       2021-05-06 08:49:41 +08:00 via Android
    JAVA 的路过,要不是这样的结果才奇怪
    luckyboy6
        36
    luckyboy6  
       2021-05-06 09:00:52 +08:00
    js 按值传递和 按引用传递的区别 let A = data[0] 时,A 只是一个指针 指向堆区的 data[0] : {x:0,y:1},所以改变 A.x 时改变的是 data[0]。
    meloncc
        37
    meloncc  
       2021-05-06 09:12:50 +08:00
    这个问题与 Javascript 没有关系
    gtanyin
        38
    gtanyin  
       2021-05-06 10:17:02 +08:00
    果然学编程应该从 C 学起,不然连指针的概念都要惊讶半天
    liuky
        39
    liuky  
       2021-05-06 10:57:20 +08:00   1
    楼主高级黑
    misaka19000
        40
    misaka19000  
       2021-05-06 10:59:55 +08:00
    这是来黑 PHP 的吧
    Leiothrix
        41
    Leiothrix  
       2021-05-06 11:19:20 +08:00
    Javascript 浅拷贝和深拷贝的区别,浅拷贝两个对象指向同一个地址,深拷贝是新开栈,两个对象指向不同的地址。可使用 JSON.parse(JSON.stringify(obj))进行深拷贝,修改后不会影响到原对象数据。
    ganbuliao
        42
    ganbuliao  
       2021-05-06 11:34:34 +08:00
    object 对象默认是引用 知道这个就清楚了
    est
        44
    est  
       2021-05-06 12:05:24 +08:00
    楼主低级黑
    zhuweiyou
        45
    zhuweiyou  
       2021-05-06 14:06:48 +08:00
    我感觉你在黑 PHP
    zhengfan2016
        46
    zhengfan2016  
       2021-05-06 15:13:59 +08:00
    为什么我看着觉得很正常,我第一门语言是 python,有没有老哥给我讲讲哪儿不正常 233
    IvanLi127
        47
    IvanLi127  
       2021-05-06 16:47:43 +08:00
    我记得 php 里也有引用传参啊,楼主用的啥版本的 php,代码放出来我们品品?
    MonkeyD1
        48
    MonkeyD1  
       2021-05-06 17:26:45 +08:00
    指针啊
    AoEiuV020
        49
    AoEiuV020  
       2021-05-06 17:29:13 +08:00
    深拷贝,浅拷贝,js 无关,一般都有这些区别,
    vueli
        50
    vueli  
       2021-05-06 17:40:12 +08:00
    前面的 = 是指向
    ruike007
        51
    ruike007  
       2021-05-06 17:42:53 +08:00
    这不是深浅拷贝的问题吗?基础啊,大哥
    karott7
        52
    karott7  
       2021-05-06 17:45:16 +08:00
    这不前端正常操作?赋值对象都是引用
    fescover
        53
    fescover  
       2021-05-06 17:54:43 +08:00
    正常操作,还有更 bt 的,猜猜下面输出什么
    NaN===NaN
    null===null
    null==NaN
    {}==={}
    []===[]
    ""===""
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     1272 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 37ms UTC 17:22 PVG 01:22 LAX 10:22 JFK 13:22
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86