你不知道的JavaScript(中)

1 類型

1.1 js有七種內(nèi)置類型

1 undefined 2 boolean 3 number 4 string 5 object 6 null 7 symbol

  • typeof undefined === "undefined"
  • typeof true === "boolean"; // true
  • typeof 42 === "number"; // true
  • typeof "42" === "string"; // true
  • typeof { life: 42 } === "object"; // true
  • typeof Symbol() === "symbol"; // true

但是null稍微特殊
typeof null === "object"; // true
所以如果檢測一個值是否為null,需要
var a = null;
(!a && typeof a === "object"); // true

1.2 JavaScript 中的變量是沒有類型的,只有值才有誓琼。變量可以隨時持有任何類型的值

換個角度來理解就是频伤,JavaScript 不做”類型強(qiáng)制“劳翰。
在對變量執(zhí)行 typeof 操作時抽减,得到的結(jié)果并不是該變量的類型盒发,而是該變量持有的值的類
型郁竟,因為 JavaScript 中的變量沒有類型玛迄。

1.3 undefined && undeclared

undefined 是值的一種。undeclared 則表示變量還沒有被聲明過棚亩。
遺憾的是蓖议,JavaScript 卻將它們混為一談,在我們試圖訪問 "undeclared" 變量時這樣報
錯:ReferenceError: a is not defined蔑舞,并且 typeof 對 undefined 和 undeclared 變量都返回
"undefined"拒担。

typeof undefined == "undefined"
typeof undeclared == "undefined"

2 值

簡單值(即標(biāo)量基本類型值,scalar primitive)總是通過值復(fù)制的方式來賦值 / 傳遞攻询,包括
null从撼、undefined、字符串钧栖、數(shù)字低零、布爾和 ES6 中的 symbol。
復(fù)合值(compound value)——對象(包括數(shù)組和封裝對象拯杠,參見第 3 章)和函數(shù)掏婶,則總 是通過引用復(fù)制的方式來賦值 / 傳遞。

var a = 2;
var b = a; // b是a的值的一個副本
b++;
a; // 2
b; // 3
var c = [1,2,3];
var d = c; // d是[1,2,3]的一個引用
d.push( 4 );
c; // [1,2,3,4]
d; // [1,2,3,4]

在上述代碼中潭陪,a雄妥,b分別指向 值 的兩個復(fù)本。a依溯,b的改變互不影響老厌。
c,d分別指向 值 的兩個引用黎炉,而引用都指向同樣的一個對象 [1,2,3]枝秤,所以c,d的改變是對于所指對象的改變慷嗜。

function foo(x) {
 x.push( 4 );
 x; // [1,2,3,4]
 // 然后
 x = [4,5,6];
 x.push( 7 );
 x; // [4,5,6,7]
}
var a = [1,2,3];
foo( a );
a; // 是[1,2,3,4]淀弹,不是[4,5,6,7]

其中丹壕,a將 [1,2,3]的引用的復(fù)本,傳給了變量x薇溃。變量x 指向 對象[1,2,3]的引用的復(fù)本菌赖,可以修改其值。
隨后沐序,變量x指向 更改為[4,5,6]的引用盏袄,這一操作并不會影響a的引用。

3 原生函數(shù)

  • String()
  • Number()
  • Boolean()
  • Array()
  • Object()
  • Function()
  • RegExp()
  • Date()
  • Error()
  • Symbol()——ES6 中新加入的薄啥!

3.1

new String("abc") 創(chuàng)建的是字符串 "abc" 的封裝對象,而非基本類型值 "abc"逛尚。

var a = new String( "abc" );
typeof a; // 是"object"垄惧,不是"String"
a instanceof String; // true
Object.prototype.toString.call( a ); // "[object String]"

3.2 內(nèi)部屬性 [[Class]]

這個屬性無法直接訪問,
一般通過 Object.prototype.toString(..) 來查看绰寞。例如:

Object.prototype.toString.call( [1,2,3] ); // "[object Array]"
Object.prototype.toString.call( /regex-literal/i ); // "[object RegExp]"

4 強(qiáng)制類型轉(zhuǎn)換

4.1 值類型轉(zhuǎn)換

將值從一種類型轉(zhuǎn)換為另一種類型通常稱為類型轉(zhuǎn)換(type casting)到逊,這是顯式的情況;隱式的情況稱為強(qiáng)制類型轉(zhuǎn)換(coercion)滤钱。
也可以這樣來區(qū)分:類型轉(zhuǎn)換發(fā)生在靜態(tài)類型語言的編譯階段觉壶,而強(qiáng)制類型轉(zhuǎn)換則發(fā)生在動態(tài)類型語言的運(yùn)行時(runtime)。
然而在 JavaScript 中通常將它們統(tǒng)稱為強(qiáng)制類型轉(zhuǎn)換件缸,我個人則傾向于用“隱式強(qiáng)制類型
轉(zhuǎn)換”(implicit coercion)和“顯式強(qiáng)制類型轉(zhuǎn)換”(explicit coercion)來區(qū)分铜靶。

例如:
var a = 42;
var b = a + ""; // 隱式強(qiáng)制類型轉(zhuǎn)換
var c = String( a ); // 顯式強(qiáng)制類型轉(zhuǎn)換

4.2 抽象值操作

  1. toString
  2. toNumber
    其中 true 轉(zhuǎn)換為 1,false 轉(zhuǎn)換為 0他炊。undefined 轉(zhuǎn)換為 NaN争剿,null 轉(zhuǎn)換為 0。
    對象(包括數(shù)組)會首先被轉(zhuǎn)換為相應(yīng)的基本類型值痊末,如果返回的是非數(shù)字的基本類型值蚕苇,則再遵循以上規(guī)則將其強(qiáng)制轉(zhuǎn)換為數(shù)字。
    為了將值轉(zhuǎn)換為相應(yīng)的基本類型值凿叠,抽象操作 ToPrimitive會首先檢查該值是否有 valueOf() 方法涩笤。
    如果有并且返回基本類型值,就使用該值進(jìn)行強(qiáng)制類型轉(zhuǎn)換盒件。如果沒有就使用 toString()的返回值(如果存在)來進(jìn)行強(qiáng)制類型轉(zhuǎn)換蹬碧。
    如果 valueOf() 和 toString() 均不返回基本類型值,會產(chǎn)生 TypeError 錯誤履恩。
  3. toBoolean
    以下為假值:
    ? undefined
    ? null
    ? false
    ? +0锰茉、-0 和 NaN
    ? ""

4.3 顯式強(qiáng)制類型轉(zhuǎn)換

  1. 字符串和數(shù)字之間的顯式轉(zhuǎn)換
    1. 運(yùn)算符的一元形式
    var a = "123"
    var b = +a // 123  被轉(zhuǎn)換為number
    
    2.奇特的 ~ 運(yùn)算符
    var a = "Hello World";
    a.indexOf('H') // 0
    ~a.indexOf('H') // -1
    Boolean(~indexOf('H')) // true
    如果存在值,則indexOf為0或其余正數(shù)切心,那么~為負(fù)數(shù)飒筑,Boolean轉(zhuǎn)換為true
    
    a.indexOf('123') // -1
    ~a.indexOf('H') // 0
    Boolean(~indexOf('H')) // false
    如果不存在值片吊,則indexOf為-1,那么~為0协屡,Boolean轉(zhuǎn)換為false
    
    1. ~~字位截除
    var a = 3.14
    ~a // -4
    ~~ a // 3
    
    Math.floor( -49.6 ); // -50
    ~~-49.6; // -49
    
  2. 顯式轉(zhuǎn)換為布爾值
    顯式強(qiáng)制類型轉(zhuǎn)換為布爾值最常用的方法是 !! 而不是 Boolean

4.4 隱式強(qiáng)制類型轉(zhuǎn)換

  1. 字符串和數(shù)字之間的隱式強(qiáng)制類型轉(zhuǎn)換
var a = "42";
var b = "0";
var c = 42;
var d = 0;
a + b; // "420"
c + d; // 42

var a = [1,2];
var b = [3,4];
a + b; // 1,23,4

如果參與運(yùn)算的對象是字符串俏脊,或者可以轉(zhuǎn)換成字符串,則+進(jìn)行字符串拼接操作肤晓。否則執(zhí)行數(shù)字加法爷贫。
因此:a+b=“420”
當(dāng)運(yùn)算對象為對象時,調(diào)用ToPrimitive补憾,調(diào)用valueOf 或者 toString漫萄,獲取[[DefaultValue]]。
因此盈匾,數(shù)組[1,2]被轉(zhuǎn)換為“1腾务,2”“3,4”再進(jìn)行字符串拼接削饵。

var a = "3.14";
var b = a - 0;
b; // 3.14

- 是數(shù)字減法運(yùn)算符岩瘦,因此 a - 0 會將 a 強(qiáng)制類型轉(zhuǎn)換為數(shù)字。
也可以使用 a * 1 和 a / 1窿撬,因為這兩個運(yùn)算符也只適用于數(shù)字启昧,只不過這樣的用法不太常見。
對象的 - 操作與 + 類似:
var a = [3];
var b = [1];
a - b; // 2
  1. 隱式強(qiáng)制類型轉(zhuǎn)換為布爾值
    (1) if (..) 語句中的條件判斷表達(dá)式劈伴。
    (2) for ( .. ; .. ; .. ) 語句中的條件判斷表達(dá)式(第二個)密末。
    (3) while (..) 和 do..while(..) 循環(huán)中的條件判斷表達(dá)式。
    (4) ? : 中的條件判斷表達(dá)式跛璧。
    (5) 邏輯運(yùn)算符 ||(邏輯或)和 &&(邏輯與)左邊的操作數(shù)(作為條件判斷表達(dá)式)苏遥。

4.5 || &&

|| 和 && 首先會對第一個操作數(shù)執(zhí)行條件判斷,如果其不是布爾值就先進(jìn)行 ToBoolean 強(qiáng)制類型轉(zhuǎn)換赡模,然后再執(zhí)行條件判斷田炭。
對于 || 來說,如果條件判斷結(jié)果為 true 就返回第一個操作數(shù)的值漓柑,如果為
false 就返回第二個操作數(shù)的值教硫。

&& 則相反,如果條件判斷結(jié)果為 true 就返回第二個操作數(shù)的值辆布,如果為 false 就返回第一個操作數(shù)的值瞬矩。
可以用a && foo() 代替 if(a) { foo() },簡潔

var a = 42;
var b = null;
var c = "foo";
if (a && (b || c)) {
 console.log( "yep" );
}
在上述 if 中
1 b||c // “foo”
2 a && (b||c) // "foo"
3 if 隱式類型轉(zhuǎn)換锋玲,將"foo"轉(zhuǎn)為true

4.6 寬松相等和嚴(yán)格相等

== 允許在相等比較中進(jìn)行強(qiáng)制類型轉(zhuǎn)換景用,而 === 不允許。
== 和 === 都會檢查操作數(shù)的類型。區(qū)別在于操作數(shù)類型不同時它們的處理方
式不同伞插。

  1. 數(shù)字和字符串比較 字符串ToNumber
x = '42'
y = 1
x== y
首先將 ‘42’ 轉(zhuǎn)為 42割粮,轉(zhuǎn)為number,再比較
返回false
  1. 布爾和其他類型比較 布爾值ToNumber
x = true
y = '42'
x == y
首先媚污,true 轉(zhuǎn)為 1舀瓢,這樣就是 1 == ‘42’
其次,‘42’ 轉(zhuǎn)為 42耗美,再比較
返回false
  1. 對象和非對象之間的相等比較
    (1) 如果 Type(x) 是字符串或數(shù)字京髓,Type(y) 是對象,則返回 x == ToPrimitive(y) 的結(jié)果商架;
    (2) 如果 Type(x) 是對象堰怨,Type(y) 是字符串或數(shù)字,則返回 ToPromitive(x) == y 的結(jié)果蛇摸。
  2. 對象和對象的比較
    比較對象所指向的值诚些,是否相等
  3. <=
在js中,a <= b
被轉(zhuǎn)換為 !(a>b)
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末皇型,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子砸烦,更是在濱河造成了極大的恐慌弃鸦,老刑警劉巖,帶你破解...
    沈念sama閱讀 210,978評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件幢痘,死亡現(xiàn)場離奇詭異唬格,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)颜说,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,954評論 2 384
  • 文/潘曉璐 我一進(jìn)店門购岗,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人门粪,你說我怎么就攤上這事喊积。” “怎么了玄妈?”我有些...
    開封第一講書人閱讀 156,623評論 0 345
  • 文/不壞的土叔 我叫張陵乾吻,是天一觀的道長。 經(jīng)常有香客問我拟蜻,道長绎签,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,324評論 1 282
  • 正文 為了忘掉前任酝锅,我火速辦了婚禮诡必,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘搔扁。我一直安慰自己爸舒,他們只是感情好蟋字,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,390評論 5 384
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著碳抄,像睡著了一般愉老。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上剖效,一...
    開封第一講書人閱讀 49,741評論 1 289
  • 那天嫉入,我揣著相機(jī)與錄音,去河邊找鬼璧尸。 笑死咒林,一個胖子當(dāng)著我的面吹牛统扳,可吹牛的內(nèi)容都是我干的磅崭。 我是一名探鬼主播,決...
    沈念sama閱讀 38,892評論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼应闯,長吁一口氣:“原來是場噩夢啊……” “哼蛀序!你這毒婦竟也來了欢瞪?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,655評論 0 266
  • 序言:老撾萬榮一對情侶失蹤徐裸,失蹤者是張志新(化名)和其女友劉穎遣鼓,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體重贺,經(jīng)...
    沈念sama閱讀 44,104評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡骑祟,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,451評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了气笙。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片次企。...
    茶點(diǎn)故事閱讀 38,569評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖潜圃,靈堂內(nèi)的尸體忽然破棺而出缸棵,到底是詐尸還是另有隱情,我是刑警寧澤谭期,帶...
    沈念sama閱讀 34,254評論 4 328
  • 正文 年R本政府宣布蛉谜,位于F島的核電站,受9級特大地震影響崇堵,放射性物質(zhì)發(fā)生泄漏型诚。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,834評論 3 312
  • 文/蒙蒙 一鸳劳、第九天 我趴在偏房一處隱蔽的房頂上張望狰贯。 院中可真熱鬧,春花似錦、人聲如沸涵紊。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,725評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽摸柄。三九已至颤练,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間驱负,已是汗流浹背嗦玖。 一陣腳步聲響...
    開封第一講書人閱讀 31,950評論 1 264
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留跃脊,地道東北人宇挫。 一個月前我還...
    沈念sama閱讀 46,260評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像酪术,于是被迫代替她去往敵國和親器瘪。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,446評論 2 348

推薦閱讀更多精彩內(nèi)容