java h5 交互 传数组, JS数组/对象的值为什么变了?你需要深入理解对象的值传递...

复杂的对象数据处理后,可能发现某个对象值变了,有时却不变。

上述问题往往会困扰 JS初学者,甚至老手也不一定能说出所以然。

本文将对此进行一定深层探究 —— 深入理解 JS中的对象的值传递。

Why

引入概念前,先出四道题(各题互不关联),可先试着写下,最下面公布答案哦~

let a = [1,2]

let b = a

a = [3, 4]

console.log(b)

复制代码

let a = [1,2]

let b = a

a[0] = 3

console.log(b)

复制代码

let a = [1,2]

let b = a

a = [3,4]

a[0] = 3

console.log(b)

复制代码

let a = [1,2]

let b = a

a.pop()

console.log(b)

复制代码

附上 TS Playground,其实一个改改就够了,顺手都 share 如下:

Example 1 Example 2 Example 3 Example 4

66ed8a2b50f7d9404cef71394e326cec.png

如果你可以全对 💯,那证明对 JS 对象值的传递理解还算扎实。

如果其中有错误,那我觉得你有必要继续看下去了 (づ。◕‿‿◕。)づ

8b2d9d4cf0a8dc658fefdf6d636a31c9.gif

What

在解释上述 🌰 分析之前,我们需要复习一下 JS 的基础数据类型:

🙌 8 种(7 种原始类型 以及 对象)更多参考 MDN JavaScript 数据类型

原始类型:Number、BigInt、String、Boolean、Null、Undefined 和 ES6中的 Symbol

复杂类型:Object对象(数组是其中一种内置对象,函数等都是特殊的对象类型)

!!!注意:原始类型是不可变的(immutable),只有对象是可变的(mutable)。

我们再来具体理清下 = 赋值操作具体执行了什么?

原始类型:值的拷贝/传递

复杂类型:引用地址的拷贝;或称共享传递(call by sharing)名称不重要,领会 ↓ 即可

有了以上理论理解的基础,我们再来依次分析下之前的 🌰

4d9a75667eaed90f5ae38fb966be670b.png

直接上图,应该不难理解了吧,当执行了 a = [3,4] ,之后,a 和 b 变量的引用根本变了,此时不论 a如何改变其值,都不再影响 b。

但是,a 和 b 共享引用(传递)时(即 Example2、4),a 的变化会直接影响 b

.pop() 或者 .push 等方法会直接更改数组,这里就不多加引申了。

继续举个简单的 🌰 ,看看你的掌握程度,以下会输出什么? (快速回答哦 (๑•̀ㅂ•́)و✧ )

let a = [1,2]

let b = a

b = []

console.log(a.length == 0)

let c = [] // TS类型强定义,TS Playground 中为 let c:number[] = []

console.log(b, c)

console.log(b == c)

let x = {}

let y = {}

console.log(x == y)

复制代码

TS Playground

看看是否与你所想一致?为什么就不说了哦

75b2cf54289be036270bc7b4a11191f0.png

最后,出个可能会作为面试题的 🌰

function changeAgeAndReference(person){

person.age = 18;

person = {

name: "Anna",

age: 16

};

return person;

}

let personObj1 = {

name: "Olaf",

age: 1000

};

console.log(personObj1); // -> ?

let personObj2 = changeAgeAndReference(personObj1);

console.log(personObj1); // -> ?

console.log(personObj2); // -> ?

复制代码

TS playground

🎉 如果真面试到,能否回答正确并且解释出所以然? 有兴趣的可以 Play 研究下(相对比较基础),但实际业务代码这么写会死得很惨 (-"-怒)

How

对象的实际应用

JS 中,数组、函数等皆为对象,那我们通常会怎么应用对象呢?举个 🌰

class student{ // 构造函数

name: string

constructor(myname){

this.name = myname;

}

sayHi(){

console.log("Hi, I'm " + this.name)

}

}

let s1 = new student("Elsa")

let s2 = s1 // ❌ 这样引用,s2的更改会直接影响s1

s2.name = "Anna"

s1.sayHi()

let s3 = new student("Olaf") // ✅ 通常会用 new 来创建一个新的对象

s3.sayHi()

复制代码

TS Playground

对于 TS 开发者,Interface 不失为一种好方式,有兴趣的参考 TS 的 Interface 了解一下?

浅拷贝 & 深拷贝

🎉 继续敲黑板,面试问到相关问题的几率 50%+,问答开始:

Q:浅拷贝、深拷贝是什么?有什么区别?

🙌 浅拷贝只复制一层对象的属性,而深拷贝则递归复制了所有层级。

Q:具体有哪些应用场景?什么时候用浅拷贝、什么时候用深拷贝?

有一份 Object 数据,你打算对它进行处理,但又希望拷贝一份副本出来,方便数据对比和恢复数据等。

浅拷贝有效性针对的是单一层级对象,比如简单的一维数组等等。

深拷贝有效性针对的是多层级对象,比如后端返回的Json对象等。

Q:如何在 JS 中实现浅拷贝 & 深拷贝?

🙌 本来想自己总结几种常用方式的,深拷贝和浅拷贝 高赞文章已有,太棒了~

个人通常使用扩展运算符 ... 来实现浅拷贝,

使用JSON.parse(JSON.stringify()) 来深拷贝

Summary

原始类型是不可变的(immutable),只有对象是可变的(mutable)

对象赋值 = 为引用地址的拷贝,改变会影响原对象(实际开发中,需慎用)

需要掌握对象的实际应用方式 & 浅拷贝和深拷贝

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值