玩轉JS的型別轉換黑科技

2021-09-11 12:27:44 字數 3268 閱讀 7655

原文**於我的github

js身為一種弱型別的語言,不用像c語言那樣要定義int、float、double、string等等資料型別,因為允許變數型別的隱式轉換和允許強制型別轉換。我們在定義乙個變數的時候,就乙個var、let、const搞定,不用擔心資料的型別。比如常見的字串拼接,用+號可以實現變數和字串的拼接。 總的來說,一般的規則是

toprimitive是指轉換為js內部的原始值,如果是非原始值則轉為原始值,呼叫valueof()和obj.tostring()來實現。valueof返回物件的值:在控制台,當你定義乙個物件按回車,控制台列印的是object,obj.tostring()返回物件轉字串的形式,列印的是"[object object]"

! //false; 

+ // 0

+! // 0

+ // ""

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

{}+//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

複製**

1

. ()

2++ — ~ !

3* / %

4+ - +

5<< >>

4+ - +

5< <= > >=

4+ - +

6== != === !==

可以看見,!優先度是第二,所以先判斷!再判斷= 給取反,會是布林值,的取反的布林值就是false

非布林型別轉布林型別:undefined、null 、0、±0、nan、0長度的字串=》false,物件=》true 非數字型別轉數字型別:undefined=》nan,null=》0,true=》1,false=》0,字串:字串數字直接轉數字型別、字串非數字=》nan

也是物件型別(typeof == "object"),轉為布林型別的!就是false

我們知道,在比較型別的時候,先會進行各種各樣的型別轉換。 從開頭的**可以看見,他們比較的時候都是先轉換為數字型別。右邊是布林值false,左邊為乙個空陣列物件,對於左邊,先進行p操作(toprimitive()),先執行valueof()返回的是,非原始型別,再 .tostring(),返回的是"",那p操作之後,結果就是""了 最後,左邊""和右邊false對比,他們再轉換為數字,就是0==0的問題了

我們知道,陣列有自己的一套方法,比如var arr = [1,2];arr.push(1),我們可以寫成[1,2].push(1),還可以寫成[1,2]['push'](1),那麼前面丟擲的問題就解決了

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

["map"] //function map()

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

複製**

我們可以通過型別轉換,獲得0和1兩個數字,既然能得到這兩個數字,那麼也可以得到其他的一切數字了: + === 0; +!! === 1 那麼, +!!+!! ===2,+((+!)+(+!!)++(+!))===10(注意:中間沒的話,就是數字的1+0,結果就是1了,有的話就是'1'+''+'0') +((+!)+(+!!)++(+!))-!! ===9 簡直就是無所不能

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

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

複製**

(!+)是"false",其實(!+)[+] 就相當於"false"[0],第乙個字母,就是f 我們就可以從上面的那些獲得單詞的字串獲得其中的字母了 好了,說道這裡,要是誰說前端簡單,那就給他乙個(!+)[+!!+!!+!!] +(+{})[+!!+!!]

近來有人問這個問題(a==1 && a==2 && a==3) 或者(a===1 && a===2 && a===3) 能不能為true? 事實上是可以的,就是因為在==比較的情況下,會進行型別的隱式轉換。前面已經說過,如果引數不是date物件的例項,就會進行型別轉換,先valueof再obj.tostring() 所以,我們只要改變原生的valueof或者tostring方法就可以達到效果:

var a = 

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

console.log(eq);

//或者改寫他的tostring方法

var num = 0;

function.prototype.tostring = function()

function

a(){}

//還可以改寫es6的symbol型別的top的方法

var a = }) (0)};

複製**

每一次進行等號的比較,就會呼叫一次valueof方法,自增1,所以能成立。當然,如果換個位置就不行了,var eq = (a==2 && a==1 && a==3); 另外,減法也是同理:

var a = 

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

console.log(eq);

複製**

如果沒有型別轉換,===的情況,還是可以的。跑題... 在vue原始碼實現雙向資料繫結中,就利用了defineproperty方法進行觀察,觀察到檢視層的變化並實時反映到model層。 每一次訪問物件中的某乙個屬性的時候,就會呼叫這個方法定義的物件裡面的get方法。每一次改變物件屬性的值,就會訪問set方法 在這裡,我們自己定義自己的get方法:

var b = 1

object.defineproperty(window, 'a',

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

console.log(s)

複製**

每一次訪問a屬性,a的屬性值就會+1,當然還是交換位置就不能為true了

玩轉JS的型別轉換黑科技

js身為一種弱型別的語言,不用像c語言那樣要定義int float double string等等資料型別,允許變數型別的隱式轉換和允許強制型別轉換。我們在定義乙個變數的時候,就乙個var let const搞定,不用擔心資料的型別。比如常見的字串拼接,用 號可以實現變數和字串的拼接。總的來說,一般...

JS的型別轉換

首先我們要知道,在 js 中型別轉換只有三種情況,分別是 我們先來看乙個型別轉換 在條件判斷時,除了undefined,null,false,nan,0,0,其他所有值都轉為true,包括所有物件。物件在轉換型別的時候,會呼叫內建的 toprimitive 函式,對於該函式來說,演算法邏輯一般來說如...

CSS 的黑科技

補充篇在這裡 昨天由於某些原因沒有寫部落格,之前說好的每天一篇的,這篇是為了補昨天的了。然後我就要當一次標題黨了。這裡的黑科技其實就是一些css中不怎麼為人所知但在解決某些問題的時候很溜的屬性。很多開發者估計都沒有正確認識這個border radius,因為基本上很多人都是這麼用的 box 稍微高階...