神奇的 Javascript,谁能告诉我为什么
- 0次
- 2021-08-10 01:19:23
- idczone
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 的搞不明白啊
不懂 php 。
{}是 object 类型,A 是做了 data[0]引用,改 A 就是改 data[0]
至少在 PHP 里,A 变量就是个完全独立的值了,只是复制了一份 data[0],直接蒙逼了哇,这操作太神奇了。
php 不知道,但我接触的大语言,都是自定义类型按引用传递,基础类型按值传递的····
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) {
["a"]=>
object(stdClass)(1) {
["ee"]=>
int(3)
}
}
```
搞清楚“对象”和“引用”的关系。列表和变量存的都是引用,而通过引用改变的都是同一个对象。
let A = Object.assign({}, data[0]);
谢谢各位,找了一篇文章学习了一下 https://segmentfault.com/a/1190000014724227
特别是 “列表和变量存的都是引用,而通过引用改变的都是同一个对象。” 精辟
JavaScript 是 pass by reference
全部都是按引用传递,所谓“按值传递”是一种 inline 优化,对程序员是透明的,这些语言没有 deref 操作。
data[0]传递的实际是指针,小伙子 C 没学好吧
实际上传指针才是主流,PHP 那种默认传值,加了&才传指针的,属于少数派
很多语言都这样吧,引用
因为 A 拿到的是 data[0] 的引用
大部分语言,CJava, Javascript, Scala, Python 都是这个逻辑。PHP 是少数。
C++ 程序员不会有这个疑问,因为他们天天和 T* T& T 打交道
php 的数组是值类型,而且是写是复制,大数组赋值起来很快,改到的时候才会真正复制值。
js 的对象 { }(包括数组 [ ] ) 是引用类型,赋值就是传一下引用,都是指向同一个对象的。
我平时基本只用 php,但我感觉 JavaScript 这个才更符合编程本质吧。
没深入研究过 php 这个问题。
。。。除了基础类型,赋值都是引用
感觉楼主在抹黑 php 。
php 里你用对象照样也和 js 得到一样的结果。
无非是 js 里面 {} 表示对象,php 里面 [] 表示数组不是对象。
看得我一脸懵逼,我还以为有啥问题呢
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.
不懂 php,pythoner 感觉没毛病啊……
PHP 里面对象也是引用的,数组不是
这不是最基础的东西?
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 list1 = new List{1,2,3,4};
List list2 = new List(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 list1 = new List{1,2,3,4};
List list2 = list1;
list2[0] = 99;
list2.ForEach(Console.WriteLine); // 99 2 3 4
list1.ForEach(Console.WriteLine); // 99 2 3 4
面试面基础还是很有必要的,即使是八股文
很多人即使自己不知道为什么,也不尝试去弄清楚为什么
这个在 java 、c 里头也是一样的呀。。。传值和传引用嘛
PHP 虽然说是传值,但实际也是引用。然后有个写死复制的机制,就是当发现要修改 A 时,是复制了一份。
省去了需要自己 copy 的问题,比较符合人的思维
等你感受一下 deep clone
data[0] 不一定传引用啊,得看 data 的数据类型,如果是 char* data[],那 data[0] 就传的是指针,如果是 char data[],data[0] 照样传值
虽然 JS 确实很神奇,但是这个是常规操作。
JS 里除了 primitive types 是 pass by value 之外,其余所有的都是 reference
因为
let A = data[0];
let B = data[1];
所以 data 的值变成 [
{x:2, y:3},
{x:2, y:3},
];
因为
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},
];
这种需要深拷贝.....PHP 这波属于非主流操作
JAVA 的路过,要不是这样的结果才奇怪