[ 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!” 错误的解决方式

ASP.NET MVC 从入门到放弃(Day27)-IIS 发布介绍

接下来讲讲如何发布程序 1.首先在专案上按右键点发布 2.目标选择资料夹 3.选择资料夹位置 (一般...

在 Lubuntu 18.04 上安装 CodeBlocks IDE 17.12

写程序,弄个 IDE 真的会方便不少,如果您是要在 ubuntu 20.04 上面使用 Code::...

[DAY-30] 最後一幕只是故事的结尾,你也知道故事没有结尾是行不通的。

And So It Is. 其实想说一些三八的话,BUT 没有 FU XDDD 好啦三十天 ya!...

Golang - html template + wkhtmltopdf生成PDF

以前很菜的时候收过这个需求 真心很讨厌PDF,因为要自己算座标和设定一堆东西 後来这个需求就被弃置了...

[Day1]C# 鸡础观念- C#简介

故事时间 在很久很久以前世界上诞生了C语言, 这是个非常灵活又高效的语言, 在不久之後他的後代C++...