摘要:模塊的私有變量是預(yù)先定義好的,而柯里化是保存第一次調(diào)用時傳入的參數(shù)為私有變量。
前言
在平時的開發(fā)中,經(jīng)常會遇到一些特殊情況,就需要一些招式來應(yīng)對。這里總結(jié)一下自己常用到的一些小招式,有不足歡迎大家指出。
模塊var fuc1 = (function() { var a = "hello "; return function(str) { return a + str; } })() fuc1("world"); // hello world
模塊模式的一般形式是:一個定義了私有變量和函數(shù);利用閉包創(chuàng)建可以訪問私有變量和函數(shù)的特權(quán)函數(shù);最后返回這個特權(quán)函數(shù),或者把它們保存到一個可訪問的地方。
該招式有以下應(yīng)用場景
協(xié)調(diào)異步代碼需要在兩個異步fuc1與fuc2都執(zhí)行結(jié)束后再執(zhí)行,
var manager = (function() { var count = 0; return function() { if(++count === 2){ // logic 3 } } })() function fuc1() { //... } function fuc2() { //... } setTimeout(function() { fuc1(); manager(); }, 10) setTimeout(function() { fuc2(); manager(); }, 10)兼容測試
var createXHR = (function () { if(typeof XMLHttpRequest != "undefined") { return function () { return new XMLHttpRequest(); } }else if(typeof ActiveXObject != "undefined") { return function () { if(typeof arguments.callee.activeXString != "string") { var versions = ["MSXML2.XMLHttp.6.0", "MSXML2.XMLHttp.3.0", "MSXML2.XMLHttp"], i,len; for(1 = 0, len = versions.length; i < len; i++){ try{ new ActiveXObject(versions[i]); arguments.callee.activeXString = versions[i]; break; }catch(ex){ // ... } } } return new ActiveXObject(arguments.callee.activeXString); } }else{ return function() { throw new Error("NO XHR object available."); } } })();利用私有變量
var parse = (function() { var config = ["I", "II", "III", "IV"]; return function(num) { return config[num - 1] } })() parse(1); // I parse(4); // IV柯里化
柯里化聽起來很高大上,然而也就是Currying的音譯,千萬別被名稱嚇跑了。
它是把接受多個參數(shù)的函數(shù)中的參數(shù)拆分成兩次調(diào)用來傳遞并返回結(jié)果的新函數(shù)。
舉一個簡單的例子理解一下:
var add = function(a, b) { return a + b } add(1, 2) // 3 var currying = function(a) { return function(b) { return a + b } } currying(1)(2) // 3
add 為 接受多個參數(shù)的函數(shù),currying是將add中的參數(shù)分兩次調(diào)用傳入并返回結(jié)果的新函數(shù)。
仔細想想,它其實是模塊的衍生招式。模塊的私有變量是預(yù)先定義好的,而柯里化是保存第一次調(diào)用時傳入的參數(shù)為私有變量。因此它倆的區(qū)別是私有變量定義時機不同。
下面是一個利用柯里化實現(xiàn)的累加方法
var currying = function (fn) { var args = []; return function () { var innerArgs = Array.prototype.slice.call(arguments); if(innerArgs.length === 0){ return fn.apply(null, args) } args = args.concat(innerArgs); return arguments.callee; } } var mutil = function () { var num = 0, i = 0; while(arguments[i]){ num += arguments[i++] } return num } var add = currying(mutil); add(1,2)(3); add(4); add(); // 10函數(shù)節(jié)流
某些代碼不可以在沒有間斷的情況下連續(xù)重復(fù)執(zhí)行,所有就需要節(jié)流。比如:拖動某DOM元素時,需要動態(tài)改變元素的 x y ,就需要用到節(jié)流函數(shù)了。
function throttle(method, delay) { var timer = null; return function () { var that = this, args = arguments; clearTimeout(method.tId); timer = setTimeout(function () { method.apply(that, args); clearTimeout(timer); }, delay); } } window.onresize = throttle(resizeHandle, 50)
使用該函數(shù)時你會發(fā)現(xiàn)一個問題:不斷拖動元素的過程中元素是不動的,只有停頓一下元素才跟著動。
這樣的體驗很糟糕,為了提高性能、改善體驗,需要升級一下節(jié)流函數(shù)。設(shè)置一個最大時間間隔來確保在拖動的過程中,元素可以跟隨移動。
function throttle(method, context, delay, maxInterval) { var _start,_diff,timer; return function () { var that = this, args = arguments, _now = +new Date(); clearTimeout(timer); _start || (_start = _now); if(_now - _start >= maxInterval){ method.apply(that, args) }else{ timer = setTimeout(function () { method.apply(that, args) }, delay) } } } window.onresize = throttle(resizeHandle, 50, 100)延遲加載處理
在業(yè)務(wù)中經(jīng)常會遇到一些不需要同步處理的,又比較耗時的邏輯。對于這些邏輯可以采用數(shù)據(jù)分塊(array chunking)的技術(shù),小塊小塊地處理數(shù)組,通常每次一小塊??梢詣?chuàng)建一個“待辦事項”隊列,然后使用定時器逐個取出“事項”,接著設(shè)置另一個定時器。
function chunk(array, process, context) { setTimeout(function() { var item = array.shift(); process.call(context, item); if(array.length > 0){ setTimeout(arguments.callee, 100); } }, 100) }記憶函數(shù)
函數(shù)可以將先前操作的結(jié)果記錄在某個對象里,從而避免重復(fù)運算,比如計算階乘函數(shù)。
function memoizer(memory, handle) { return function (n) { var result = memory[n], recur = arguments.callee; // 已運算過則直接返回 if(!result){ result = handle(recur ,n); memory[n] = result; } return result; } } var memory = [1, 1], factorial = memoizer(memory, function (recur, n) { return n * recur(n - 1) }); factorial(4); console.log(memory); // [1, 1, 2, 6, 24]
(未完待續(xù)......)
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://m.hztianpu.com/yun/81148.html
摘要:建議先熟悉一遍修煉秘籍之命令篇,本秘籍食用更佳正文核心秘訣功法之究極總結(jié)操作次數(shù)操作行為操作范圍下面,我會將此秘訣親自傳授于你。 前言 少年,我看你骨骼精奇,是萬中無一的武學(xué)奇才,維護世界和平就靠你了,我這有本秘籍《Vim修煉秘籍》,見與你有緣,就十塊賣給你了! 如果你是一名 Vimer,那么恭喜你,你的 Vim 技能馬上要升級了 ?! 如果你之前不了解過 Vim ,那么也沒關(guān)系,本文...
摘要:扎實基礎(chǔ)幸好自己之前花了大力氣去給自己打基礎(chǔ),讓自己現(xiàn)在的基礎(chǔ)還算不錯。 寫文章不容易,點個贊唄兄弟專注 Vue 源碼分享,文章分為白話版和 源碼版,白話版助于理解工作原理,源碼版助于了解內(nèi)部詳情,讓我們一起學(xué)習(xí)吧研究基于 Vue版本 【2.5.17】 如果你覺得排版難看,請點擊 下面鏈接 或者 拉到 下面關(guān)注公眾號也可以吧 【Vue原理】Vue源碼閱讀總結(jié)大會 - 序 閱讀源碼是需...
閱讀 1409·2019-08-30 15:44
閱讀 2186·2019-08-30 11:04
閱讀 582·2019-08-29 15:17
閱讀 2608·2019-08-26 12:12
閱讀 3192·2019-08-23 18:09
閱讀 976·2019-08-23 15:37
閱讀 1609·2019-08-23 14:43
閱讀 2997·2019-08-23 13:13