每日挑战,从Javascript面试题目了解一些你可能忽略的概念 - Day13

tags: ItIron2021 Javascript

前言

我们前两天都把心力分给可爱的闭包,又是换换口味的时间罗! 友情提醒,今天的概念也会在未来继续探讨,所以千万不要错过今天的文章了!

本日题目与解释

请解释call by reference & by value间的差异

防雷防疫,你我有责

thinking-day13

这同样也是个很常见的问题,在进入理论之前我们先做个简单的测试

let a = 5
let b = a
let c = []
let d = c

function modifyArray(arr) {
  arr = {}
}

a = 10

c.push(1)

modifyArray(d)

看完上述的程序码,请问a,b,c,d的数值分别为?

今天破天荒再给你一张防雷图

最终的输出结果为以下

a => 10
b => 5
c => [1]
d => [1]

若你对於其中任何一点感到震惊,那很抱歉你需要继续往下看,至於全部答对的同学可以直接离开,把时间拿去看动漫吧! 最近Netflix上线第二季的新石纪罗! 以下进入正题

简单的说,js中分成两种主要的资料型别,分别为基本型别(primitive value)以及物件(Object)

其中基本型别包括: string, number, bigint(这玩意是新夥伴), boolean, undefined, symbol, and null。
除了这些以外全都是物件,这两种主要的型别在比较、更新与传值的方法有着明显的差别。基本型别为call by value而物件则是call by reference(先别急着吐槽,我知道你想说什麽)

这两种的差别在哪呢? 当你在复制或是比较基本型别时,它在乎的是该值本身,举个简单的例子

let a = 5
let b = a

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

上述的程序码并不是直接把a复制给b,而是先把a的值复制起来再赋值给b,也就是说a & b已经是完全独立、不同的个体,这也就是为什麽一开始的范例会出现a = 10但b = 5的结果。

以上我们用最最最基本的方法(是的,实际上还要再更复杂一些)讲解了什麽是call by value,那物件们的call by reference又是怎麽一回事呢? 简单来说,当你宣告一个物件的时候会在记忆体建立一个新的物件,你可以把它想像成一个盒子,最终你再将你宣告的变数指向那个盒子。 配合一个简单的例子来看吧!

let arr1 = []
let arr2 = arr1

上方的程序码依序发生了以下的事情

  1. 建立一个新盒子,并把arr1指向这个盒子
  2. 将arr2指向arr1目前指向的盒子

也就是说,call by reference是一种用引用(或是参照)的方式在做值的传递,上述的例子中两个阵列都指向同一个盒子,所以你对盒子做的任何操作都会影响到两个阵列! 这也就是为什麽范例中明明是对c操作,但d最终仍有完全相同的结果。

最後我们来看一个最难懂的部分

let arr = []

function modifyArr(arr) {
  arr = [1,2,3]
}

modifyArr(arr)
console.log(arr) // []

这就奇怪了,我们刚刚才说过物件是call by reference,那这样的资料更新为什麽没有影响到arr阵列? 原因在於...js其实并不是真正的call by reference,有一派的说法是实际上js属於call by sharing,名词的部分我就不做解释了,一样你们自己去查。

简单来说call by sharing的特点是,当该参数在函数中被重新赋值时,它其实会建立一个传入参数的复制品并将其重新赋值,也就是说,一旦你选择重新赋值传进来的参数,传进来的参数与原始的资料就完全没有任何关系了,因此会造成范例中看到的结果,arr仍是一个空阵列。
我知道这有点难懂,不是我想偷懒,不过这系列文章本就不是要深入探讨每一个观念,你可以透过我提供的关键字去做搜寻!

本日核心观念与总结

核心观念

call by value、call by reference、call by sharing

总结

  • 了解js中主要分为基本型别与物件
  • 了解基本型别属於call by value
  • 了解由於call by reference,相同参照的物件会互相影响
  • 了解物件属於call by sharing (也有一派说法是不管是不是物件都是call by sharing)

本文章同步发布於个人部落格,有兴趣的朋友也可以来逛逛~!

参考文章

关於今天的主题,中文资源部分我很推荐一篇文章:重新认识 JavaScript: Day 05 JavaScript 是「传值」或「传址」?,算是中文资源中讲得相当不错的一篇文章,当时也帮了我不少忙。


<<:  14 实作出牌倒数 诶这是什麽放置游戏

>>:  Day 22: Recurrent Neural Network — 循环精神网路初探(上)

GoLang 语言

https://wolkesau.medium.com/golang-语言-d86e8a781fb3...

Day21:今天来聊一下Azure Sentinel 介绍

传统的安全性资讯与事件管理(SIEM)系统通常需要很长的时间 来安装及设定。这类系统在设计时也不一定...

资料结构与演算法

** 这主题博大精深这里先进行初步的介绍** 资料结构 资料结构可以想像成容器,每个物品都有适合放置...

浅谈Web应用系统安全 - 骇客攻防战

跨站脚本攻击(XSS) 攻击 XXS就是透过网页没有适当筛选、处理文字造成的漏洞 例如有用户将<...

Day28 Gin with SMTP Server

What is an SMTP Server? SMTP 全名为Simple Mail Transf...