第一章 類型

第一章 類型

js中的類型

js語言中的類型分為基本類型和對(duì)象類型

類型有:(除對(duì)象外,其他統(tǒng)稱為基本類型)

  • 空值(null)
  • 未定義(undefined)
  • 布爾值(boolean)
  • 數(shù)字(number)
  • 字符串(string)
  • 對(duì)象(object)
  • 符號(hào)(symbol,ES6中新增)

如何判別值的類型

typeof運(yùn)算符可以查看值的類型,他返回的是類型的字符串值,但是這七種值和他們的字符串值并不一一對(duì)應(yīng)

typeof undefined === "undefined"; // true

typeof true === "boolean"; // true

typeof 42 === "number"; // true

typeof "42" === "string"; // true

typeof { life: 42 } === "object"; // true

// ES6中新加入的類型

typeof Symbol() === "symbol"; // true

以上六種判別均正常,但是null例外


typeof null === "object"; // true

我們需要使用復(fù)合條件來檢測(cè) null 值的類型


var a = null;
(!a && typeof a === "object"); // true

還有一種情況:


typeof function a(){ /* .. */ } === "function"; // true
typeof [1,2,3] === "object"; // true

undefined 和 undeclared

變量在未持有值的時(shí)候?yàn)?undefined。此時(shí) typeof 返回 "undefined

var a;
typeof a; // "undefined"
var b = 42;
var c;
// later
b = c;
typeof b; // "undefined"
typeof c; // "undefined"

大多數(shù)開發(fā)者傾向于將 undefined 等同于 undeclared(未聲明),但在 JavaScript 中它們完全
是兩回事。

已在作用域中聲明但還沒有賦值的變量,是 undefined 的。

相反,還沒有在作用域中聲明過的變量,是 undeclared 的。

var a;
a; // undefined
b; // ReferenceError: b is not defined

更讓人抓狂的是 typeof 處理 undeclared 變量的方式。例如:

var a;
typeof a; // "undefined"
typeof b; // "undefined"

對(duì)于 undeclared(或者 not defined)變量,typeof 照樣返回 "undefined"。

請(qǐng)注意雖然 b 是
一個(gè) undeclared 變量,但 typeof b 并沒有報(bào)錯(cuò)。這是因?yàn)?typeof 有一個(gè)特殊的安全防范機(jī)制。


typeof Undeclared

該安全防范機(jī)制對(duì)在瀏覽器中運(yùn)行的 JavaScript 代碼來說還是很有幫助的,

因?yàn)槎鄠€(gè)腳本文件會(huì)在共享的全局命名空間中加載變量。


// 這樣會(huì)拋出錯(cuò)誤
if (DEBUG) {
 console.log( "Debugging is starting" );
}
// 這樣是安全的
if (typeof DEBUG !== "undefined") {
 console.log( "Debugging is starting" );
}

//這不僅對(duì)用戶定義的變量(比如 DEBUG)有用,對(duì)內(nèi)建的 API 也有幫助:
if (typeof atob === "undefined") {
 atob = function() { /*..*/ };
}

還有一種不用通過 typeof 的安全防范機(jī)制的方法,就是檢查所有全局變量是否是全局對(duì)象
的屬性,瀏覽器中的全局對(duì)象是 window。所以前面的例子也可以這樣來實(shí)現(xiàn):

if (window.DEBUG) {
 // ..
}
if (!window.atob) {
 // ..
}

與 undeclared 變量不同,訪問不存在的對(duì)象屬性(甚至是在全局對(duì)象 window 上)不會(huì)產(chǎn)生
ReferenceError 錯(cuò)誤。

一些開發(fā)人員不喜歡通過 window 來訪問全局對(duì)象,尤其當(dāng)代碼需要運(yùn)行在多種 JavaScript
環(huán)境中時(shí)(不僅僅是瀏覽器,還有服務(wù)器端,如 node.js 等),因?yàn)榇藭r(shí)全局對(duì)象并非總是
window。


小結(jié)

JavaScript 有 七 種 內(nèi) 置 類 型:null、undefined、boolean、number、string、object 和
symbol,可以使用 typeof 運(yùn)算符來查看。

變量沒有類型,但它們持有的值有類型。類型定義了值的行為特征。

很多開發(fā)人員將 undefined 和 undeclared 混為一談,但在 JavaScript 中它們是兩碼事。
undefined 是值的一種。undeclared 則表示變量還沒有被聲明過。

遺憾的是,JavaScript 卻將它們混為一談,在我們?cè)噲D訪問 "undeclared" 變量時(shí)這樣報(bào)錯(cuò):ReferenceError: a is not defined,并且 typeof 對(duì) undefined 和 undeclared 變量都返回
"undefined"。

然而,通過 typeof 的安全防范機(jī)制(阻止報(bào)錯(cuò))來檢查 undeclared 變量,有時(shí)是個(gè)不錯(cuò)的
辦法。


第二章 值

數(shù)組

和其他強(qiáng)類型語言不同,在 JavaScript 中,數(shù)組可以容納任何類型的值,可以是字符串、
數(shù)字、對(duì)象(object),甚至是其他數(shù)組(多維數(shù)組就是通過這種方式來實(shí)現(xiàn)的)

使用 delete 運(yùn)算符可以將單元從數(shù)組中刪除,但是請(qǐng)注意,單元?jiǎng)h除后,數(shù)
組的 length 屬性并不會(huì)發(fā)生變化。第 5 章將詳細(xì)介紹 delete 運(yùn)算符。

數(shù)組通過數(shù)字進(jìn)行索引,但有趣的是它們也是對(duì)象,所以也可以包含字符串鍵值和屬性
(但這些并不計(jì)算在數(shù)組長(zhǎng)度內(nèi))


var a = [ ];
a[0] = 1;
a["foobar"] = 2;
a.length; // 1
a["foobar"]; // 2
a.foobar; // 2

這里有個(gè)問題需要特別注意,如果字符串鍵值能夠被強(qiáng)制類型轉(zhuǎn)換為十進(jìn)制數(shù)字的話,它
就會(huì)被當(dāng)作數(shù)字索引來處理。


var a = [ ];
a["13"] = 42;
a.length; // 14

在數(shù)組中加入字符串鍵值 / 屬性并不是一個(gè)好主意。建議使用對(duì)象來存放鍵值 / 屬性值,
用數(shù)組來存放數(shù)字索引值。


類數(shù)組

有時(shí)需要將類數(shù)組(一組通過數(shù)字索引的值)轉(zhuǎn)換為真正的數(shù)組,這一般通過數(shù)組工具函數(shù)(如 indexOf(..)、concat(..)、forEach(..) 等)來實(shí)現(xiàn)。

例如,一些 DOM 查詢操作會(huì)返回 DOM 元素列表,它們并非真正意義上的數(shù)組,但十分
類似。另一個(gè)例子是通過 arguments 對(duì)象(類數(shù)組)將函數(shù)的參數(shù)當(dāng)作列表來訪問(從
ES6 開始已廢止)。

工具函數(shù) slice(..) 經(jīng)常被用于這類轉(zhuǎn)換:

function foo() {
 var arr = Array.prototype.slice.call( arguments );
 arr.push( "bam" );
 console.log( arr );
}
foo( "bar", "baz" ); // ["bar","baz","bam"]

用 ES6 中的內(nèi)置工具函數(shù) Array.from(..) 也能實(shí)現(xiàn)同樣的功能:

...
var arr = Array.from( arguments );
...

字符串

許多數(shù)組函數(shù)用來處理字符串很方便。雖然字符串沒有這些函數(shù),但可以通過“借用”數(shù)
組的非變更方法來處理字符串:

var a = "foo";
var b = ["f","o","o"];
a.join; // undefined
a.map; // undefined
var c = Array.prototype.join.call( a, "-" );
var d = Array.prototype.map.call( a, function(v){
 return v.toUpperCase() + ".";
} ).join( "" );
c; // "f-o-o"
d; // "F.O.O."

另一個(gè)不同點(diǎn)在于字符串反轉(zhuǎn)(JavaScript 面試常見問題)。數(shù)組有一個(gè)字符串沒有的可變更成員函數(shù) reverse():

a.reverse; // undefined
b.reverse(); // ["!","o","O","f"]
b; // ["f","O","o","!"]

可惜我們無法“借用”數(shù)組的可變更成員函數(shù),因?yàn)樽址遣豢勺兊模?/p>

Array.prototype.reverse.call( a );
// 返回值仍然是字符串"foo"的一個(gè)封裝對(duì)象(參見第3章):(
// 在瀏覽器中會(huì)報(bào)以下錯(cuò)誤
20200824162257

一個(gè)變通(破解)的辦法是先將字符串轉(zhuǎn)換為數(shù)組,待處理完后再將結(jié)果轉(zhuǎn)換回字符串:

這種方法的確簡(jiǎn)單粗暴,但對(duì)簡(jiǎn)單的字符串卻完全適用

var c = a
// 將a的值轉(zhuǎn)換為字符數(shù)組
.split( "" )
// 將數(shù)組中的字符進(jìn)行倒轉(zhuǎn)
.reverse()
// 將數(shù)組中的字符拼接回字符串
.join( "" );
c; // "oof"

數(shù)字

數(shù)字的語法

var a = 42; 
var b = 42.3;

小數(shù)點(diǎn)前面的 0 可以省略:

var a = 42.0; 
var b = 42.;

默認(rèn)情況下大部分?jǐn)?shù)字都以十進(jìn)制顯示,小數(shù)部分最后面的 0 被省略,如:

var a = 42.300; 
var b = 42.0; 
a; // 42.3 
b; // 42

特別大和特別小的數(shù)字默認(rèn)用指數(shù)格式顯示,與 toExponential() 函數(shù)的輸出結(jié)果相同。
例如:

var a = 5E10; 
a; // 50000000000 
a.toExponential(); // "5e+10" 
var b = a * a; 
b; // 2.5e+21 
var c = 1 / a; 
c; // 2e-11

由于數(shù)字值可以使用 Number 對(duì)象進(jìn)行封裝(參見第 3 章),因此數(shù)字值可以調(diào)用 Number.prototype 中的方法(參見第 3 章)。例如,tofixed(..) 方法可指定小數(shù)部分的顯示位數(shù):

var a = 42.59; 
a.toFixed( 0 ); // "43" 
a.toFixed( 1 ); // "42.6" 
a.toFixed( 2 ); // "42.59" 
a.toFixed( 3 ); // "42.590" 
a.toFixed( 4 ); // "42.5900"

請(qǐng)注意,上例中的輸出結(jié)果實(shí)際上是給定數(shù)字的字符串形式,如果指定的小數(shù)部分的顯示
位數(shù)多于實(shí)際位數(shù)就用 0 補(bǔ)齊。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容