目錄
- 值和型別
- 八種資料型別
- 原始值和參考值
- 訪問物件的方式
- 相等與全等運算子
- typeof 和 instanceof
- 深拷貝與淺拷貝
值和型別
八種資料型別
undefined、null、boolean、number、string、symbol、bigint、object
原始值和參考值
原始值:按值訪問,值存盤在堆疊中,變數賦值傳遞時會創建該值的副本,兩個變數(復制與被復制)完全獨立,
常見原始值型別:undefined、null、boolean、number、string、symbol、bigint,
let num1 = 5
let num1 = num2
num2 = 4 // num1此時不發生改變
參考值:按參考地址訪問,物件存盤在堆中,其參考地址會存盤在堆疊中指向物件,變數賦值傳遞時會復制其參考地址,兩個變數(復制與被復制)會指向同一個物件,物件資料的修改會同時反映到兩個變數上,
常見參考型別(object):Object、Function、Array、Date、RegExp等,
let obj1 = { a: 1 }
let obj2 = obj1
obj2.a = 4 // 此時發生改變 obj1.a = 1 => obj1.a = 4
訪問物件的方式
.點訪問:不支持變數名稱和特殊字符,物件不存在的屬性,通過點訪問賦值后會創建該屬性,[]中括號訪問:支持變數名稱和特殊字符,物件不存在的屬性,通過中括號訪問賦值后也會創建該屬性,
let a = {}
let key = 'sex'
a.name = '小明' // 物件.屬性名
a['age'] = 22 // 物件['屬性名']
a[key] = '男' // 物件[變數名]
console.log(a) // { name: '小明', age: 22 }
相等與全等運算子
==相等運算子:檢查其兩個運算元是否相等,它會嘗試強制型別轉換并且比較不同型別的運算元,
===全等運算子:檢查它的兩個運算元是否相等, 全等運算子總是認為不同型別的運算元是不同的,
注意:比較物件時,需要考慮其參考地址,也可用toString()方法轉換后比較,
({name: '小紅'}).toString() === ({name: '小米'}).toString() => true
相等和不相等運算子轉換規則:
- 如果有一個運算元是布林值,則在比較相等性之前先將其轉換為數值——
false轉換為0,而true轉換為1; - 如果一個運算元是字串,另一個運算元是數值,在比較相等性之前先將字串轉換為數值;
- 如果一個運算元是物件,另一個運算元不是,則呼叫物件的
valueOf()方法(回傳物件原始值),用得到的基本型別值按照前面的規則進行比較;
相等和不相等運算子比較規則:
null和undefined是相等的,- 要比較相等性之前,不能將
null和undefined轉換成其他任何值, - 如果有一個運算元是
NaN,則相等運算子回傳false,而不相等運算子回傳true,重要提示:即使兩個運算元都是NaN,相等運算子也回傳false;因為按照規則,NaN不等于NaN, - 如果兩個運算元都是物件,則比較它們是不是同一個物件,如果兩個運算元都指向同一個物件,則相等運算子回傳
true;否則,回傳false,
typeof 和 instanceof
typeof 運算子
可推斷型別(回傳值:對應型別字串)如下:
undefined、boolean、stirng、number、object、function、bigint
注意:null值表示一個空物件指標,使用typeof運算子檢測null值時會回傳"object"
instanceof 運算子
可推斷型別(回傳值:布林值)如下:
Object、Array、Date、Function、RegExp、基本包裝型別(Boolean、Number和String)、單體內置物件(Global和Math)
手寫 typeof 和 instanceof 方法
前置知識:原型鏈、toString方法
物件toString方法應用:
- 檢測物件型別
let obj = new Number('5')
Object.prototype.toString.call(obj) // '[object Number]'
- 實作進制轉換
let num = 5
num.toString(2) // '101'
手寫typeof方法
function myTypeof(value) {
return Object.prototype.toString.call(value).slice(8, -1).toLowerCase()
}
手寫instanceof方法:
function myInstanceof(left, right) {
while (1) {
if (left === null) {
return false
}
if (left === right.prototype) {
return true
}
left = left.__proto__
}
}
說明:變數left為實體物件,變數right為建構式,
深拷貝與淺拷貝
淺拷貝
基本概念:物件的淺拷貝是其屬性與拷貝源物件的屬性共享相同參考(指向相同的底層值)的副本,
實作方式:
Object.assign()Object.create()- 擴展運算子:
{ ...obj } Array.concat()Array.slice()Array.from()- lodash API :
_.clone()
let obj1 = { a: 2, b: { s: 4 } }
let obj2 = { ...obj1 }
obj2.a = 3 // obj1.a 不發生改變
obj2.b.s = 5 // obj1.b.s 此時發生改變,值更改為5
注意:以上方式僅對物件第一層作深拷貝,無法對多層級物件實作深拷貝
深拷貝
基本概念:物件的深拷貝是指其屬性與其拷貝的源物件的屬性不共享相同的參考(指向相同的底層值)的副本,
實作方式:
- 遞回實作(簡版)
function cloneDeep(obj) {
let res = Array.isArray(obj[key]) ? [] : {};
for (let key in obj) {
if (obj.hasOwnProperty(key)) {
if (obj[key] && obj[key] === 'object') {
res[key] = cloneDeep(obj[key])
} else {
res[key] = obj[key]
}
}
}
return res
}
-
JSON.parse(JSON.stringify(obj)) -
lodash API :
_.cloneDeep()
let obj1 = { a: 2, b: { s: 4 } }
let obj2 = JSON.parse(JSON.stringify(obj1))
obj2.a = 3 // obj1.a 不發生改變
obj2.b.s = 5 // obj1.b.s 不發生改變
注意:深拷貝會使源和副本互相獨立,即對多層級物件能夠實作深拷貝
參考
MDN-深拷貝
JavaScript高級程式設計(第4版)
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/542488.html
標籤:JavaScript
上一篇:前端使用 fetch() 流式下載.mp4視頻檔案,跟蹤進度
下一篇:轉義字符在前端開發中的詳細介紹
