日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 前端技术 > HTML >内容正文

HTML

栈在前端中的应用,顺便再了解下深拷贝和浅拷贝!

發布時間:2023/12/4 HTML 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 栈在前端中的应用,顺便再了解下深拷贝和浅拷贝! 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

詳解棧在前端中的應用

  • 一、棧是什么
  • 二、棧的應用場景
  • 三、前端與棧:深拷貝與淺拷貝
    • 1、JS數據類型
      • (1)js數據類型的分類
      • (2)js數據類型的定義和存儲方式
      • (3)js數據類型的判斷方式
    • 2、深究淺拷貝和深拷貝
      • (1)淺拷貝
      • (2)深拷貝
  • 四、前端與棧:函數調用堆棧
  • 五、寫在最后

棧 在日常生活中的應用非常廣泛,比如我們最熟悉不過的十進制轉二進制、迷宮求解等等問題。同時,它在前端中的應用也非常廣泛,很多小伙伴都會誤以為 棧 在前端中的應用很少,但殊不知的是,我們寫的每一個程序,基本上都會用到 棧 這個數據結構。比如,函數調用堆棧、數據的深拷貝和淺拷貝……。

所以呢,對于一個前端工程師來說, 棧 結構是一個必學的知識點。在接下來的這篇文章中,將講解關于 棧 在前端中的應用。

一、棧是什么

  • 棧是一種只能在表的一端(棧頂)進行插入和刪除運算的線性表
  • 只能在棧頂運算,且訪問結點時依照后進先出 (LIFO) 或先進后出 (FILO) 的原則。

二、棧的應用場景

  • 需要后進先出的場景;
  • 比如:十進制轉二進制、迷宮求解、馬踏棋盤、判斷字符串是否有效、函數調用堆棧……。

三、前端與棧:深拷貝與淺拷貝

1、JS數據類型

談到堆棧,我們需要先來了解一下關于 js 的兩種數據類型。

(1)js數據類型的分類

首先,JavaScript中的數據類型分為基本數據類型引用數據類型。

了解完分類以后,相信很多小伙伴心里有一個疑惑:這兩個數據類型是什么呢?且在內存中是存放在哪里呢?

(2)js數據類型的定義和存儲方式

基本數據類型:

基本數據類型,是指 Numer 、 Boolean 、 String 、 null 、 undefined 、 Symbol(ES6新增的) 、 BigInt(ES2020) 等值,它們在內存中都是存儲在 中的,即直接訪問該變量就可以得到存儲在 中的對應該變量的值。

若將一個變量的值賦值給另一個變量,則這兩個變量在內存中是獨立的,修改其中任意一個變量的值,不會影響另一個變量。這就是基本數據類型。

引用數據類型:

那引用數據類型呢,是指 Object 、 Array 、 Function 等值,他們在內存中是存在于 棧和堆 當中的,即我們要訪問到引用類型的值時,需要先訪問到該變量在 中的地址(這個地址指向堆中的值),然后再通過這個地址,訪問到存放在 中的數據。這就是引用數據類型。

這樣說可能有點抽象,讓我們用一張圖來理解一下。

從上圖中可以看到, name 和 age 的值都是基本數據類型,所以他們指向程序中 的位置。而 like 是數組類型,也就是引用數據類型,所以在 中,它先存放了一個 like 的地址,之后再把 like 對應的值,存放到 當中。

了解完數據類型和其存儲方式后,在面試中,還有可能被問到如何判斷某一個數據的類型是什么?什么意思呢?比如說,給你一個數字 7 ,需要你來判斷它是什么,我們都知道它是Number類型,但很多時候止步于如何做才能判斷它是一個Number類型。接下來將詳細介紹三種判斷數據類型的方法。

(3)js數據類型的判斷方式

常用判斷方式:typeof、instanceof、===

1)typeof:

定義:返回數據類型的字符串表達(小寫)

用法:typeof + 變量

可以判斷

  • undefined / 數值 / 字符串 / 布爾值 / function ( 返回 undefined / number / string / boolean / function )
  • null 、 object 與 array (null、array、object都會返回 object )

以下給出代碼演示:

<script type="text/javascript">console.log(typeof "Tony"); // 返回 string console.log(typeof 5.01); // 返回 numberconsole.log(typeof false); // 返回 booleanconsole.log(typeof undefined); // 返回 undefinedconsole.log(typeof null); // 返回 objectconsole.log(typeof [1,2,3,4]); // 返回 objectconsole.log(typeof {name:'John', age:34}); // 返回 object </script>

2)instanceof:

定義:判斷對象的具體類型

用法:b instanceof A → b是否是A的實例對象

可以判斷

  • 專門用來判斷對象數據的類型: Object , Array 與 Function

  • 判斷 String ,Number ,Boolean 這三種類型的數據時,直接賦值為 false ,調用構造函數創建的數據為 true

以下給出代碼演示:

<script type="text/javascript">let str = new String("hello world") //console.log(str instanceof String); → truestr = "hello world" //console.log(str instanceof String); → falselet num = new Number(44) //console.log(num instanceof Number); → truenum = 44 //console.log(num instanceof Number); → falselet bool = new Boolean(true) //console.log(bool instanceof Boolean); → truebool = true //console.log(bool instanceof Boolean); → false</script> <script type="text/javascript">let items = []; let object = {}; function reflect(value) {return value; } console.log(items instanceof Array); // true console.log(items instanceof Object); // true console.log(object instanceof Object); // true console.log(object instanceof Array); // false console.log(reflect instanceof Function); // true console.log(reflect instanceof Object); // true </script>

3)===:

可以判斷:undefined,null

以下給出代碼演示:

<script type="text/javascript">let str;console.log(typeof str, str === undefined); //'undefined', truelet str2 = null;console.log(typeof str2, str2 === null); // 'object', true</script>

講到這里,我們了解了js的兩種數據類型,以及兩種數據類型相關的存儲方式和判斷方式。那么,接下來將講解他們在前端中常見的應用,深拷貝和淺拷貝。

2、深究淺拷貝和深拷貝

(1)淺拷貝

1)定義

所謂淺拷貝,就是一個變量賦值給另一個變量,其中一個變量的值改變,則兩個變量的值都變了,即對于淺拷貝來說,是數據在拷貝后,新拷貝的對象內部 仍然有一部分數據 會隨著源對象的變化而變化。

2)代碼演示

// 淺拷貝-分析 function shallowCopy(obj){let copyObj = {};for(let i in obj){copyObj[i] = obj[i];}return copyObj; }// 淺拷貝-實例 let a = {name: '張三',age: 19,like: ['打籃球', '唱歌', '跳舞'] }//將a拷貝給b let b = shallowCopy(a);a.name = '李四'; a.like[0] = '打乒乓球'; console.log(a); /* *{name: '李四',age: 19,like: ['打乒乓球', '唱歌', '跳舞']} */ console.log(b); /* *{name: '張三',age: 19,like: ['打乒乓球', '唱歌', '跳舞']} */

3)圖例

從上面中的代碼可以看到,我們明明把 a 對象拷貝給 b 了,但是 b 最終打印出來的結果部分數據不變,部分數據卻變了。這個時候很多小伙伴就很疑惑了,這究竟是為什么呢?

我們回顧上面所說到的關于 引用數據類型 的知識點,上述代碼中的 b 中的 like ,是一個數組,也就是引用數據類型。我們都知道,引用數據類型的數據是存放于 棧和堆 當中的,所以上述中的 like 數組,我們將它視為一個地址,這個地址存放于 當中,同時,這個地址里面的數據,就指向于 當中。我們來看一下圖例。

從上圖中可以看到,當對 a 中 like 的數據進行改變時,它對應的數據在 中改變。而 b 拷貝后的 like 地址所指向的數據,也是跟 a 一樣在 中的位置。也就是說,a 和 b 中的 like 地址,它們的數據指向 中的同一個位置,所以 b 在拷貝完數據以后,部分數據會隨著 a 的變化而變化。這就是淺拷貝。

講完淺拷貝,接下來來了解深拷貝。

(2)深拷貝

1)定義:深拷貝就是,新拷貝的對象內部所有數據都是 獨立存在 的,不會隨著源對象的改變而改變。

2)深拷貝有兩種方式:遞歸拷貝和利用 JSON 函數進行深拷貝。

  • 遞歸拷貝的實現原理是:對變量中的每個元素進行獲取,若遇到基本類型值,直接獲取;若遇到引用類型值,則繼續對該值內部的每個元素進行獲取。
  • JSON深拷貝的實現原理是:將變量的值轉為字符串形式,然后再轉化為對象賦值給新的變量。

3)局限性:深拷貝的局限性在于,會忽略undefined,不能序列化函數,不能解決循環引用的對象。

4)代碼演示

// 深拷貝-遞歸函數方法分析 function deepCopy(obj){// 判斷是否為引用數據類型if(typeof obj === 'object'){let result = obj.constructor === Array ? [] : {};for(let i in obj){result[i] = typeof obj[i] === 'object' ? deepCopy(obj[i]) : obj[i];}return result;}// 為基本數據類型,直接賦值返回else{return obj;} }// 深拷貝-遞歸函數方法實例 let c = {name:'張三',age:12,like:['打籃球','打羽毛球','打太極'] }let d = deepCopy(c);c.name = '李四'; c.like[0] = '打乒乓球'; console.log(c); /* *{name: '李四',age: 19,like: ['打乒乓球', '打羽毛球', '打太極']} */ console.log(d); /* *{name: '張三',age: 19,like: ['打籃球', '打羽毛球', '打太極']} */ // 深拷貝-JSON函數方法實例 let c = {name: '張三',age: 19,like:['打籃球', '唱歌', '跳舞'] }let d = JSON.parse(JSON.stringify(c));// 注意: JSON函數做深度拷貝時不能拷貝正則表達式,Date,方法函數等c.name = '李四'; c.like[0] = '打乒乓球';console.log(c); /* *{name: '李四',age: 19,like: ['打乒乓球', '唱歌', '跳舞']} */ console.log(d); /* *{name: '張三',age: 19,like: ['打籃球', '唱歌', '跳舞']} */

從上述代碼中可以看到,深拷貝后的數據各自都是獨立存在的,不會隨著源對象的變化而變化,這就是深拷貝。不過值得注意的是,在我們平常的開發中,用的更多的是遞歸函數來進行深拷貝,原因在于遞歸函數方法的靈活性會更強一點。而 JSON 函數方法有很多局限性,在做深度拷貝時不能拷貝正則表達式、Date、方法函數等。

四、前端與棧:函數調用堆棧

在我們平常的開發中,經常會寫很多函數,那函數在執行過程中,其實就是一個調用堆棧。接下來我們用一段代碼來演示。

const func1 = () => {func2();console.log(3); }const func2 = () => {func3();console.log(4); }const func3 = () => {console.log(5); }func1(); //5 4 3

看到這里,很多小伙伴心中可能已經在構思整段代碼的執行順序是什么樣的。接下來用一張圖來展示。

我們都知道, JavaScript 的執行環境是單線程的。所謂單線程是指一次只能完成一個任務,如果有多個任務,就必須排隊,只有當前面一個任務完成時,才能執行后面一個任務,以此類推。上圖中所演示的,即每調用一個函數,如果里面還有新的函數,那么就先把它放到調用堆棧里,等到所有任務都放滿以后,開始依次執行。

而函數調用堆棧是一個典型的棧的數據結構,遵循后進先出原則,當 func1 , func2 , func3 依次放進調用棧后, 遵循后進先出原則 ,那么 func3 函數的內容會先被執行,之后是 func2 ,最后是 func1 。這就是函數調用堆棧。

五、寫在最后

棧在前端中的應用就講到這里啦!棧在我們平常的開發中無處不在,我們寫的每一個程序,基本上都會用到函數調用堆棧。且在前端的面試中,面試官也很喜歡問深拷貝和淺拷貝,大家可以對這塊知識多回顧多實踐。

如果有不理解或者有誤的地方也歡迎私聊我或加我微信指正~

  • 公眾號:星期一研究室
  • 微信:MondayLaboratory

創作不易,如果這篇文章對你有用,記得點個 Star 哦~

總結

以上是生活随笔為你收集整理的栈在前端中的应用,顺便再了解下深拷贝和浅拷贝!的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。