摘要:原文來源于我的前言身為一種弱類型的語言,不用像語言那樣要定義等等數(shù)據(jù)類型,因為允許變量類型的隱式轉(zhuǎn)換和允許強制類型轉(zhuǎn)換。
原文來源于我的github 0.前言
js身為一種弱類型的語言,不用像c語言那樣要定義int、float、double、string等等數(shù)據(jù)類型,因為允許變量類型的隱式轉(zhuǎn)換和允許強制類型轉(zhuǎn)換。我們在定義一個變量的時候,就一個var、let、const搞定,不用擔心數(shù)據(jù)的類型。比如常見的字符串拼接,用+號可以實現(xiàn)變量和字符串的拼接。
總的來說,一般的規(guī)則是
!后面的字符會被轉(zhuǎn)為換布爾
+后面的字符會被轉(zhuǎn)換為數(shù)值(-也是差不多)
[]+后面的字符會被轉(zhuǎn)換為字符串
對于object和number、string、boolean之間的轉(zhuǎ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返回對象的值:在控制臺,當你定義一個對象按回車,控制臺打印的是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 []==![] //true2.從[]==![]開始
大家也可能聽說過[]!=[],主要是因為他們是引用類型,內(nèi)存地址不同所以不相等。那么為什么加了一個!就能等于了?不是內(nèi)存地址還是不一樣嗎?
這又引出一個問題,符號的優(yōu)先度
1 | . [] () |
2 | ++ — ~ ! |
3 | * / % |
4 | + - + |
5 | << >> |
4 | + - + |
5 | < <= > >= |
4 | + - + |
6 | == != === !== |
可以看見,!優(yōu)先度是第二,所以先判斷!再判斷=
給[]取反,會是布爾值,[]的取反的布爾值就是false
非布爾類型轉(zhuǎn)布爾類型:undefined、null 、0、±0、NaN、0長度的字符串=》false,對象=》true
非數(shù)字類型轉(zhuǎn)數(shù)字類型:undefined=》NaN,null=》0,true=》1,false=》0,字符串:字符串數(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的問題了
我們知道,數(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 間接進行下標操作 3.2.1數(shù)字的獲取
我們可以通過類型轉(zhuǎn)換,獲得0和1兩個數(shù)字,既然能得到這兩個數(shù)字,那么也可以得到其他的一切數(shù)字了:
+[] === 0; +!![] === 1
那么, +!![]+!![] ===2,+((+![])+(+!![])+[]+(+![]))===10(注意:中間沒[]的話,就是數(shù)字的1+0,結(jié)果就是1了,有的話就是"1"+""+"0")
+((+![])+(+!![])+[]+(+![]))-!![] ===9
簡直就是無所不能
(![]+[])[+[]] //"f" (![]+[])[+!![]] // "a"
(![]+[])是"false",其實(![]+[])[+[]] 就相當于"false"[0],第一個字母,就是f
我們就可以從上面的那些獲得單詞的字符串獲得其中的字母了
好了,說道這里,要是誰說前端簡單,那就給他一個(![]+[])[+!![]+!![]+!![]] +([]+{})[+!![]+!![]]
近來有人問這個問題(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或者tostring方法就可以達到效果:
var a = { num: 0, valueOf: function() { return this.num += 1 } }; var eq = (a==1 && a==2 && a==3); console.log(eq); //或者改寫他的tostring方法 var num = 0; Function.prototype.toString = function(){ return ++num; } function a(){} //還可以改寫ES6的symbol類型的toP的方法 var a = {[Symbol.toPrimitive]: (function (i) { return function(){return ++i } }) (0)};
每一次進行等號的比較,就會調(diào)用一次valueOf方法,自增1,所以能成立。當然,如果換個位置就不行了,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,當然還是交換位置就不能為TRUE了
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://m.hztianpu.com/yun/94363.html
摘要:讓我們快速的復習一下在中一共有兩種類型的值原始值和對象值原始值有布爾值數(shù)字還有字符串其他的所有值都是對象類型的值包括數(shù)組和函數(shù)類型轉(zhuǎn)化先按運算符來分一下類減號,乘號,肯定是進行數(shù)學運算,所以操作數(shù)需轉(zhuǎn)化為類型。 前言 很多小伙伴們覺得javaScript很簡單,下面的這行 javaScript代碼可能會讓你懷疑人生。 (!(~+[])+{})[--[~+][+[]]*[~+[]] +...
摘要:都快要來了,必須跟棧長學起即將發(fā)布,新特性必須搶先看棧長之前在技術棧微信公眾號分享過已發(fā)布,還能這樣玩這篇文章,介紹了的新玩法,讓大家耳目一新。更多關于的資訊干貨教程以及好消息,請關注微信公眾號技術棧,第一時間推送。 Java 13 都快要來了,12必須跟棧長學起! Java 13 即將發(fā)布,新特性必須搶先看! 棧長之前在Java技術棧微信公眾號分享過《Java 11 已發(fā)布,Stri...
摘要:前幾天李老哥秀了一個中騷操作給我看,即的值是各位也可以看一下臥槽,牛逼啊很好奇,如何得到這個結(jié)果,莫名其妙就得到了我第一感覺是不可能啊,可是結(jié)果就在那這就要思考了,這個是什么碼的騷操作計算得來的數(shù)字結(jié)果還是字符轉(zhuǎn)化,或是別的什么,它是通過什 前幾天李老哥秀了一個JavaScript中騷操作給我看,即++[[]][+[]]+[+[]]的值是10;各位也可以看一下 console.log(...
摘要:沒錯,在中你一樣可以這樣簡單的操作,而不同的是你操作的是一整列的字符串數(shù)據(jù)。因為對于類型的,字符的操作發(fā)生在的非重復值上,而并非原上的所有元素上。下面的這些屬性基本都是關于查看和操作數(shù)據(jù)類型的。 作者:xiaoyu 微信公眾號:Python數(shù)據(jù)科學 知乎:python數(shù)據(jù)分析師 showImg(https://segmentfault.com/img/remote/146000001...
摘要:沒錯,在中你一樣可以這樣簡單的操作,而不同的是你操作的是一整列的字符串數(shù)據(jù)。因為對于類型的,字符的操作發(fā)生在的非重復值上,而并非原上的所有元素上。下面的這些屬性基本都是關于查看和操作數(shù)據(jù)類型的。 作者:xiaoyu 微信公眾號:Python數(shù)據(jù)科學 知乎:python數(shù)據(jù)分析師 showImg(https://segmentfault.com/img/remote/146000001...
閱讀 2161·2021-09-22 15:54
閱讀 1900·2021-09-04 16:40
閱讀 926·2019-08-30 15:56
閱讀 2686·2019-08-30 15:44
閱讀 2214·2019-08-30 13:52
閱讀 1180·2019-08-29 16:35
閱讀 3402·2019-08-29 16:31
閱讀 2624·2019-08-29 13:48