接下來的一系列學(xué)習(xí)筆記都來自于阮一峰老師的JavaScript 教程,重新回顧一遍JavaScript基礎(chǔ)。
本篇是對于這個教程中數(shù)據(jù)類型的相關(guān)總結(jié)。
在學(xué)習(xí)基礎(chǔ)知識之前,先來看一下關(guān)于JavaScript的相關(guān)介紹和特點:
- JavaScript 是一種輕量級的腳本語言。
- 是一種嵌入式語言,本身不提供任何與 I/O相關(guān)的 API,都要靠宿主環(huán)境(host)提供
- 從語法角度看,JavaScript 語言是一種“對象模型”語言
- JavaScript 并不是純粹的“面向?qū)ο笳Z言”,還支持其他編程范式(比如函數(shù)式編程)
下面以提問的方式來對JavaScript的數(shù)據(jù)類型來進(jìn)行學(xué)習(xí)和總結(jié):
JavaScript中有幾種數(shù)據(jù)類型?
JavaScript 的數(shù)據(jù)類型,共有六種,(ES6 又新增了第七種 Symbol 類型的值).
主要包括:數(shù)值(number),字符串(string),布爾值(boolean),undefined,null,以及對象(object)。
其中對象又包括狹義的對象object,函數(shù)和數(shù)組。
判斷數(shù)據(jù)類型的方法?
JavaScript 有三種方法,可以確定一個值到底是什么類型。
- typeof運算符
- instanceof運算符
- Object.prototype.toString方法
不過需要注意,null使用typeof運算符會返回object。
為何typeof 用來檢查一個沒有聲明的變量不報錯?
- 因為 typeof undefined // "undefined"
null 和 undefined 有什么區(qū)別?
- null是一個表示“空”的對象,轉(zhuǎn)為數(shù)值時為0;
- undefined是一個表示"此處無定義"的原始值,轉(zhuǎn)為數(shù)值時為NaN。
布爾值的轉(zhuǎn)化規(guī)則?
如果 JavaScript 預(yù)期某個位置應(yīng)該是布爾值,會將該位置上現(xiàn)有的值自動轉(zhuǎn)為布爾值。轉(zhuǎn)換規(guī)則是除了下面六個值被轉(zhuǎn)為false,其他值都視為true。
- undefined
- null
- false
- 0
- NaN
- ""或''(空字符串)
為何說JavaScript 語言的底層根本沒有整數(shù)?
- JavaScript 內(nèi)部,所有數(shù)字都是以64位浮點數(shù)形式儲存,即使整數(shù)也是如此。所以,1與1.0是相同的,是同一個數(shù)。1 === 1.0 // true
+0 和 -0的區(qū)別?
- 幾乎所有場合,正零和負(fù)零都會被當(dāng)作正常的0。唯一有區(qū)別的場合是,+0或-0當(dāng)作分母,返回的值是不相等的。
數(shù)值NaN有什么特殊性?
- 屬于Number類型,
typeof NaN // 'number' - NaN不等于任何值,包括它本身
- indexOf方法不能判定NaN
- NaN與任何數(shù)(包括它自己)的運算,得到的都是NaN
- NaN在布爾運算時被當(dāng)作false
為何使用isNaN之前,最好判斷一下數(shù)據(jù)類型?
- 因為isNaN只對數(shù)值有效,如果傳入其他值,會被先轉(zhuǎn)成數(shù)值。當(dāng)isNaN為true的值,有可能不是NaN。
如何把長字符串分成多行?
- 在每一行的尾部使用反斜杠
為什么對象的所有鍵名加不加引號都可以?
- 因為對象的所有鍵名都是字符串
如果行首是一個大括號,它到底是表達(dá)式還是語句?
- JavaScript 引擎的做法是,如果遇到這種情況,無法確定是對象還是代碼塊,一律解釋為代碼塊。如果要解釋為對象,最好在大括號前加上圓括號。
delete命令可以刪除對象的所有屬性嗎?
- 只能刪除對象本身的屬性,無法刪除繼承的屬性,即使delete返回true,該屬性依然可能讀取到值。
for...in 循環(huán) 和普通for循環(huán)的區(qū)別
- for...in 遍歷的是對象所有可遍歷(enumerable)的屬性,會跳過不可遍歷的屬性。它不僅遍歷對象自身的屬性,還遍歷繼承的屬性。
- 標(biāo)準(zhǔn)的for循環(huán)中的i是number類型,表示的是數(shù)組的下標(biāo),但是foreach循環(huán)中例如
for(var i in array)的i表示的是數(shù)組的key是string類型 - for循環(huán)是對數(shù)組的元素進(jìn)行循環(huán),而不能引用于非數(shù)組對象
arguments 對象跟數(shù)組的關(guān)系?
- arguments對象包含了函數(shù)運行時的所有參數(shù),具有l(wèi)ength屬性,可以判斷函數(shù)調(diào)用時到底帶幾個參數(shù)
- arguments是類數(shù)組,“類似數(shù)組的對象”的根本特征,就是具有l(wèi)ength屬性。只要有l(wèi)ength屬性,就可以認(rèn)為這個對象類似于數(shù)組
- 雖然arguments很像數(shù)組,但它是一個對象。數(shù)組專有的方法(比如slice和forEach),不能在arguments對象上直接使用
- 將arguments轉(zhuǎn)為真正的數(shù)組:
Array.prototype.slice.call(arguments)
JavaScript 的作用域?
JavaScript 有兩種作用域:全局作用域和函數(shù)作用域
- 全局作用域:變量在整個程序中一直存在,所有地方都可以讀??;
- 函數(shù)作用域,變量只在函數(shù)內(nèi)部存在。
- (ES6 新增了塊級作用域)
函數(shù)本身的作用域在哪里?
函數(shù)本身也是一個值,也有自己的作用域。它的作用域與變量一樣,就是其聲明時所在的作用域,與其運行時所在的作用域無關(guān)。
var a = 'out';
var x = function () {
console.log(a);
};
function f() {
var a = 'inter';
x();
}
f() // 'out'
函數(shù)參數(shù)的傳遞方式?
- 函數(shù)參數(shù)如果是原始類型的值(數(shù)值、字符串、布爾值),傳遞方式是傳值傳遞
- 如果函數(shù)參數(shù)是復(fù)合類型的值(數(shù)組、對象、其他函數(shù)),傳遞方式是傳址傳遞(pass by reference)。因此在函數(shù)內(nèi)部修改參數(shù),將會影響到原始值。
如果在函數(shù)體內(nèi)修改參數(shù)值,會不會影響到函數(shù)外部?
- 如果是原始類型的值(數(shù)值、字符串、布爾值),傳遞方式是傳值傳遞,不影響;
- 如果是復(fù)合類型的值(數(shù)組、對象、其他函數(shù)),傳遞方式是傳址傳遞。在函數(shù)內(nèi)部修改參數(shù),將會影響到原始值;
- 如果函數(shù)內(nèi)部修改的,不是參數(shù)對象的某個屬性,而是替換掉整個參數(shù),這時不會影響到原始值;
什么是閉包?
當(dāng)我們需要獲取到某個函數(shù)f1的局部變量時,我們可以在函數(shù)f1內(nèi)定義一個函數(shù)f2,則在函數(shù)B中可以獲到f1中的局部變量,把函數(shù)f2作為返回值return回來,我們就可以在函數(shù)f1的外部獲取到它的局部變量,此時,這個函數(shù)f2就是閉包。
閉包,即能夠讀取其他函數(shù)內(nèi)部變量的函數(shù)。
閉包的用處:
- 讀取函數(shù)內(nèi)部的變量,讓這些變量始終保持在內(nèi)存中,即閉包可以使得它誕生環(huán)境一直存在。
- 封裝對象的私有屬性和私有方法
為何不能濫用閉包?
- 內(nèi)存消耗會很大,造成網(wǎng)頁的性能問題。
立即調(diào)用的函數(shù)表達(dá)式(IIFE)的作用是什么?
- 不必為函數(shù)命名,避免了污染全局變量
- IIFE 內(nèi)部形成了一個單獨的作用域,可以封裝一些外部無法讀取的私有變量。
數(shù)組的某個位置是空位與某個位置是undefined的區(qū)別?
- 如果是空位,使用數(shù)組的forEach方法、for...in結(jié)構(gòu)、以及Object.keys方法進(jìn)行遍歷,空位都會被跳過。