[ JS个人笔记 ] 传值传址&深浅层拷贝—DAY5

传值(call by value)vs传址(call by reference)

  • 基本型别(Number、String、Boolean、null、undefined)属於 call by value。
  • 物件型别(Array、Object、function) 为 call by reference。

1. 传值

当资料为基本型别(如 string、number、boolean、null、undefined),那麽即为赋值。

let a = 10
let b = 10

console.log(a === b) // true

a 更新後不会影响 b

let a = 10
let b = a
a = 20

console.log(a === b) // false

2.传址

当资料为物件型别(Array、Object、function),那麽即为赋址。

var obj1 = { v1: 1 };
var obj2 = { v1: 1 };

console.log( obj1 === obj2 );  // false

因为两者的记忆体位置并不相同。在比较物件型别时,比较的是记忆体位置,而非值。

let obj1 = { v1: 1 };
let obj2 = obj1;

obj1.v1 = 0;

console.log( obj2.v1 );  // 0

obj2.v2 = 2;

console.log( obj1.v2 );  // 2
console.log( obj1 === obj2 );  // true

当我们修改任意物件属性时,另一边的属性也会更动,这是因为两个变数指向相同的记忆体位置,并没有新的物件被复制出来。

注意例外

  • pass by sharing => 当物件被传入function当参数且物件被重新赋址时,物件是不会被影响的。
let obj1 = { v1: 1 };

function change(e){
e = {v1:100};
console.log(obj1)   //{ v1: 1 }
}
change(obj1)
console.log(obj1)   //{ v1: 1 }

若改成以下,则可变更资料

let obj1 = { v1: 1 };

function change(e){
console.log(obj1)   // { v1: 1 }
e.v1=100;
}

change(obj1)
console.log(obj1)  //{ v1: 100 }

浅层拷贝vs深层拷贝

  • 浅层拷贝:复制资料只能复制第一层,因为深层的物件或阵列还是传址,不会完全复制一份
  • 深层拷贝:深拷贝就是完全复制一份,不会有共用记忆体的问题

1.浅层拷贝常见方法

  • 物件的浅拷贝
    • Object.assign()
    • 展开运算子 ...
  • 阵列的浅拷贝
    • slice()
    • concat()
    • forEach + push()
    • map()
    • filter()
    • ... 展开运算子

2.深层拷贝常见方法

  • 利用 JSON 方法:先转 JSON 格式,再转回来。
  • 第三方函式库
    • jQuery 的 $.extend
    • Lodash 的 _.cloneDeep()

更详细内容请参考 竹白笔记

面试题目

1.b 会呈现什麽答案?

let a = {};
let b = a ;
let c = b = {number:1};
c.name = "tom";
console.log(b)

Ans:{number:1,name:tom}
在第三行,c、b皆指向{number:1}
2.请问 console.log(hello.a)、console.log(a)会出现什麽?

function hello(){
  a = 1;
}
hello.a = "hi";
hello();
console.log(hello.a)
console.log(a)

Ans:hi、1

3.console.log(family[0].members.bro)会是?

let family = [{
  name:"tom",
  members:{
    mon:'妈',
    dad:'爸',
    bro:'哥',
  }
}]

let newArray = [];

family.forEach((item)=>{
  newArray.push(item);
})

newArray[0].members.bro = '弟' ;
console.log(family[0].members.bro)

Ans:弟
因浅层拷贝,故深层指向被复制的物件

4.console.log(family.name)、console.log(family.members.mon)会是?

let family = {
  name:"tom",
  members:{
    mon:'妈',
    dad:'爸',
    bro:'哥',
  }
};

let newfamily = {...family};
newfamily.name = 'ted';
newfamily.members.mon = "momy" ;

console.log(family.name)
console.log(family.members.mon)

Ans:tom、momy


<<:  Day 38 (PHP)

>>:  Vue 在 Localhost 开发时出现 “[prerender-spa-plugin] Unable to prerender all routes!” 错误的解决方式

[ Day 9 ] - 函式

函式 一个函式内会包装一段执行的动作,可以被重复的使用 如何宣告函式 宣告函式时,需要使用 func...

[机派X] Day 6 - Linux 没网路,我要怎麽发铁人赛的文章

引言 今天是机派X系列文章的第六天。 昨天介绍了 Linux 的权限管理机制以及一些相关指令,今天要...

JavaScript运算子

在程序设计中必须使用变数或常数储存资料,再将资料经由判断与演算,去得到需要的结果,建构出的内容就是运...

[DAY14]Label进阶使用-Affinity and anti-affinity

把pod部署到特定node上面 k8s的特性来说,基本上部署到k8s一定是会挑资源最轻的那台node...

Day 27:「流浪到淡水!」- 手风琴选单

嘿,今天是怎样? 都没有人交作业,是不是昨天的太小菜一叠了! 今天是昨天的延伸, 但说难也难不到哪...