關(guān)于js類型轉(zhuǎn)換騷操作

本文是lhyt本人原創(chuàng),希望用通俗易懂的方法來理解一些細節(jié)和難點。轉(zhuǎn)載時請注明出處。文章最早出現(xiàn)于本人github

0.前言

js身為一種弱類型的語言,不用像c語言那樣要定義int、float、double、string等等數(shù)據(jù)類型,因為允許變量類型的隱式轉(zhuǎn)換和允許強制類型轉(zhuǎn)換。我們在定義一個變量的時候,就一個var、let、const搞定,不用擔(dān)心數(shù)據(jù)的類型。比如常見的字符串拼接,用+號可以實現(xiàn)變量和字符串的拼接。

總的來說,一般的規(guī)則是

!后面的字符會被轉(zhuǎn)為換布爾

+后面的字符會被轉(zhuǎn)換為數(shù)值(-也是差不多)

[]+后面的字符會被轉(zhuǎn)換為字符串

對于object和number、string、boolean之間的轉(zhuǎn)換關(guān)系,這里偷網(wǎng)上一幅圖

Object 與Primitive,需要Object轉(zhuǎn)為Primitive

String 與 Boolean,需要兩個操作數(shù)同時轉(zhuǎn)為Number。

String/Boolean 與 Number,需要String/Boolean轉(zhuǎn)為Number。

undefined 與 null ,和所有其他值比較的結(jié)果都是false,他們之間==成立

ToPrimitive是指轉(zhuǎn)換為js內(nèi)部的原始值,如果是非原始值則轉(zhuǎn)為原始值,調(diào)用valueOf()和obj.toString()來實現(xiàn)。valueOf返回對象的值:在控制臺,當(dāng)你定義一個對象按回車,控制臺打印的是Object{...},obj.toString()返回對象轉(zhuǎn)字符串的形式,打印的是"[object Object]"

如果參數(shù)是Date對象的實例,那么先toString()如果是原始值則返回,否則再valueOf(),如果是原始值則返回,否則報錯。

如果參數(shù)不是Date對象的實例,同理,不過先valueOf再obj.toString()。

1.奇葩例子

![] //false;

+[] // 0

+![] // 0

[]+[] // ""

{}+{}//"[object Object][object Object]"

{}+[]//0

{a:0}+1 // 1

[]+{}//"[object Object]"

[]+![]//"false"

{}+[]//0

![]+[] // "false"

''+{} //"[object Object]"

{}+'' //0

[]["map"]+[] //"function map() { }"

[]["a"]+[] // "undefined"

[][[]] + []// "undefined"

+!![]+[] //"1"

+!![] //1

1-{} //NaN

1-[] //1

true-1 //0

{}-1 //-1

[]==![] //true

2.從[]==![]開始

大家也可能聽說過[]!=[],主要是因為他們是引用類型,內(nèi)存地址不同所以不相等。那么為什么加了一個!就能等于了?不是內(nèi)存地址還是不一樣嗎?

這又引出一個問題,符號的優(yōu)先度

1. [] ()

2 ++ — ~ !

3 * / %

4 + - +

5 <<? >>?

6 + - +

7 < <= > >=

8 + - +

9 ==? !=? ===? !==

可以看見,!優(yōu)先度是第二,所以先判斷!再判斷=

給[]取反,會是布爾值,[]的取反的布爾值就是false

2.1 []的反就是false?

ECMA規(guī)范:

非布爾類型轉(zhuǎn)布爾類型:undefined、null 、0、±0、NaN、0長度的字符串=》false,對象=》true

非數(shù)字類型轉(zhuǎn)數(shù)字類型:undefined=》NaN,null=》0,true=》0,false=》1,字符串:字符串?dāng)?shù)字直接轉(zhuǎn)數(shù)字類型、字符串非數(shù)字=》NaN

[]也是對象類型(typeof [] == "object"),轉(zhuǎn)為布爾類型的![]就是false

2.2 等號兩邊對比

我們知道,在比較類型的時候,先會進行各種各樣的類型轉(zhuǎn)換。

從開頭的表格可以看見,他們比較的時候都是先轉(zhuǎn)換為數(shù)字類型。右邊是布爾值false,左邊為一個空數(shù)組對象,對于左邊,先進行P操作(ToPrimitive([])),先執(zhí)行valueOf([])返回的是[],非原始類型,再

[].toString(),返回的是"",那P操作之后,結(jié)果就是""了

最后,左邊""和右邊f(xié)alse對比,他們再轉(zhuǎn)換為數(shù)字,就是0==0的問題了

3.從已有的得到想不到的

3.1 間接獲取數(shù)組方法

我們知道,數(shù)組有自己的一套方法,比如var arr = [1,2];arr.push(1),我們可以寫成[1,2].push(1),還可以寫成[1,2]['push'](1),那么前面拋出的問題就解決了

[]['push'](1)//[1]

[]["map"] //function map() { [native code] }

[]["map"]+[] // "function map() { [native code] }"

3.2 間接進行下標(biāo)操作

3.2.1數(shù)字的獲取

我們可以通過類型轉(zhuǎn)換,獲得0和1兩個數(shù)字,既然能得到這兩個數(shù)字,那么也可以得到其他的一切數(shù)字了:

+[] === 0; +!![] === 1

那么, +!![]+!![] ===2,+((+![])+(+!![])+[]+(+![]))===10(注意:中間沒[]的話,就是數(shù)字的1+0,結(jié)果就是1了,有的話就是'1'+''+'0')

+((+![])+(+!![])+[]+(+![]))-!![] ===9

簡直就是無所不能

3.2.2 字符串下標(biāo)

(![]+[])[+[]] //"f"

(![]+[])[+!![]] // "a"

(![]+[])是"false",其實(![]+[])[+[]] 就相當(dāng)于"false"[0],第一個字母,就是f

我們就可以從上面的那些獲得單詞的字符串獲得其中的字母了

好了,說道這里,要是誰說前端簡單,那就給他一個(![]+[])[+!![]+!![]+!![]] +([]+{})[+!![]+!![]]

4.關(guān)于(a==1 && a==2 && a==3)

4.1 ==

近來有人問這個問題(a==1 && a==2 && a==3) 或者(a===1 && a===2 && a===3) 能不能為true?

事實上是可以的,就是因為在==比較的情況下,會進行類型的隱式轉(zhuǎn)換。前面已經(jīng)說過,如果參數(shù)不是Date對象的實例,就會進行類型轉(zhuǎn)換,先valueOf再obj.toString()

所以,我們只要改變原生的valueOf方法就可以達到效果:

var a = {

num: 0,

valueOf: function() {

return this.num += 1

}

};

var eq = (a==1 && a==2 && a==3);

console.log(eq);

每一次進行等號的比較,就會調(diào)用一次valueOf方法,自增1,所以能成立。當(dāng)然,如果換個位置就不行了,var eq = (a==2 && a==1 && a==3);

另外,減法也是同理:

var a = {

num: 4,

valueOf: function() {

return this.num -= 1

}

};

var eq = (a==3 && a==2 && a==1);

console.log(eq);

4.2 ===

如果沒有類型轉(zhuǎn)換,===的情況,還是可以的。跑題...

在vue源碼實現(xiàn)雙向數(shù)據(jù)綁定中,就利用了defineProperty方法進行觀察,觀察到視圖層的變化并實時反映到model層。

每一次訪問對象中的某一個屬性的時候,就會調(diào)用這個方法定義的對象里面的get方法。每一次改變對象屬性的值,就會訪問set方法

在這里,我們自己定義自己的get方法:

var b = 1

Object.defineProperty(window, 'a', {

get:function() { return b++; }

})

var s = (a===1 && a===2 && a === 3 )

console.log(s)

每一次訪問a屬性,a的屬性值就會+1,當(dāng)然還是交換位置就不能為TRUE了


原文來自lhyt的github

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

相關(guān)閱讀更多精彩內(nèi)容

  • 第2章 基本語法 2.1 概述 基本句法和變量 語句 JavaScript程序的執(zhí)行單位為行(line),也就是一...
    悟名先生閱讀 4,619評論 0 13
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,724評論 19 139
  • 秋天最好看的風(fēng)景是,陽光肆意,微風(fēng)白云,佳人的披肩與短裙,明媚“凍”人,與金黃色的落葉交相輝映,一切都恰好,連心情...
    yaparis閱讀 275評論 0 0
  • 閱讀時間:2016年1月26日,19:30-21:30,2小時; 閱讀書本:《失控》,作者:【美】凱文·凱利;新星...
    時空山莊閱讀 241評論 0 1

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