這裡給大家分享我在網上總結出來的一些知識,希望對大家有所幫助 1. new操作符的實現原理 new操作符的執行過程: (1)首先創建了一個新的空對象 (2)設置原型,將對象的原型設置為函數的 prototype 對象。 (3)讓函數的 this 指向這個對象,執行構造函數的代碼(為這個新對象添加屬性 ...
這裡給大家分享我在網上總結出來的一些知識,希望對大家有所幫助
1. new操作符的實現原理
new操作符的執行過程:
(1)首先創建了一個新的空對象
(2)設置原型,將對象的原型設置為函數的 prototype 對象。
(3)讓函數的 this 指向這個對象,執行構造函數的代碼(為這個新對象添加屬性)
(4)判斷函數的返回值類型,如果是值類型,返回創建的對象。如果是引用類型,就返回這個引用類型的對象。
具體實現:
function objectFactory() { let newObject = null; let constructor = Array.prototype.shift.call(arguments); let result = null; // 判斷參數是否是一個函數 if (typeof constructor !== "function") { console.error("type error"); return; } // 新建一個空對象,對象的原型為構造函數的 prototype 對象 newObject = Object.create(constructor.prototype); // 將 this 指向新建對象,並執行函數 result = constructor.apply(newObject, arguments); // 判斷返回對象 let flag = result && (typeof result === "object" || typeof result === "function"); // 判斷返回結果 return flag ? result : newObject; } // 使用方法 objectFactory(構造函數, 初始化參數);
2. map和Object的區別
3.Map3. map和weakMap的區別
map本質上就是鍵值對的集合,但是普通的Object中的鍵值對中的鍵只能是字元串。而ES6提供的Map數據結構類似於對象,但是它的鍵不限制範圍,可以是任意類型,是一種更加完善的Hash結構。如果Map的鍵是一個原始數據類型,只要兩個鍵嚴格相同,就視為是同一個鍵。
實際上Map是一個數組,它的每一個數據也都是一個數組,其形式如下:
const map = [ ["name","張三"], ["age",18], ]
Map數據結構有以下操作方法:
- size:
map.size
返回Map結構的成員總數。 - set(key,value):設置鍵名key對應的鍵值value,然後返回整個Map結構,如果key已經有值,則鍵值會被更新,否則就新生成該鍵。(因為返回的是當前Map對象,所以可以鏈式調用)
- get(key):該方法讀取key對應的鍵值,如果找不到key,返回undefined。
- has(key):該方法返回一個布爾值,表示某個鍵是否在當前Map對象中。
- delete(key):該方法刪除某個鍵,返回true,如果刪除失敗,返回false。
- clear():map.clear()清除所有成員,沒有返回值。
Map結構原生提供是三個遍歷器生成函數和一個遍歷方法
- keys():返回鍵名的遍歷器。
- values():返回鍵值的遍歷器。
- entries():返回所有成員的遍歷器。
- forEach():遍歷Map的所有成員。
const map = new Map([ ["foo",1], ["bar",2], ]) for(let key of map.keys()){ console.log(key); // foo bar } for(let value of map.values()){ console.log(value); // 1 2 } for(let items of map.entries()){ console.log(items); // ["foo",1] ["bar",2] } map.forEach( (value,key,map) => { console.log(key,value); // foo 1 bar 2 })
(2)WeakMap
WeakMap 對象也是一組鍵值對的集合,其中的鍵是弱引用的。其鍵必須是對象,原始數據類型不能作為key值,而值可以是任意的。
該對象也有以下幾種方法:
- set(key,value):設置鍵名key對應的鍵值value,然後返回整個Map結構,如果key已經有值,則鍵值會被更新,否則就新生成該鍵。(因為返回的是當前Map對象,所以可以鏈式調用)
- get(key):該方法讀取key對應的鍵值,如果找不到key,返回undefined。
- has(key):該方法返回一個布爾值,表示某個鍵是否在當前Map對象中。
- delete(key):該方法刪除某個鍵,返回true,如果刪除失敗,返回false。
其clear()方法已經被棄用,所以可以通過創建一個空的WeakMap並替換原對象來實現清除。
WeakMap的設計目的在於,有時想在某個對象上面存放一些數據,但是這會形成對於這個對象的引用。一旦不再需要這兩個對象,就必須手動刪除這個引用,否則垃圾回收機制就不會釋放對象占用的記憶體。
而WeakMap的鍵名所引用的對象都是弱引用,即垃圾回收機制不將該引用考慮在內。因此,只要所引用的對象的其他引用都被清除,垃圾回收機制就會釋放該對象所占用的記憶體。也就是說,一旦不再需要,WeakMap 裡面的鍵名對象和所對應的鍵值對會自動消失,不用手動刪除引用。
總結:
- Map 數據結構。它類似於對象,也是鍵值對的集合,但是“鍵”的範圍不限於字元串,各種類型的值(包括對象)都可以當作鍵。
- WeakMap 結構與 Map 結構類似,也是用於生成鍵值對的集合。但是 WeakMap 只接受對象作為鍵名( null 除外),不接受其他類型的值作為鍵名。而且 WeakMap 的鍵名所指向的對象,不計入垃圾回收機制。
4. JavaScript有哪些內置對象
全局的對象( global objects )或稱標準內置對象,不要和 "全局對象(global object)" 混淆。這裡說的全局的對象是說在
全局作用域里的對象。全局作用域中的其他對象可以由用戶的腳本創建或由宿主程式提供。
標準內置對象的分類:
(1)值屬性,這些全局屬性返回一個簡單值,這些值沒有自己的屬性和方法。
例如 Infinity、NaN、undefined、null 字面量
(2)函數屬性,全局函數可以直接調用,不需要在調用時指定所屬對象,執行結束後會將結果直接返回給調用者。
例如 eval()、parseFloat()、parseInt() 等
(3)基本對象,基本對象是定義或使用其他對象的基礎。基本對象包括一般對象、函數對象和錯誤對象。
例如 Object、Function、Boolean、Symbol、Error 等
(4)數字和日期對象,用來表示數字、日期和執行數學計算的對象。
例如 Number、Math、Date
(5)字元串,用來表示和操作字元串的對象。
例如 String、RegExp
(6)可索引的集合對象,這些對象表示按照索引值來排序的數據集合,包括數組和類型數組,以及類數組結構的對象。例如 Array
(7)使用鍵的集合對象,這些集合對象在存儲數據時會使用到鍵,支持按照插入順序來迭代元素。
例如 Map、Set、WeakMap、WeakSet
(8)矢量集合,SIMD 矢量集合中的數據會被組織為一個數據序列。
例如 SIMD 等
(9)結構化數據,這些對象用來表示和操作結構化的緩衝區數據,或使用 JSON 編碼的數據。
例如 JSON 等
(10)控制抽象對象
例如 Promise、Generator 等
(11)反射
例如 Reflect、Proxy
(12)國際化,為了支持多語言處理而加入 ECMAScript 的對象。
例如 Intl、Intl.Collator 等
(13)WebAssembly
(14)其他
例如 arguments
總結:
js 中的內置對象主要指的是在程式執行前存在全局作用域里的由 js 定義的一些全局值屬性、函數和用來實例化其他對象的構造函數對象。一般經常用到的如全局變數值 NaN、undefined,全局函數如 parseInt()、parseFloat() 用來實例化對象的構造函數如 Date、Object 等,還有提供數學計算的單體內置對象如 Math 對象。
5. 常用的正則表達式有哪些?
// (1)匹配 16 進位顏色值 var regex = /#([0-9a-fA-F]{6}|[0-9a-fA-F]{3})/g; // (2)匹配日期,如 yyyy-mm-dd 格式 var regex = /^[0-9]{4}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])$/; // (3)匹配 qq 號 var regex = /^[1-9][0-9]{4,10}$/g; // (4)手機號碼正則 var regex = /^1[34578]\d{9}$/g; // (5)用戶名正則 var regex = /^[a-zA-Z\$][a-zA-Z0-9_\$]{4,16}$/;
6. 對JSON的理解
JSON 是一種基於文本的輕量級的數據交換格式。它可以被任何的編程語言讀取和作為數據格式來傳遞。
在項目開發中,使用 JSON 作為前後端數據交換的方式。在前端通過將一個符合 JSON 格式的數據結構序列化為
JSON 字元串,然後將它傳遞到後端,後端通過 JSON 格式的字元串解析後生成對應的數據結構,以此來實現前後端數據的一個傳遞。
因為 JSON 的語法是基於 js 的,因此很容易將 JSON 和 js 中的對象弄混,但是應該註意的是 JSON 和 js 中的對象不是一回事,JSON 中對象格式更加嚴格,比如說在 JSON 中屬性值不能為函數,不能出現 NaN 這樣的屬性值等,因此大多數的 js 對象是不符合 JSON 對象的格式的。
在 js 中提供了兩個函數來實現 js 數據結構和 JSON 格式的轉換處理,
- JSON.stringify 函數,通過傳入一個符合 JSON 格式的數據結構,將其轉換為一個 JSON 字元串。如果傳入的數據結構不符合 JSON 格式,那麼在序列化的時候會對這些值進行對應的特殊處理,使其符合規範。在前端向後端發送數據時,可以調用這個函數將數據對象轉化為 JSON 格式的字元串。
- JSON.parse() 函數,這個函數用來將 JSON 格式的字元串轉換為一個 js 數據結構,如果傳入的字元串不是標準的 JSON 格式的字元串的話,將會拋出錯誤。當從後端接收到 JSON 格式的字元串時,可以通過這個方法來將其解析為一個 js 數據結構,以此來進行數據的訪問。
7. JavaScript腳本延遲載入的方式有哪些?
延遲載入就是等頁面載入完成之後再載入 JavaScript 文件。 js 延遲載入有助於提高頁面載入速度。
一般有以下幾種方式:
- defer 屬性:給 js 腳本添加 defer 屬性,這個屬性會讓腳本的載入與文檔的解析同步解析,然後在文檔解析完成後再執行這個腳本文件,這樣的話就能使頁面的渲染不被阻塞。多個設置了 defer 屬性的腳本按規範來說最後是順序執行的,但是在一些瀏覽器中可能不是這樣。
- async 屬性:給 js 腳本添加 async 屬性,這個屬性會使腳本非同步載入,不會阻塞頁面的解析過程,但是當腳本載入完成後立即執行 js 腳本,這個時候如果文檔沒有解析完成的話同樣會阻塞。多個 async 屬性的腳本的執行順序是不可預測的,一般不會按照代碼的順序依次執行。
- 動態創建 DOM 方式:動態創建 DOM 標簽的方式,可以對文檔的載入事件進行監聽,當文檔載入完成後再動態的創建 script 標簽來引入 js 腳本。
- 使用 setTimeout 延遲方法:設置一個定時器來延遲載入js腳本文件
- 讓 JS 最後載入:將 js 腳本放在文檔的底部,來使 js 腳本儘可能的在最後來載入執行。
8. JavaScript 類數組對象的定義?
一個擁有 length 屬性和若幹索引屬性的對象就可以被稱為類數組對象,類數組對象和數組類似,但是不能調用數組的方法。常見的類數組對象有 arguments 和 DOM 方法的返回結果,還有一個函數也可以被看作是類數組對象,因為它含有 length 屬性值,代表可接收的參數個數。
常見的類數組轉換為數組的方法有這樣幾種:
(1)通過 call 調用數組的 slice 方法來實現轉換
Array.prototype.slice.call(arrayLike);
(2)通過 call 調用數組的 splice 方法來實現轉換
Array.prototype.splice.call(arrayLike, 0);
(3)通過 apply 調用數組的 concat 方法來實現轉換
Array.prototype.concat.apply([], arrayLike);
(4)通過 Array.from 方法來實現轉換
Array.from(arrayLike)
9. 數組有哪些原生方法?
- 數組和字元串的轉換方法:toString()、toLocalString()、join() 其中 join() 方法可以指定轉換為字元串時的分隔符。
- 數組尾部操作的方法 pop() 和 push(),push 方法可以傳入多個參數。
- 數組首部操作的方法 shift() 和 unshift() 重排序的方法 reverse() 和 sort(),sort() 方法可以傳入一個函數來進行比較,傳入前後兩個值,如果返回值為正數,則交換兩個參數的位置。
- 數組連接的方法 concat() ,返回的是拼接好的數組,不影響原數組。
- 數組截取辦法 slice(),用於截取數組中的一部分返回,不影響原數組。
- 數組插入方法 splice(),影響原數組查找特定項的索引的方法,indexOf() 和 lastIndexOf() 迭代方法 every()、some()、filter()、map() 和 forEach() 方法
- 數組歸併方法 reduce() 和 reduceRight() 方法
10. Unicode、UTF-8、UTF-16、UTF-32的區別?
(1)Unicode
在說Unicode
之前需要先瞭解一下ASCII
碼:ASCII 碼(American Standard Code for Information Interchange
)稱為美國標準信息交換碼。
- 它是基於拉丁字母的一套電腦編碼系統。
- 它定義了一個用於代表常見字元的字典。
- 它包含了"A-Z"(包含大小寫),數據"0-9" 以及一些常見的符號。
- 它是專門為英語而設計的,有128個編碼,對其他語言無能為力
ASCII
碼可以表示的編碼有限,要想表示其他語言的編碼,還是要使用Unicode
來表示,可以說Unicode
是ASCII
的超集。
Unicode
全稱 Unicode Translation Format
,又叫做統一碼、萬國碼、單一碼。Unicode
是為瞭解決傳統的字元編碼方案的局限而產生的,它為每種語言中的每個字元設定了統一併且唯一的二進位編碼,以滿足跨語言、跨平臺進行文本轉換、處理的要求。
Unicode
的實現方式(也就是編碼方式)有很多種,常見的是UTF-8、UTF-16、UTF-32和USC-2。
(2)UTF-8
UTF-8
是使用最廣泛的Unicode
編碼方式,它是一種可變長的編碼方式,可以是1—4個位元組不等,它可以完全相容ASCII
碼的128個字元。
註意: UTF-8
是一種編碼方式,Unicode
是一個字元集合。
UTF-8
的編碼規則:
- 對於單位元組的符號,位元組的第一位為0,後面的7位為這個字元的
Unicode
編碼,因此對於英文字母,它的Unicode
編碼和ACSII
編碼一樣。 - 對於n位元組的符號,第一個位元組的前n位都是1,第n+1位設為0,後面位元組的前兩位一律設為10,剩下的沒有提及的二進位位,全部為這個符號的
Unicode
碼 。
來看一下具體的Unicode
編號範圍與對應的UTF-8
二進位格式 :
找到該Unicode
編碼的所在的編號範圍,進而找到與之對應的二進位格式那該如何通過具體的Unicode
編碼,進行具體的UTF-8
編碼呢?步驟如下:
- 將
Unicode
編碼轉換為二進位數(去掉最高位的0) - 將二進位數從右往左一次填入二進位格式的
X
中,如果有X
未填,就設為0
來看一個實際的例子:
“馬” 字的Unicode
編碼是:0x9A6C
,整數編號是39532
(1)首選確定了該字元在第三個範圍內,它的格式是 1110xxxx 10xxxxxx 10xxxxxx
(2)39532對應的二進位數為1001 1010 0110 1100
(3)將二進位數填入X中,結果是:11101001 10101001 10101100
(3)UTF-16
1. 平面的概念
在瞭解UTF-16
之前,先看一下平面的概念:
Unicode
編碼中有很多很多的字元,它並不是一次性定義的,而是分區進行定義的,每個區存放65536(216)個字元,這稱為一個平面,目前總共有17 個平面。
最前面的一個平面稱為基本平面,它的碼點從0 — 216-1,寫成16進位就是U+0000 — U+FFFF
,那剩下的16個平面就是輔助平面,碼點範圍是 U+10000—U+10FFFF
。
2. UTF-16 概念:
UTF-16
也是Unicode
編碼集的一種編碼形式,把Unicode
字元集的抽象碼位映射為16位長的整數(即碼元)的序列,用於數據存儲或傳遞。Unicode
字元的碼位需要1個或者2個16位長的碼元來表示,因此UTF-16
也是用變長位元組表示的。
3. UTF-16 編碼規則:
- 編號在
U+0000—U+FFFF
的字元(常用字元集),直接用兩個位元組表示。 - 編號在
U+10000—U+10FFFF
之間的字元,需要用四個位元組表示。
4. 編碼識別
那麼問題來了,當遇到兩個位元組時,怎麼知道是把它當做一個字元還是和後面的兩個位元組一起當做一個字元呢?
UTF-16
編碼肯定也考慮到了這個問題,在基本平面內,從 U+D800 — U+DFFF
是一個空段,也就是說這個區間的碼點不對應任何的字元,因此這些空段就可以用來映射輔助平面的字元。
輔助平面共有 220 個字元位,因此表示這些字元至少需要 20 個二進位位。UTF-16
將這 20 個二進位位分成兩半,前 10 位映射在 U+D800 — U+DBFF
,稱為高位(H),後 10 位映射在 U+DC00 — U+DFFF
,稱為低位(L)。這就相當於,將一個輔助平面的字元拆成了兩個基本平面的字元來表示。
因此,當遇到兩個位元組時,發現它的碼點在 U+D800 —U+DBFF
之間,就可以知道,它後面的兩個位元組的碼點應該在 U+DC00 — U+DFFF
之間,這四個位元組必須放在一起進行解讀。
5. 舉例說明
以 "