摘要:在這種惰性判斷里,我們利用了函數(shù)一等公民的身份和立即執(zhí)行的便利,進行了初始判斷,隨后通過語句進行變量的重賦值,進而達到了性能上的提高。
常規(guī)的檢測方式在SPA、各種MV*框架如日中天,前后端分離、工程化大行其道的現(xiàn)如今來看,能力檢測似乎已經(jīng)不那么重要,因為大多產(chǎn)品已經(jīng)不再需要去兼容老舊的IE,或者說是更多偏向移動端的開發(fā),雖然一些兼容的坑依舊存在,但是通過層出不窮的自動化工具,我們已經(jīng)不必事事躬親了。然而今天要向大家分享的則是關(guān)于事件兼容性的能力檢測,可能看上去沒什么大的用場,卻是我們理解惰性函數(shù)的好途徑。
先看一則常見的事件監(jiān)聽封裝
function addEvent(ele, type, cb, isCap) { if (window.addEventListener) { ele.addEventListener(type, cb, isCap); } else if (window.attachEvent) { ele.attachEvent(type, function () { var args = [].prototype.slice(0); window.event[target] = window.event.srcElement; args.unshift(window.event); cb.apply(this, args); }); } else { ele["on" + type] = cb; } } var body = document.body; addEvent(body,"load",function () { console.log("onload") // onload }); addEvent(body,"click",function () { console.log("onclick") // onclick });
可以看的到,這是一個有著足夠兼容性的的事件方法,能夠應(yīng)付常見的需求和場面。
只是細細想來,當我們將這個方法復(fù)用了很多次后,會發(fā)現(xiàn)每次復(fù)用都會重新進行一次能力檢測,以便符合當前宿主環(huán)境。可能你會想,對于瀏覽器性能過剩的現(xiàn)如今來說,這點性能損耗并不算什么。
那么不妨做個假設(shè),當我們在做一個高頻操作,例如window.onresize的監(jiān)聽,鼠標隨便輕輕一拖,就可能會觸發(fā)無數(shù)次事件的重載。
面臨這種狀況,常規(guī)情況下,有經(jīng)驗的開發(fā)者大致會做兩種處理來改善性能。
惰性檢測方式函數(shù)節(jié)流,將方法限頻,過濾一些線性重復(fù)性的操作。這方面,在loadash和underscore都有相應(yīng)的方法。日后我也會分享出原生的實現(xiàn)方式。
從源頭找起,把不必要的能力檢測去除,我們只在頁面加載時檢測一次不好嗎?
函數(shù)節(jié)流我們?nèi)蘸笤俜窒恚敲矗绾伟巡槐匾哪芰z測去除掉呢?下面有兩種實現(xiàn)方式,代碼如下:
//使用惰性函數(shù) var addEvent = (function () { //立即執(zhí)行 if (window.addEventListener) { return function (ele, type, cb, isCap) { ele.addEventListener(type, cb, isCap); } } else if (window.attachEvent) { return function (ele, type, cb) { ele.attachEvent(type, function () { var args = [].prototype.slice(0); window.event[target] = window.event.srcElement; args.unshift(window.event); cb.apply(this, args); }); } } else { return function (ele, type, cb) { ele["on" + type] = cb; } //初始判斷過后,addEvent就無需再次判斷,已經(jīng)是正確的封裝。 } }());
代碼變化并不大,關(guān)鍵點在于,我們用到了立即執(zhí)行函數(shù),即方法在初始化完畢,便立即判斷,判斷后,返回適合當前場景的方法。
//常見的方法調(diào)用方式 function getName() { console.log("ives") } getName() // ives;
//立即執(zhí)行 可以是聲明函數(shù) 也可以是匿名函數(shù) 兩種方式均可 (function getName() { console.log("ives") // ives }());
在常見的高階函數(shù)實踐中,我們時常會接受函數(shù),對函數(shù)的參數(shù)或者是上下文環(huán)境進行一些改造,并返回。在這種惰性判斷里,我們利用了函數(shù)一等公民的身份和立即執(zhí)行的便利,進行了初始判斷,隨后通過return語句進行變量的重賦值,進而達到了性能上的提高。
實際上,很多常用的檢測,比如AJAX的封裝、獲取實際的CSS樣式等,都可以使用惰性函數(shù)處理。
重載檢測方式然而,這種方法也并非是完美的,我們假設(shè)另外一種場景,即是在靜態(tài)HTML中,我們引用的某個JS文件中有這個方法,但是這個HTML頁面并沒有事件性質(zhì)的交互,那么我們可以基于吹毛求疵,雞蛋里挑骨頭的角度來斷言,這次惰性加載是失敗的,無用的。因為我們浪費了系統(tǒng)的資源,我們沒有事件,你為什么要加載一次?
總而言之,惰性加載雖然性能有提升,卻仍然不是最好的處理,只是有利于我們對于惰性函數(shù)的理解。
什么情景才是最完美的呢?即是初次調(diào)用時才做第一次判斷,隨后,無需判斷,方法也很簡單,只要簡單的改動幾行代碼。
依舊是以事件為例,代碼如下:
var addEvent = function (ele,type,cb,isCap) { //取消了立即執(zhí)行 初次調(diào)用時進行方法重載 if (window.addEventListener) { addEvent = function (ele, type, cb, isCap) { ele.addEventListener(type, cb, isCap); } } else if (window.attachEvent) { addEvent = function (ele, type, cb) { ele.attachEvent(type, function () { var args = [].prototype.slice(0); window.event[target] = window.event.srcElement; args.unshift(window.event); cb.apply(this, args); }); } } else { addEvent = function (ele, type, cb) { ele["on" + type] = cb; } } //初次調(diào)用時,手動執(zhí)行重載的方法 addEvent(ele,type,cb,isCap); };
可以看到實現(xiàn)的方式異常簡單,通過對方法的重載,并在初始執(zhí)行時手動執(zhí)行重載后的方法,滿足了我們上述的條件。
結(jié)束語可能大家會說,你個標題黨,最后一種重載的方式才是相對完美的方式,今天又為什么要講惰性函數(shù)呢?無外,拋磚引玉罷了,在鉆研設(shè)計模式時,是絕對離不開閉包和惰性函數(shù)的,今天則算是小小的熱身。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/89398.html
摘要:作用域安全的構(gòu)造函數(shù)會首先確認對象是正確類型的實例,然后再進行更改,如下這樣就避免了在全局對象上意外更改或設(shè)置屬性。在多人協(xié)作的項目中,為了避免他們誤改了全局對象,也應(yīng)使用作用域安全的構(gòu)造函數(shù)。 博客原文地址:Claiyre的個人博客如需轉(zhuǎn)載,請在文章開頭注明原文地址 在JavaScript中,函數(shù)的功能十分強大。它們是第一類對象,也可以作為另一個對象的方法,還可以作為參數(shù)傳入另一個函...
摘要:在執(zhí)行函數(shù)時,通過保存堆棧狀態(tài),再保存堆棧跳出后返回位置的指針,最后對變量賦值。這看上去沒有問題,只要將值存在堆棧就搞定了。 1. 引言 本周精讀的文章是 V8 引擎 Lazy Parsing,看看 V8 引擎為了優(yōu)化性能,做了怎樣的嘗試吧! 這篇文章介紹的優(yōu)化技術(shù)叫 preparser,是通過跳過不必要函數(shù)編譯的方式優(yōu)化性能。 2. 概述 & 精讀 解析 Js 發(fā)生在網(wǎng)頁運行的關(guān)鍵路...
摘要:函數(shù)是一等公民。其實閉包本身也是函數(shù)式編程的一個應(yīng)用。劣勢不能算是嚴格意義上的函數(shù)式語言,很多函數(shù)式編程的特性并沒有。 隨著大前端時代的到來,在產(chǎn)品開發(fā)過程中,前端所占業(yè)務(wù)比重越來越大、交互越來越重。傳統(tǒng)的老夫拿起JQuery就是一把梭應(yīng)付當下重交互頁面已經(jīng)十分乏力。于是乎有了Angular,React,Vue這些現(xiàn)代框架。 但隨之而來的還有大量的新知識新名詞,如MVC,MVVM,F(xiàn)l...
摘要:函數(shù)是一等公民。其實閉包本身也是函數(shù)式編程的一個應(yīng)用。劣勢不能算是嚴格意義上的函數(shù)式語言,很多函數(shù)式編程的特性并沒有。 隨著大前端時代的到來,在產(chǎn)品開發(fā)過程中,前端所占業(yè)務(wù)比重越來越大、交互越來越重。傳統(tǒng)的老夫拿起JQuery就是一把梭應(yīng)付當下重交互頁面已經(jīng)十分乏力。于是乎有了Angular,React,Vue這些現(xiàn)代框架。 但隨之而來的還有大量的新知識新名詞,如MVC,MVVM,F(xiàn)l...
摘要:更多描述可見文檔這種惰性求值的方法在很多模塊中都會使用,比如中的使用上與例子一致,如表單中的討論在大部分情況下,讓屬性具有惰性求值能力的全部意義就在于提升程序性能。當不需要這個屬性時就能避免進行無意義的計算,同時又能阻止該屬性重復(fù)進行計算。 起步 我們希望將一個只讀的屬性定義為 property 屬性方法,只有在訪問它時才進行計算,但是,又希望把計算出的值緩存起來,不要每次訪問它時都重...
閱讀 1453·2021-09-02 19:23
閱讀 1601·2021-08-11 11:19
閱讀 646·2019-08-30 15:55
閱讀 1657·2019-08-30 12:50
閱讀 2245·2019-08-30 11:23
閱讀 2187·2019-08-29 13:13
閱讀 1507·2019-08-28 18:13
閱讀 3347·2019-08-26 11:53