摘要:所謂的高級(jí),其實(shí)就是講了一些我們平常用不到或許用了不知道,但是非常實(shí)在的東西。比如如果你想檢測(cè)里面的屬性值的話,基本上是不可能的。要知道,我們是有情懷的淫。
JS進(jìn)階
說(shuō)起這個(gè)應(yīng)該算是老生常談了吧。所謂的高級(jí),其實(shí)就是講了一些我們平常用不到(或許用了不知道),但是非常實(shí)在的東西。算是熟練掌握js的一個(gè)必經(jīng)road吧。
檢測(cè)函數(shù)類型其實(shí)檢測(cè)函數(shù)的類型應(yīng)該算是js的一個(gè)痛點(diǎn),因?yàn)閖s是一門弱類型的語(yǔ)言,對(duì)類型的檢測(cè)不是那么看重。但隨著JS的發(fā)展,類型變得更加豐富。而檢測(cè)類型的復(fù)雜度,也變得復(fù)雜了~ (MD). 大致梳理一下吧。
如果你想檢測(cè)值類型(Number,String,Boolean,undefined,null,Symbol). 使用typeof就可以了
typeof 23; //"number" typeof "webpack"; //"string" typeof true; //"boolean" typeof undefined; //"undefined" typeof symbol(); //"symbol" //但是有個(gè)呆毛null. typeof null; //"object" 如果理解原型鏈的話,那就無(wú)可厚非了
而檢測(cè)自定義類型,或者原生的應(yīng)用類型,則需要使用到instanceof
let obj = new Object(); obj instanceof Object; //true ...
但是有時(shí)候情況往往不是這么簡(jiǎn)單。 比如如果你想檢測(cè)iframe里面的屬性值的話,基本上是不可能的。因?yàn)闄z測(cè)的前提要求是在同一個(gè)全局作用于下。所以為了能夠正常檢測(cè)一些值的類型(排除在iframe的情況).那有沒(méi)有什么萬(wàn)能的方法呢? 確實(shí)有,你可以使用調(diào)用toString()的方法,得到相關(guān)的類型.
let value = new FormData(); console.log(Object.prototype.toString.call(value)); //"[object FormData]"
是不是感覺(jué)特別情切呢。 你也可以更進(jìn)一步的提取。要知道,我們是有情懷的淫。
function getType(value){ //基本上可以返回所有的類型,不論你是自定義還是原生 return Object.prototype.toString.call(value).match(/s{1}(w+)/)[1]; } let obj = new Object(); console.log(getType(obj)); //"Object"作用域安全的構(gòu)造函數(shù)
關(guān)于函數(shù)的坑應(yīng)該是無(wú)處不在(誰(shuí)叫他是js里面最難懂的一個(gè)類型)。關(guān)于函數(shù)里面的this得說(shuō)明一下。只有函數(shù)在運(yùn)行的時(shí)候,函數(shù)里面的this才會(huì)真正的綁定.這就造成了一個(gè)問(wèn)題,即,如果你在全局不小心運(yùn)行了一個(gè)函數(shù),那結(jié)果就呵呵了。 因?yàn)榇藭r(shí),你的this代表的window.這樣你會(huì)污染到全局的相關(guān)屬性,造成一個(gè)蜜汁bug.
所以,為了安全需要在創(chuàng)建時(shí),對(duì)this指針做一個(gè)判斷.
function Father(name){ this.name = name; } var jimmy = Father("jimmy"); //這樣會(huì)污染全局變量window.name的屬性。造成重寫 console.log(window.name); //"jimmy" console.log(jimmy.name); //"jimmy" //修改過(guò)后 function Father(name){ if(this instanceof Father){ this.name = name; }else{ return new Father(name); } } var jimmy = Father("jimmy"); //保證了作用域的安全性 console.log(window.name); //"xxx" console.log(jimmy.name); //"jimmy"惰性載入函數(shù)
這個(gè)應(yīng)用最多的場(chǎng)景應(yīng)該是兼容性判斷吧。比如你寫了一個(gè)判斷綁定事件方法的檢測(cè)函數(shù)
function bind(ele,fn,type){ if(document.addEventListener){ //檢測(cè)現(xiàn)代瀏覽器 ele.addEventListener(type,fn,false); }else if(document.attachEvent){ //檢測(cè)低版本的IE ele.attachEvent(type,fn); } } let ele = document.querySelector("#first"); bind(ele,function(){console.log("hehe");},"click"); //執(zhí)行一次判斷 bind(ele,function(){console.log("hehe");},"dbclick"); //第二次執(zhí)行判斷 bind(ele,function(){console.log("hehe");},"mouseover"); //第三次執(zhí)行判斷 ...
如果你綁定的事件越多,那么他每次綁定時(shí)都會(huì)執(zhí)行一次判斷. 為了減少判斷次數(shù),可以使用惰性載入函數(shù),即,先判斷再返回函數(shù).
function bind(){ if(document.addEventListener){ bind = function(ele,fn,type){ ele.addEventListener(type,fn,false); } }else if(document.attachEvent){ //檢測(cè)低版本的IE bind = function(ele,fn,type){ ele.attachEvent(type,fn); } }else{ throw "u browser is from outer space"; } } bind(); //首先檢測(cè)一遍,然后返回對(duì)應(yīng)的檢測(cè)版本 console.log(bind); //可以檢測(cè)一下現(xiàn)在bind里面的內(nèi)容 //當(dāng)然如果不爽的話可以直接使用匿名函數(shù),直接執(zhí)行 var bind = (function(){ if(document.addEventListener){ return function(ele,fn,type){ ele.addEventListener(type,fn,false); } }else if(document.attachEvent){ //檢測(cè)低版本的IE return function(ele,fn,type){ ele.attachEvent(type,fn); } }else{ throw "u browser is from outer space"; } })(); console.log(bind);
本人推薦下面哪種寫法,因?yàn)檠院?jiǎn)意賅,不用顯示調(diào)用~.
函數(shù)的綁定這個(gè)坑應(yīng)該大多數(shù)人都踩過(guò).比如我使用單例,創(chuàng)建了一系列的函數(shù)和內(nèi)容.然后再執(zhí)行綁定.
let sendMsg = { ele: document.querySelector("#element"), change:function(){ this.ele.classList.toggle(".active"); //改變狀態(tài) } } document.querySelector("#button").addEventListener("click",sendMsg.change,false);
意淫的效果是,點(diǎn)擊#button元素,#element會(huì)改變狀態(tài)。但實(shí)際是會(huì)報(bào)錯(cuò)。找不到你的ele.
原因出現(xiàn)在,綁定事件的回調(diào)函數(shù)是在全局作用域中執(zhí)行的。 上面那種寫法,就像當(dāng)對(duì)于把change函數(shù)的代碼給拷貝到第二個(gè)參數(shù).
即
document.querySelector("#button").addEventListener("click",function(){ this.ele.classList.toggle(".active"); //改變狀態(tài) },false);
而執(zhí)行的時(shí)候,是在window的全局環(huán)境里執(zhí)行的。所以會(huì)拋出錯(cuò)誤。解決辦法就是創(chuàng)建一個(gè)閉包,來(lái)保存這個(gè)調(diào)用方法的作用域.
document.querySelector("#button").addEventListener("click",function(){ sendMsg.change(); },false);
這樣就不會(huì)出錯(cuò)了。
但這樣寫有悖我們作為一名代碼藝術(shù)家的風(fēng)格。 通常是不提倡使用閉包的(即不要讓別人看出來(lái)你在使用閉包). 這時(shí)候可以自己創(chuàng)建一個(gè)綁定函數(shù)(I call it as 代理)
function bind(fn,context){ return function(){ fn.apply(context,arguments); //arguments是作為參數(shù)傳入的 } } //上面的閉包可以改為 document.querySelector("#button").addEventListener("click",bind(sendMsg.change,sendMsg),false);
在es5中,每個(gè)函數(shù)都自帶了自已bind的方法,這樣就更容易,讓別人看不出,你在使用閉包了。
document.querySelector("#button").addEventListener("click",sendMsg.change.bind(sendMsg),false);
由于這個(gè)方法只兼容到IE9+,所以遇到IE8的時(shí)候你就呵呵了.
函數(shù)的Curry函數(shù)的柯里化應(yīng)該算是函數(shù)綁定的一個(gè)升級(jí)版。但他們兩個(gè)有個(gè)共同點(diǎn)就是: 都是用了閉包并且返回了一個(gè)函數(shù). 但是Curry 可以額外的傳入?yún)?shù),這是函數(shù)綁定所不具備的.
關(guān)于Curry還有一個(gè)好處就是,實(shí)現(xiàn)自定義參數(shù)函數(shù)的重用性.
//這是JS高程上面的例子 function curry(fn){ var args = Array.prototype.slice.call(arguments,1); return function(){ var innerArgs = Array.prototype.slice.call(arguments); var final = args.concat(innerArgs); } } function add(num1,num2){ return num1+num2; } var Cadd = curry(add,5); console.log(Cadd(3)); //8 console.log(Cadd(5)); //10
可以重寫上面的bind
function bind(fn,context){ var args = Array.prototype.slice.call(arguments,2); //獲取上面兩個(gè)參數(shù)以外的其余參數(shù) return function(){ //獲取你第二次傳入的參數(shù),并轉(zhuǎn)化為數(shù)組 var innerArgs = Array.prototype.slice.call(arguments); var final = args.concat(innerArgs); fn.apply(context,final); //使用apply解析參數(shù)并調(diào)用. } }
這樣我們就可以傳入多個(gè)參數(shù),而且還可以自定義參數(shù). 當(dāng)然也可以使用原來(lái)的調(diào)用方式。
差不多了,覺(jué)得上面的如果你用到了,說(shuō)明你的js水平應(yīng)該有一些,如果沒(méi)有用到的話,可以當(dāng)做學(xué)習(xí),萬(wàn)一以后踩坑了,應(yīng)該知道自己是怎么屎的~
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://m.specialneedsforspecialkids.com/yun/78432.html
摘要:我打算把一些上使用的高級(jí)技巧寫成你不知道的這一系列的博文,希望大家一起學(xué)習(xí)學(xué)習(xí)。然而,這還不是最嚴(yán)重的,因?yàn)榈恼Z(yǔ)法比較寬松和隨意,所以同一功能多種寫法,各種奇葩都有。總結(jié)前端在調(diào)試代碼的時(shí)候,知道開(kāi)發(fā)工具上的小技巧,可以提高查找問(wèn)題的效率。 Web前端開(kāi)發(fā)過(guò)程中必然會(huì)用到Chrome瀏覽器自帶的開(kāi)發(fā)者工具Chrome DevTools,使用它作為Web前端開(kāi)發(fā)性能調(diào)試的必備工具。就連隔...
摘要:本文首發(fā)于我的博客在前面兩篇文章你不知道的一和你不知道的二中大致介紹了一些方面比較隱晦的但又很實(shí)用的技巧。系列文章你不知道的一你不知道的二本文首發(fā)于我的博客 本文首發(fā)于我的博客 在前面兩篇文章《你不知道的CSS(一)》和《你不知道的CSS(二)》中大致介紹了一些CSS方面比較隱晦的但又很實(shí)用的技巧。相信這些技巧會(huì)為大家在項(xiàng)目實(shí)踐中帶來(lái)一定的幫助,本文作為《你不知道的CSS》系列的第三篇...
摘要:歡迎來(lái)我的個(gè)人站點(diǎn)性能優(yōu)化其他優(yōu)化瀏覽器關(guān)鍵渲染路徑開(kāi)啟性能優(yōu)化之旅高性能滾動(dòng)及頁(yè)面渲染優(yōu)化理論寫法對(duì)壓縮率的影響唯快不破應(yīng)用的個(gè)優(yōu)化步驟進(jìn)階鵝廠大神用直出實(shí)現(xiàn)網(wǎng)頁(yè)瞬開(kāi)緩存網(wǎng)頁(yè)性能管理詳解寫給后端程序員的緩存原理介紹年底補(bǔ)課緩存機(jī)制優(yōu)化動(dòng) 歡迎來(lái)我的個(gè)人站點(diǎn) 性能優(yōu)化 其他 優(yōu)化瀏覽器關(guān)鍵渲染路徑 - 開(kāi)啟性能優(yōu)化之旅 高性能滾動(dòng) scroll 及頁(yè)面渲染優(yōu)化 理論 | HTML寫法...
摘要:歡迎來(lái)我的個(gè)人站點(diǎn)性能優(yōu)化其他優(yōu)化瀏覽器關(guān)鍵渲染路徑開(kāi)啟性能優(yōu)化之旅高性能滾動(dòng)及頁(yè)面渲染優(yōu)化理論寫法對(duì)壓縮率的影響唯快不破應(yīng)用的個(gè)優(yōu)化步驟進(jìn)階鵝廠大神用直出實(shí)現(xiàn)網(wǎng)頁(yè)瞬開(kāi)緩存網(wǎng)頁(yè)性能管理詳解寫給后端程序員的緩存原理介紹年底補(bǔ)課緩存機(jī)制優(yōu)化動(dòng) 歡迎來(lái)我的個(gè)人站點(diǎn) 性能優(yōu)化 其他 優(yōu)化瀏覽器關(guān)鍵渲染路徑 - 開(kāi)啟性能優(yōu)化之旅 高性能滾動(dòng) scroll 及頁(yè)面渲染優(yōu)化 理論 | HTML寫法...
摘要:歡迎來(lái)我的個(gè)人站點(diǎn)性能優(yōu)化其他優(yōu)化瀏覽器關(guān)鍵渲染路徑開(kāi)啟性能優(yōu)化之旅高性能滾動(dòng)及頁(yè)面渲染優(yōu)化理論寫法對(duì)壓縮率的影響唯快不破應(yīng)用的個(gè)優(yōu)化步驟進(jìn)階鵝廠大神用直出實(shí)現(xiàn)網(wǎng)頁(yè)瞬開(kāi)緩存網(wǎng)頁(yè)性能管理詳解寫給后端程序員的緩存原理介紹年底補(bǔ)課緩存機(jī)制優(yōu)化動(dòng) 歡迎來(lái)我的個(gè)人站點(diǎn) 性能優(yōu)化 其他 優(yōu)化瀏覽器關(guān)鍵渲染路徑 - 開(kāi)啟性能優(yōu)化之旅 高性能滾動(dòng) scroll 及頁(yè)面渲染優(yōu)化 理論 | HTML寫法...
閱讀 3060·2021-11-22 15:29
閱讀 1743·2021-10-12 10:11
閱讀 1783·2021-09-04 16:45
閱讀 2260·2021-08-25 09:39
閱讀 2802·2021-08-18 10:20
閱讀 2529·2021-08-11 11:17
閱讀 458·2019-08-30 12:49
閱讀 3322·2019-08-30 12:49