JS 有哪些數(shù)據(jù)類型,如何判斷這些數(shù)據(jù)類型 ?
7種基本數(shù)據(jù)類型:string, number, boolean, null, undefined, symbol,bigInt
1種引用數(shù)據(jù)類型:Object 對象:Array(數(shù)組)、Function(函數(shù))、Date(時間)等
JS 檢測數(shù)據(jù)類型的 4 種方式
1.typeof:返回值類型為字符串類型;
- 判斷基本數(shù)據(jù)類型時,除null輸出結(jié)果為’object’,其他類型判斷正確
- 判斷引用數(shù)據(jù)類型時,除了判斷函數(shù)會輸出’function’,其它都輸出‘object’,不能區(qū)分引用數(shù)據(jù)類型
2.instanceof:判斷兩個對象是否屬于實例關(guān)系,通過這種關(guān)系來判斷對象是否屬于某一類型;
- 準(zhǔn)確判斷引用數(shù)據(jù)類型,檢測構(gòu)造函數(shù)的prototype屬性是否在某個實例對象的原型鏈上
obj1 instance obj2; // 判斷obj1 是否為obj2的實例
3.constructor:當(dāng)一個函數(shù)F被定義時,js引擎會為F添加prototype原型,在prototype上添加一個constructor屬性,并讓其指向F的引用
4.Object.prototype.toString.call()
- toString() 是Object的原型方法,調(diào)用返回當(dāng)前對象的[object type],type是對象的類型
- Object對象,調(diào)用toString()能返回[object Object]
- Object.prototype.toString.call(‘’) // [object String]
number 類型表示整數(shù)的最大范圍
-2^53 —— 2^53
什么是變量提升 ?
包括變量和函數(shù)在內(nèi)的所有聲明都會在任何代碼被執(zhí)行前首先被處理,這種現(xiàn)象稱為提升
但只有聲明本身會被提升,而賦值或其他運行邏輯會留在原地
javascript并不是嚴(yán)格的自上而下執(zhí)行的語言
1.JavaScript的變量提升是針對var的,而let和const不存在變量提升這一特性
2.通過var定義的變量,在定義語句之前就可以訪問到 值:undefined
3.變量提升就是變量會被提升到作用域的最頂上去,也就是該變量不管是在作用域的哪個地方聲明的,都會提升到作用域的最頂上去
a = 2;
var a;
console.log(a);
typeof(NaN) 返回什么 ?
返回結(jié)果就是 number
NaN === NaN 結(jié)果為 false
如何判斷一個變量的值是 NaN ?
var a = "我" - "你";
isNaN(a) && typeof a === "number";
typeof(null) 為什么返回的是 'object'
- typeof(null) = object 是 JS 在誕生設(shè)計之初留下的歷史遺留 BUG 問題
- 在 JS 中進行數(shù)據(jù)底層存儲的時候是用二進制存儲的,它的前三位是代表存儲的數(shù)據(jù)類型,而 000 是代表 object 類型也就是引用類型的數(shù)據(jù)
- null 正好全是 0,所以它巧妙的符合 object 類型的存儲格式,所以在 typeof 檢測的時候,它才會輸出 object
null 和 undefined的區(qū)別 ?
undefined(未定義):當(dāng)一個變量被定義(聲明)但并沒有賦值時,他的初始值就是 undefined
null(空):表示對一個空對象的引用
- 當(dāng)一個變量定好之后,未來是用來保存對象的引用時,我們可以給他賦初始值為 null
- 當(dāng)一個對象使用完,需要對其進行釋放內(nèi)存時,可以將其值設(shè)置 null (js 會自動垃圾回收)
相同點:
- undefined 和 null 都是基本數(shù)據(jù)類型,保存棧中
- undefined 和 null 轉(zhuǎn)換為 boolean 布爾值都為 false
不同點:
兩者轉(zhuǎn)換為數(shù)字類型時,其值不一樣
Number(undefined); //NaN
Number(null); //0
特殊點:
undefined == null; //true
console.log([] == false) // true
- [] 轉(zhuǎn)換成字符串是'' ,然后'' 轉(zhuǎn)換成數(shù)值是 0
- false 轉(zhuǎn)換成數(shù)值是 0 所以最后比較的值是 0==0 ,結(jié)果為 true
if ([]) {
alert("能彈出嗎?"); // 可以彈出彈窗
}
== 和 === 的區(qū)別?
== 在比較類型不同的變量時,如果兩側(cè)的數(shù)據(jù)類型不同,則會按以下規(guī)則進行相應(yīng)的隱式類型做類型轉(zhuǎn)換
- 對象 --> 字符串 --> 數(shù)值
- 布爾值 --> 數(shù)值
轉(zhuǎn)換后,再比較兩邊的值是否相等,值相等返回 true,不等返回 false;
=== 在比較時,會比較值和類型兩個。只要兩邊值的類型不相等就返回 false
NaN === NaN; // false NaN和任何數(shù)據(jù)都不相等,包括自身
[] == []; // false 比較的是地址
{} == {}; // false 比較的是地址
undefined == null; // true; 特殊情況,記下
const、let、var 區(qū)別
變量提升和暫時性死區(qū):var 存在變量提升,let 和 const 不存在變量提升,所以 let 和 const 會存在暫時性死區(qū)
塊級作用域:var 不存在塊級作用域,let 和 const 存在塊級作用域
重復(fù)聲明:var 允許重復(fù)聲明變量,let 和 const 在同一作用域下不允許重復(fù)聲明變量
修改變量:var 和 let 聲明的變量可以修改,const 是不可以的
使用:const 用來聲明常量,引用類型值。其它情況推薦用 let ,避免用 var
const 定義的值一定是不能改變的嗎
const 實際上保證的,并不是變量的值不得改動,而是變量指向的那個棧內(nèi)存地址所保存的數(shù)據(jù)不得改動
對于簡單類型的數(shù)據(jù)(數(shù)值、字符串、布爾值)值就保存在變量指向的那個棧內(nèi)存地址,因此等同于常量
引用類型的數(shù)據(jù)(主要是對象和數(shù)組)變量指向的棧內(nèi)存地址,保存的只是一個指向?qū)嶋H數(shù)據(jù)的指針
const 只能保證這個指針是固定的(即總是指向另一個固定的地址),至于它指向的數(shù)據(jù)結(jié)構(gòu)是不是可變的,就完全不能控制了
若 const 聲明的是一個引用類型的變量,其引用類型的結(jié)構(gòu)是可以發(fā)生改變的
const 聲明了數(shù)組,還能 push 元素嗎,為什么?
可以,
棧內(nèi)存中的地址,只是一個指向?qū)嶋H數(shù)據(jù)的指針。指針指向堆內(nèi)存中保存的數(shù)據(jù)
const 只能保證棧內(nèi)存中的地址不變,但是堆內(nèi)存中的數(shù)據(jù)如何改變是沒有辦法控制的
push 方法相當(dāng)于是改變了堆內(nèi)存中的數(shù)據(jù)結(jié)構(gòu)
JS 獲取字符串的第 N 個字符
- 字符串函數(shù)直接截?。簊tr.substr(1,1); str.substring(1,2); str.slice(1,2)
str.substring(1,2); str.slice(1,2)表示截取的起始和結(jié)束位置
但是slice入?yún)⒃试S為負(fù),表示截取str的倒數(shù)第幾個字符
str.substr表示截取的起始位置和截取的長度 - 字符串可遍歷性:for…of
- Es6的解構(gòu)賦值
- 正則匹配
const 聲明生成對象的時候,如何使其不可更改
const 聲明的對象只保存其對象的引用地址,只要地址不變,就不會出錯,使用Object.freeze(obj)凍結(jié)obj,可使內(nèi)部屬性不可變,局限是若屬性是對象,該對象內(nèi)屬性還能改變,要求不可變可使用遞歸一層層凍結(jié)
以下這兩種方式的區(qū)別 ?typeof 判斷
const str1 = "abc";
typeof(str1) // 'string'
const str2 = new String("abc");
typeof(str2) // 'object'