日韩黑丝制服一区视频播放|日韩欧美人妻丝袜视频在线观看|九九影院一级蜜桃|亚洲中文在线导航|青草草视频在线观看|婷婷五月色伊人网站|日本一区二区在线|国产AV一二三四区毛片|正在播放久草视频|亚洲色图精品一区

分享

JS中的基本類型和引用類型

 Coder編程 2021-10-29

內(nèi)置類型

JS 中七種內(nèi)置類型(null,undefined,boolean,number,string,symbol,object)又分為兩大類型

兩大類型:

  • 基本類型: null,undefined,boolean,number,stringsymbol
  • 引用類型Object: Array ,FunctionDate, RegExp

object.png

存放位置:

  • 基本數(shù)據(jù)類型:基本類型值在內(nèi)存中占據(jù)固定大小,直接存儲(chǔ)在棧內(nèi)存中的數(shù)據(jù)
  • 引用數(shù)據(jù)類型:引用類型在棧中存儲(chǔ)了指針,這個(gè)指針指向堆內(nèi)存中的地址,真實(shí)的數(shù)據(jù)存放在堆內(nèi)存里。

obj.png

值的可變性:

  • 基本數(shù)據(jù)類型: 值不可變,javascript中的原始值(undefined、null、布爾值、數(shù)字和字符串)是不可更改的
  • 引用數(shù)據(jù)類型:引用類型是可以直接改變其值的
//基本數(shù)據(jù)類型
var str = "abc";
console.log(str[1]="f");    // f
console.log(str);           // abc

//引用數(shù)據(jù)類型
 var a = [1,2,3];
a[1] = 5;
    console.log(a[1]); // 5

比較:

  • 基本數(shù)據(jù)類型: 基本類型的比較是值的比較,只要它們的值相等就認(rèn)為他們是相等的
  • 引用數(shù)據(jù)類型: 引用數(shù)據(jù)類型的比較是引用的比較,看其的引用是否指向同一個(gè)對象
//基本數(shù)據(jù)類型
var a = 1;
var b = 1;
console.log(a === b);//true

//引用數(shù)據(jù)類型
var a = [1,2,3];
var b = [1,2,3];
console.log(a === b); // false   
//雖然變量 a 和變量 b 都是表示一個(gè)內(nèi)容為 1,2,3 的數(shù)組,
//但是其在內(nèi)存中的位置不一樣,也就是說變量 a 和變量 b 指向的不是同一個(gè)對象,所以他們是不相等的

Typeof

typeof 對于基本類型,除了 null 都可以顯示正確的類型,對于 null 來說,雖然它是基本類型,但是會(huì)顯示 object,這是一個(gè)存在很久了的 Bug, 這與JavaScript的歷史有關(guān),null被設(shè)計(jì)成可以自動(dòng)轉(zhuǎn)為0

typeof 1 // 'number'
typeof '1' // 'string'
typeof undefined // 'undefined'
typeof true // 'boolean'
typeof Symbol() // 'symbol'
typeof b // b 沒有聲明,但是還會(huì)顯示 undefined

typeof null // 'object'

typeof 對于對象,除了函數(shù)都會(huì)顯示 object

typeof []  // 'object'
typeof {}  // 'object'
typeof console.log // 'function'

獲得一個(gè)變量的正確類型,可以通過 Object.prototype.toString.call(xx)。這樣我們就可以獲得類似 [object Type] 的字符串。

Object.prototype.toString.call(22)    //"[object Number]"

Object.prototype.toString.call('22')  //"[object String]"

Object.prototype.toString.call(null)  //"[object Null]"

Object.prototype.toString.call(undefined) //"[object Undefined]"
Object.prototype.toString.call(a)         //"[object Undefined]"

Object.prototype.toString.call(true)      //"[object Boolean]"

Object.prototype.toString.call({a:1})     //"[object Object]"

typeof的安全防范機(jī)制
檢查 DEBUG 變量是否已被聲明

if (DEBUG) {
  console.log('Debugging is starting');
}
// 報(bào)錯(cuò) ReferenceError 錯(cuò)誤

if (typeof DEBUG !== 'undefined') {
  console.log('Debugging is starting');
}

基本類型

null

  • Null 類型也只有一個(gè)值,就是 null,它的語義表示空值
  • null 是 JavaScript 關(guān)鍵字

常見問題:null 和 undefined 的區(qū)別?
**
null表示"沒有對象",即該處不應(yīng)該有值。典型用法是:

(1) 作為函數(shù)的參數(shù),表示該函數(shù)的參數(shù)不是對象。

(2) 作為對象原型鏈的終點(diǎn)。

Object.getPrototypeOf(Object.prototype)
// null

undefined表示"缺少值",就是此處應(yīng)該有一個(gè)值,但是還沒有定義。典型用法是:

(1)變量被聲明了,但沒有賦值時(shí),就等于undefined。
(2) 調(diào)用函數(shù)時(shí),應(yīng)該提供的參數(shù)沒有提供,該參數(shù)等于undefined。
(3)對象沒有賦值的屬性,該屬性的值為undefined。
(4)函數(shù)沒有返回值時(shí),默認(rèn)返回undefined。

//變量被聲明了,但沒有賦值時(shí),就等于undefined。
var i;
i // undefined 

//調(diào)用函數(shù)時(shí),應(yīng)該提供的參數(shù)沒有提供,該參數(shù)等于undefined。
function f(x){console.log(x)}
f() // undefined

//對象沒有賦值的屬性,該屬性的值為undefined。
var  o = new Object();
o.p // undefined

//函數(shù)沒有返回值時(shí),默認(rèn)返回undefined。
var x = f();
x // undefined

undefined

  • Undefined 類型表示未定義,它的類型只有一個(gè)值,就是 undefined。
  • 任何變量在賦值前是 Undefined 類型、值為 undefined
  • undefined 是一個(gè)變量,而并非是一個(gè)關(guān)鍵字

常見問題:為什么有的編程規(guī)范要求用 void 0 代替 undefined?
因?yàn)?JavaScript 的代碼 undefined 是一個(gè)變量,而并非是一個(gè)關(guān)鍵字,這是 JavaScript 語言公認(rèn)的設(shè)計(jì)失誤之一,所以,我們?yōu)榱吮苊鉄o意中被篡改,建議使用 void 0 來獲取 undefined 值,void 后面隨便跟上一個(gè)便組成表達(dá)式,返回就是 undefined

let a
a === undefined  //true


a      //undefined
void 0 //undefined      void 后面隨便跟上一個(gè)組成表達(dá)式返回就是 undefined

a === void 0  //true

boolean

Boolean 類型有兩個(gè)值, true 和 false

number

JavaScript 中的 Number 類型基本符合 IEEE 754-2008 規(guī)定的雙精度浮點(diǎn)數(shù)規(guī)則,但是 JavaScript 為了表達(dá)幾個(gè)額外的語言場景(比如不讓除以 0 出錯(cuò),而引入了無窮大的概念),規(guī)定了幾個(gè)例外情況:

  • NaN,占用了 9007199254740990,這原本是符合 IEEE 規(guī)則的數(shù)字;
  • Infinity,無窮大;
  • -Infinity,負(fù)無窮大。

常見問題:0.1 + 0.2 不是等于 0.3 么?為什么 JavaScript 里不是這樣的?
這里錯(cuò)誤的不是結(jié)論,而是比較的方法,正確的比較方法是使用 JavaScript 提供的最小精度值:

console.log( Math.abs(0.1 + 0.2 - 0.3) <= Number.EPSILON);

檢查等式左右兩邊差的絕對值是否小于最小精度,才是正確的比較浮點(diǎn)數(shù)的方法。這段代碼結(jié)果就是 true 了。

string

常見問題:字符串有最大長度嗎?

  • String 用于表示文本數(shù)據(jù)。String 有最大長度是 2^53 - 1,這在一般開發(fā)中都是夠用的,但是有趣的是,這個(gè)所謂最大長度,并不完全是你理解中的字符數(shù)
  • String 的意義并非“字符串”,而是字符串的 UTF16 編碼,我們字符串的操作 charAt、charCodeAt、length 等方法針對的都是 UTF16 編碼。所以,字符串的最大長度,實(shí)際上是受字符串的編碼長度影響的

symbol

Symbol 是 ES6 中引入的新類型,它是一切非字符串的對象 key 的集合,在 ES6 規(guī)范中,整個(gè)對象系統(tǒng)被用 Symbol 重塑。

//創(chuàng)建
var mySymbol = Symbol("my symbol");

引用類型

Object

Object 表示對象的意思,它是一切有形和無形物體的總稱。
在 JavaScript 中,對象的定義是“屬性的集合”。
屬性分為數(shù)據(jù)屬性和訪問器屬性,二者都是 key-value 結(jié)構(gòu),key 可以是字符串或者 Symbol 類型

現(xiàn)象:類型轉(zhuǎn)換

四則運(yùn)算符

  • 加法

    • 運(yùn)算中其中一方為字符串,那么就會(huì)把另一方也轉(zhuǎn)換為字符串

    • 如果一方不是字符串或者數(shù)字,那么會(huì)將它轉(zhuǎn)換為數(shù)字或者字符串(具體轉(zhuǎn)換參照對象轉(zhuǎn)原始類型)

  • 其他運(yùn)算符

    • 只要其中一方是數(shù)字,那么另一方就會(huì)被轉(zhuǎn)為數(shù)字
1 + '1' // '11'
true + true // 2
4 + [1,2,3] // "41,2,3"

4 * '3' // 12
4 * [] // 0
4 * [1, 2] // NaN

== 操作符

JavaScript 中的“ == ”運(yùn)算,因?yàn)樵噲D實(shí)現(xiàn)跨類型的比較,它的規(guī)則復(fù)雜到幾乎沒人可以記住, 它屬于設(shè)計(jì)失誤,并非語言中有價(jià)值的部分,很多實(shí)踐中推薦禁止使用“ ==”,而要求程序員進(jìn)行顯式地類型轉(zhuǎn)換后,用 === 比較

比較運(yùn)算符

1.如果是對象,則轉(zhuǎn)換為原始類型再比較值
2.如果是字符串,就通過unicode字符索引來比較

'10'.charCodeAt()  //49
'厲害'.charCodeAt() //21385
'10' < '厲害'       //true
'10' > '厲害'       //false

對象轉(zhuǎn)基本類型

對象在轉(zhuǎn)換類型的時(shí)候,會(huì)調(diào)用內(nèi)置的[[ToPrimitive]]函數(shù)
轉(zhuǎn)換流程:

  1. 如果已經(jīng)是原始類型了,就不需要轉(zhuǎn)換了(因?yàn)榭梢灾貙?code>Symbol.toPrimitive)
  2. 如果需要轉(zhuǎn)換為字符串類型,則直接調(diào)用toString方法,轉(zhuǎn)換為基礎(chǔ)類型的話就返回轉(zhuǎn)換的值。
  3. 如果不是字符串類型,則先調(diào)用valueOf方法,結(jié)果不是基礎(chǔ)類型的話再調(diào)用toString方法
  4. 如果以上處理后,都沒有返回原始類型,就會(huì)報(bào)錯(cuò)

注意:

  • Symbol.toPrimitive ,有該方法時(shí)則只調(diào)用該方法,優(yōu)先級(jí)最高
  • 無symbol時(shí)  valueOf高于 toString
let a = {
  valueOf() {
    return 0;
  },
  toString() {
    return '1';
  },
  [Symbol.toPrimitive]() {
    return 2;
  }
}
1 + a // => 3
'1' + a // => '12'

裝箱轉(zhuǎn)換

JS引擎有意去模糊“對象”和“基本類型”之間的關(guān)系, 遇到"."時(shí),JS引擎會(huì)臨時(shí)幫我們做一層“裝箱轉(zhuǎn)換”,這里就是 new String() 生成一個(gè)“臨時(shí)對象”
裝箱轉(zhuǎn)換,正是把基本類型轉(zhuǎn)換為對應(yīng)的對象,它是類型轉(zhuǎn)換中一種相當(dāng)重要的種類

// Number
1
new Number(1)

// String
'aaa'
new String('aaa')

// Boolean
true
new Boolean(true)

Symbol不能new,我們用特殊的方法把它new出來

Object(Symbol('aaa'))
// 或者
(function(){return this}).call(Symbol('aaa'))

拆箱轉(zhuǎn)換

JS中拆箱轉(zhuǎn)換是調(diào)用了對象的toPrimitive方法來拆箱
它會(huì)依次嘗試使用valueOf toString來轉(zhuǎn)換
如果沒有valueOf toString方法,或者這2個(gè)方法轉(zhuǎn)換出來的都是非基本類型,則報(bào)錯(cuò)


參考鏈接:
https://github.com/amandakelake/blog/issues/34
https:///docs/frontend/#%E5%AF%B9%E8%B1%A1%E8%BD%AC%E5%9F%BA%E6%9C%AC%E7%B1%BB%E5%9E%8B

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請遵守用戶 評(píng)論公約

    類似文章 更多