摘要:突然有一天,發現了一些基于很基礎的東西的騷操作,就開始懷疑人生如果沒有遇到被某些東西打擊到或者見識到新的世界,可能永遠的,就感嘆真好用,我精通,精通。最后,就相當于對每一個元素進行,,,,位操作符基本用法和概念就不說了,自行看文檔。
本文來源于我的github 0.前言
大家學習的時候,一開始小白,然后接觸到進階的東西的時候,發現一切得心應手,有的人可能開始說精通了。突然有一天,發現了一些基于很基礎的東西的騷操作,就開始懷疑人生:wtf JavaScript?
如果沒有遇到被某些東西打擊到或者見識到新的世界,可能永遠的,就感嘆:jQuery真好用,我精通jQuery,精通js。要不就是,vue?angular?react?我都會,我精通。
然而,我現在只能說我只是熟悉,越學發現越多坑。
對于數據類型轉換和正則的坑,前面有講過:
數據類型
正則表達式
類似一些遍歷類型的api:forEach、map,可能有人就說了:不就是arr.map(x=>x+1),要是涉及到索引,那就再來個index,arr.map((x,index)=>x+index),多簡單是不是
然后,先拋出一個問到爛的面試題:
["1","2","3"].map(parseInt)
找工作的人,看過面試題的,都知道結果是[1,NaN,NaN],那么為什么會這樣呢?
首先,map里面可以傳兩個參數:map(對每一個元素都調用的函數,該函數的this值)
而那個每一個元素都調用的函數,他傳入的參數是(current,index,arr)當前元素(必須)、索引、數組。
在這個例子,對parseInt傳入的就是這三個參數。
而parseInt這個原生的函數,他傳入的參數是(num,radix):
radix表示要解析的數字的基數。該值介于 2 ~ 36 之間。
如果省略該參數或其值為 0,則數字將以 10 為基礎來解析。如果它以 “0x” 或 “0X” 開頭,將以 16 為基數。如果該參數小于 2 或者大于 36,則 parseInt() 將返回 NaN
parseInt(10,10)//對10進制數字10取整,10 parseInt(10,2)//對2進制數字10取整,2 parseInt(111,2)//對2進制數字111取整,7 parseInt(111,4)//對4進制數字111取整,21 parseInt("1",2,[1])//1,傳入第三個數組是沒有意義的 parseInt("1",2,["1","2","3","4"])//1 parseInt("2",2,["1","2","3","4"])//NaN,2進制沒有2 parseInt("2",3,["1","2","3","4"])//3
那就很明顯了,對于為什么是[1,NaN,NaN],其實就是:
parseInt("1",0,["1","2","3"])//1,radix為 0,則數字將以 10 為基礎來解析 parseInt("2",1,["1","2","3"])//1進制是啥?反正就是NaN parseInt("3",2,["1","2","3"])//2進制沒有3
另外,parseInt,遇到字符串的數字他會盡量解釋,直到不能解釋就停止。
parseInt("123sfd")//123 parseInt("123sfd123")//123 parseInt("sfd213")//NaN1.2數組遍歷的api第二個參數
第二個參數,表示前面那個函數內部的this,一般不填這個參數,this就是undefined。而在非嚴格模式下,undefined就是window:
[1,2,3].forEach(function(x){console.log(this)})//window
我們可以強行把他改成其他的看看:
[1,2,3].forEach(function(x){console.log(this)},Math)//Math
我們知道,Array可以直接生成某一個長度元素全是空的數組:
Array(5)//注意了,5空和5個undefined是不同的
不妨apply一下:
Array.apply(null, { length:5 })//?[undefined, undefined, undefined, undefined, undefined] Array.apply(null, { "0":1,length:5 })//?[1, undefined, undefined, undefined, undefined] Array.apply(null, { "2":1,length:5 })//?[undefined, undefined, 1, undefined, undefined]
相當于給新創建的array的屬性直接進行改變
1.4你是不是用循環生成一個序列?生成一個序號數組:
var arr = []; for(var i = 0;i<10;i++){ arr.push(i) }
常規操作,沒什么問題,但是精通jQuery的你會不會用到其他方法呢?
比如:
Array.apply(null, {length:5 }).map(f.call,Number)//[0, 1, 2, 3, 4],f可以是任何函數 Array.apply(null, { "0":1,length:5 }).map(f.call,Number)//[0, 1, 2, 3, 4],不管元素是什么都一樣 Array.apply(null, {length:5 }).map(f.call,Boolean)//[false, true, true, true, true] Array.apply(null, {length:5 }).map(f.call,String)//["0", "1", "2", "3", "4"] Array.apply(null, {length:5 }).map(eval.call,Object)//[Number, Number, Number, Number, Number]
對于最后一個結果,點開第二個看看
map的那個函數,傳入了三個參數,第一個參數是當前元素。可是對于加了call的,第一個參數就是call的this指向了。而map后面的那個參數,就是this,也就是后面那個this已經把current覆蓋,起到主導作用的也是后面那個參數。而map的第一個參數fn,fn里面的第二個參數是index,也就是當前索引。而對于f.call,第一個參數是this指向,第二個參數以后全是f.call的函數f所使用的參數。最后,就相當于對每一個元素進行,Number(index),Boolean(index),String(index),Object(index)
2.位操作符基本用法和概念就不說了,自行看文檔。
2.1字符串轉數字有全世界都知道的parseInt,但是我們又可以用簡單一點的方法:
//就是讓他進行不改變本身的值的數學運算 +"1" "1"*1 "1"|0 "1" >> 0 "1" << 02.2更多的操作
要是我們要隨意得到一個很大的數,一般就是9999*9999這樣子吧,而位移操作可以相當于乘上2的n次方:1<<30//1073741824
好像沒什么用,先拋出一個需求:隨機生成字符串(數字+字母)
我知道,很多人完全不需要思考,直接拿起鍵盤擼:比如生成一個6位隨機字符串
var n = 6 var str = "abcdefghijklmnopqrstuvwxyz0123456789" var result = "" for (var i = 0 ;i對于位操作,就是短短的代碼解決:
(~~(Math.random()*(1<<24))).toString(16) (~~(Math.random()*(1<<30))).toString(36)首先生成一個大數,再轉進制。16進制就是0-9加上前面幾個字母,36進制就是0-9加上26個字母,那么我們可以得到一個穩定的生成n位隨機字符串版本:
function f(n){ if(n==1) return (~~(Math.random()*36)).toString(36) return (~~(Math.random()*36)).toString(36) + f(n-1) } //尾遞歸優化 function k(n){ return function f(n,s){ if(n==1) return s return f(n-1,(~~(Math.random()*36)).toString(36)+s) }(n,(~~(Math.random()*36)).toString(36)) }另一種方法:(也是基于高進制)
來一段小插曲
我們可以從Math.random().toString(36)得到一個0.xxx后面有11位小數的字符串,所以我們只要取第2位以后的就可以了Math.random().toString(36).slice(2)對于追求代碼極其簡短的強迫癥,看見上面的if -else,突然想起來平時寫了一大堆if-else實在是不順眼,好的,除了無腦if和簡短的三元表達式,我們還有短路表達式:
|| &&
a&&b:a為true,跑到b
a||b:a為false,跑b,a為true就取a//來一個有點智障的例子 function f(a){ if(a==1) console.log(1) if(a==2) console.log(2) if(a==3) console.log(3) } //一定要記得寫分號 function f(a){ (a==1)&& console.log(1); (a==2) &&console.log(2); (a==3) &&console.log(3); }如果在實際應用上面,代碼將會大大簡潔,但是可能第一次讓別人看難以理解
位操作交換倆整數不用中間變量,加減法實現交換
a = a+b;b = a-b;a = a-b
用位操作:
a ^= b;
b ^= a;
a ^= b;具體過程可以這樣子證明:
我們先令a0 = a, b0 = b。a = a ^ b 可以轉化為a = a0 ^ b 第二句:b = b ^ a = b0 ^ a = b0 ^ (a0 ^ b0) = a0 ^ (b0 ^ b0) = a0 ^ 0 = a0//達到了原始值a0和實際值b交換 第三句一樣:a = a ^ b = a ^ (b0 ^ a) = b0 ^ (a ^ a)= b0 ^ 0 = b0,和原始的b0交換成功3. 構造類繼續回到前面的例子:
Array.apply(null, {length:5 }).map(f.call,Number)//[0, 1, 2, 3, 4],f可以是任何函數 Array.apply(null, { "0":1,length:5 }).map(f.call,Number)//[0, 1, 2, 3, 4],不管元素是什么都一樣 Array.apply(null, {length:5 }).map(f.call,Boolean)//[false, true, true, true, true] Array.apply(null, {length:5 }).map(f.call,String)//["0", "1", "2", "3", "4"] Array.apply(null, {length:5 }).map(eval.call,Object)//[Number, Number, Number, Number, Number]map第二個參數ctx是this指向,而第一個參數是一個函數f(任何函數),f的第一個參數已經報廢,因為第一個參數是call的上下文this,但是這個this又被后面的ctx替代了,因此f有效的參數是從第二個開始,最后就相當于ctx(index),即是 :構造類(index)
于是我們又可以看看構造類另一個有意思的地方
var toFixed = 1; var obj = { toFixed:"我只是客串的", show:function(){ return this. toFixed; } } obj.show.call( toFixed); //? toFixed() { [native code] }也許一眼看上去是1,然而call的第一個參數居然不是null、undefined,效果不一樣了。
我們call的上下文就是toFixed。可以這樣理解,對于js內部,1其實是構造類Number(1)構造出來的,相當于this指向了Number,而我們可以打印一下Number.prototype,結果有
我們把toFixed方法打印出來了對于String也是可以的
var big = "1sdasdsadsdasd";//不是字符串的話,其他構造類沒有big方法,返回undefined var obj = { big:"我是客串的", show:function(){ return this.big; } } obj.show.call(big); //? big() { [native code] } //或者說,打印一個length看看 var l = "1sdasdsadsdasd";//變量換成l var obj = { length:"我是客串的", show:function(){ return this.length;//主要是這個,變量是什么不重要 } } obj.show.call(l); //14屬性太多了,可以去控制臺看看String.prototype有什么。
再或者說,看看函數執行起來會發生什么事情:
var l = true;//這次試一下boolean類型 var obj = { length:"我是客串的", show:function(){ return this.valueOf();//這次我們不打印這個函數了,讓他執行 } } obj.show.call(l,this); //true,直接調用類型轉換過程中的那個valueOf道理都是一樣,大家自己可以回去玩一下
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/94361.html
摘要:退回上一頁面時代碼是不會再重復運行的但代碼會重新運行一次所以我們可以用此點解決登錄驗證失敗退回登錄界面時驗證碼不刷新的問題通過代碼給加屬性這樣就可以重新刷新驗證碼表單的項一般寫成的形式這樣就可以直接把數據提交當前模塊的當前控制器的當前方法來 1、退回上一頁面時,html代碼是不會再重復運行的,但JS代碼會重新運行一次,所以我們可以用此點解決 登錄驗證失敗退回登錄界面時,驗證碼不刷新的問...
摘要:后續在日常開發中如遇到更多的冷門,會更新本文章獲取系統的負載創建一個包含變量名和它們的值的數組基于以微秒計的當前時間,生成一個唯一的。規定在包裝數據時所使用的格式。如果有什么冷門的函數,可在評論區留言。有時冷門函數也會幫上大忙不是嘛 概述 整理一些日常生活中基本用不到的PHP函數,也可以說在框架內基本都內置了,無需我們去自行使用的函數。量不多。后續在日常開發中如遇到更多的冷門,會更新本...
閱讀 2348·2021-11-23 09:51
閱讀 1152·2021-11-22 13:52
閱讀 3623·2021-11-10 11:35
閱讀 1205·2021-10-25 09:47
閱讀 3010·2021-09-07 09:58
閱讀 1074·2019-08-30 15:54
閱讀 2830·2019-08-29 14:21
閱讀 3042·2019-08-29 12:20