摘要:前言面試的時候我們經常會被問答的數(shù)據(jù)類型。大部分情況我們會這樣回答包括基本類型值類型或者原始類型以及的引用類型等我曾經也是這樣回答的,并且一直覺得沒有什么問題。
前言: 面試的時候我們經常會被問答js的數(shù)據(jù)類型。大部分情況我們會這樣回答包括1 、在內存中的位置不同
1、基本類型(值類型或者原始類型): Number、Boolean、String、NULL、Undefined以及ES6的Symbol
2、引用類型:Object、Array、Function、Date等
我曾經也是這樣回答的,并且一直覺得沒有什么問題。
基本類型: 占用空間固定,保存在棧中;
引用類型:占用空間不固定,保存在堆中;
棧(stack)為自動分配的內存空間,它由系統(tǒng)自動釋放;使用一級緩存,被調用時通常處于存儲空間中,調用后被立即釋放。
堆(heap)則是動態(tài)分配的內存,大小不定也不會自動釋放。使用二級緩存,生命周期與虛擬機的GC算法有關
當一個方法執(zhí)行時,每個方法都會建立自己的內存棧,在這個方法內定義的變量將會逐個放入這塊棧內存里,隨著方法的執(zhí)行結束,這個方法的內存棧也將自然銷毀了。因此,所有在方法中定義的變量都是放在棧內存中的;棧中存儲的是基礎變量以及一些對象的引用變量,基礎變量的值是存儲在棧中,而引用變量存儲在棧中的是指向堆中的數(shù)組或者對象的地址,這就是為何修改引用類型總會影響到其他指向這個地址的引用變量。
當我們在程序中創(chuàng)建一個對象時,這個對象將被保存到運行時數(shù)據(jù)區(qū)中,以便反復利用(因為對象的創(chuàng)建成本通常較大),這個運行時數(shù)據(jù)區(qū)就是堆內存。堆內存中的對象不會隨方法的結束而銷毀,即使方法結束后,這個對象還可能被另一個引用變量所引用(方法的參數(shù)傳遞時很常見),則這個對象依然不會被銷毀,只有當一個對象沒有任何引用變量引用它時,系統(tǒng)的垃圾回收機制才會在核實的時候回收它。
2、賦值、淺拷貝、深拷貝對于基本類型值,賦值、淺拷貝、深拷貝時都是復制基本類型的值給新的變量,之后二個變量之間操作不在相互影響。
對于引用類型值,
賦值后二個變量指向同一個地址,一個變量改變時,另一個也同樣改變;
淺拷貝后得到一個新的變量,這個與之前的已經不是指向同一個變量,改變時不會使原數(shù)據(jù)中的基本類型一同改變,但會改變會原數(shù)據(jù)中的引用類型數(shù)據(jù)
深拷貝后得到的是一個新的變量,她的改變不會影響元數(shù)據(jù)
- | 和原數(shù)據(jù)是否指向同一對象 | 第一層數(shù)據(jù)為基本數(shù)據(jù)類型 | 原數(shù)據(jù)中包含子對象 |
---|---|---|---|
賦值 | 是 | 改變會使原數(shù)據(jù)一同改變 | 改變會使原數(shù)據(jù)一同改變 |
淺拷貝 | 否 | 改變不會使原數(shù)據(jù)一同改變 | 改變會使原數(shù)據(jù)一同改變 |
深拷貝 | 否 | 改變不會使原數(shù)據(jù)一同改變 | 改變不會使原數(shù)據(jù)一同改變 |
var obj1 = { "name" : "zhangsan", "age" : "18", "language" : [1,[2,3],[4,5]], }; var obj2 = obj1; var obj3 = shallowCopy(obj1); function shallowCopy(src) { var dst = {}; for (var prop in src) { if (src.hasOwnProperty(prop)) { dst[prop] = src[prop]; } } return dst; } obj2.name = "lisi"; obj3.age = "20"; obj2.language[1] = ["二","三"]; obj3.language[2] = ["四","五"]; console.log(obj1); //obj1 = { // "name" : "lisi", // "age" : "18", // "language" : [1,["二","三"],["四","五"]], //}; console.log(obj2); //obj2 = { // "name" : "lisi", // "age" : "18", // "language" : [1,["二","三"],["四","五"]], //}; console.log(obj3); //obj3 = { // "name" : "zhangsan", // "age" : "20", // "language" : [1,["二","三"],["四","五"]], //};2.1、淺拷貝
數(shù)組常用的淺拷貝方法有slice,concat,Array.from() ,以及es6的析構
var arr1 = [1, 2,{a:1,b:2,c:3,d:4}]; var arr2 = arr1.slice(); var arr3 = arr1.concat(); var arr4 = Array.from(arr1); var arr5 = [...arr1]; arr2[0]=2; arr2[2].a=2; arr3[0]=3; arr3[2].b=3; arr4[0]=4; arr4[2].c=4; arr5[0]=5; arr5[2].d=5; // arr1[1,2,{a:2,b:3,c:4,d:5}] // arr2[2,2,{a:2,b:3,c:4,d:5}] // arr3[3,2,{a:2,b:3,c:4,d:5}] // arr4[4,2,{a:2,b:3,c:4,d:5}] // arr5[5,2,{a:2,b:3,c:4,d:5}]
對象常用的淺拷貝方法Object.assign(),es6析構
var obj1 = { x: 1, y: { m: 1 } }; var obj2 = Object.assign({}, obj1); console.log(obj1) //{x: 1, y: {m: 1}} console.log(obj2) //{x: 1, y: {m: 1}} obj2.x=2; obj2.y.m = 2; //修改obj2.y.m console.log(obj1) //{x: 1, y: {m: 2}} console.log(obj2) //{x: 2, y: {m: 2}}
我們自己實現(xiàn)一個淺拷貝
var obj = { a:1, arr: [2,3] }; var shallowObj = shallowCopy(obj); var shallowCopy = function(obj) { // 只拷貝對象 if (typeof obj !== "object") return; // 根據(jù)obj的類型判斷是新建一個數(shù)組還是對象 var newObj = obj instanceof Array ? [] : {}; // 遍歷obj,并且判斷是obj的屬性才拷貝 for (var key in obj) { if (obj.hasOwnProperty(key)) { newObj[key] = obj[key]; } } return newObj; }2.2、深拷貝
比較簡單粗暴的的做法是使用JSON.parse(JSON.stringify(obj))
var arr = ["old", 1, true, ["old1", "old2"], {old: 1}] var new_arr = JSON.parse( JSON.stringify(arr) ); new_arr[4].old=4; console.log(arr); //["old", 1, true, ["old1", "old2"], {old: 1}] console.log(new_arr); //["old", 1, true, ["old1", "old2"], {old: 4}]
JSON.parse(JSON.stringify(obj)) 看起來很不錯,不過MDN文檔 的描述有句話寫的很清楚:
undefined、任意的函數(shù)以及 symbol 值,在序列化過程中會被忽略(出現(xiàn)在非數(shù)組對象的屬性值中時)或者被轉換成 null(出現(xiàn)在數(shù)組中時)。
但是在平時的開發(fā)中JSON.parse(JSON.stringify(obj))已經滿足90%的使用場景了。
下面我們自己來實現(xiàn)一個
var deepCopy = function(obj) { if (typeof obj !== "object") return; var newObj = obj instanceof Array ? [] : {}; for (var key in obj) { if (obj.hasOwnProperty(key)) { newObj[key] = typeof obj[key] === "object" ? deepCopy(obj[key]) : obj[key]; } } return newObj; }3、參數(shù)的傳遞
所有的函數(shù)參數(shù)都是按值傳遞。也就是說把函數(shù)外面的值賦值給函數(shù)內部的參數(shù),就和把一個值從一個變量賦值給另一個一樣;
基本類型
var a = 2; function add(x) { return x = x + 2; } var result = add(a); console.log(a, result); // 2 4
引用類型
function setName(obj) { obj.name = "laowang"; obj = new Object(); obj.name = "Tom"; } var person = new Object(); setName(person); console.log(person.name); //laowang
很多人錯誤地以為在局部作用域中修改的對象在全局作用域中反映出來就是說明參數(shù)是按引用傳遞的。
但是通過上面的例子可以看出如果person是按引用傳遞的最終的person.name應該是Tom。
實際上當函數(shù)內部重寫obj時,這個變量引用的就是一個局部變量了。而這個變量會在函數(shù)執(zhí)行結束后銷毀。(這是是在js高級程序設計看到的,還不是很清楚)
基本類型用typeof,引用類型用instanceof
特別注意typeof null是"object", null instanceof Object是true;
console.log(typeof "Nicholas"); // "string" console.log(typeof 10); // "number" console.log(typeof true); // "boolean" console.log(typeof undefined); // "undefined" console.log(typeof null); // "object" var items = []; var obj = {}; function reflect(value){ return value; } console.log(items instanceof Array); // true; console.log(obj instanceof Object); // true; console.log(reflect instanceof Function); // true;
Object.prototype.toString.call([]).slice(8, -1)有興趣的同學可以看一下這個是干什么的5、總結
如果有錯誤或者不嚴謹?shù)牡胤剑垊毡亟o予指正,十分感謝。如果喜歡或者有所啟發(fā),歡迎star對作者也是一種鼓勵。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/103146.html
摘要:在反射方面來說,從運行時返回一個的實例時不需要經過強制轉換然后則需要經過轉換才能得到。如果對數(shù)據(jù)的數(shù)量大小已知,操作也非常簡單,也不需要中的大部分方法,也是可以直接使用數(shù)組的。 showImg(https://segmentfault.com/img/bVbruTp?w=1920&h=1080); 我在想每個人在面試的時候都會被問到集合相關的問題,有好大一部分人在回答的時候并沒有那么多...
摘要:背景在開發(fā)好頁面后,如何讓頁面更快更好的運行,是區(qū)分一個程序猿技術水平和視野的一個重要指標。在對這些環(huán)節(jié)進行優(yōu)化之前,我們需要知道如何監(jiān)控這些環(huán)節(jié)花費了多少時間。為了優(yōu)化鏈接的環(huán)節(jié),前端這里還需要對資源使用,雪碧圖,代碼合并等手段。 背景 在開發(fā)好頁面后,如何讓頁面更快更好的運行,是區(qū)分一個程序猿技術水平和視野的一個重要指標。所以面試時,面試官總會問你一個問題,如何進行性能優(yōu)化呢? 如...
摘要:所謂高并發(fā),就是同一時間有很多流量通常指用戶訪問程序的接口頁面及其他資源,解決高并發(fā)就是當流量峰值到來時保證程序的穩(wěn)定性。索引多主多從分布式數(shù)據(jù)庫緩存連接池消息隊列等是從數(shù)據(jù)庫方便考慮如何優(yōu)化性能。 所謂高并發(fā),就是同一時間有很多流量(通常指用戶)訪問程序的接口、頁面及其他資源,解決高并發(fā)就是當流量峰值到來時保證程序的穩(wěn)定性。 我們一般用QPS(每秒查詢數(shù),又叫每秒請求數(shù))來衡量程序的...
閱讀 2080·2021-11-24 10:34
閱讀 3055·2021-11-22 11:58
閱讀 3712·2021-09-28 09:35
閱讀 1724·2019-08-30 15:53
閱讀 2770·2019-08-30 14:11
閱讀 1551·2019-08-29 17:31
閱讀 542·2019-08-26 13:53
閱讀 2141·2019-08-26 13:45