摘要:總想找個機會夯實一下自己的基礎(chǔ),正好最近略有清閑,看視頻讀書擼代碼我選擇了第三者怎么感覺有點別扭,看視頻的話效率不高適合入門,看書的話一本你不知道的推薦給大家,選擇繼續(xù)看書的話還是算了吧,畢竟讀萬卷書不如行萬里路是吧。
總想找個機會夯實一下自己的JS基礎(chǔ),正好最近略有清閑,看視頻?讀書?擼代碼?我選擇了第三者(怎么感覺有點別扭),看視頻的話效率不高適合入門,看書的話,一本《你不知道的JavaScript》推薦給大家,選擇繼續(xù)看書的話還是算了吧,畢竟讀萬卷書不如行萬里路是吧。擼代碼的話,擼個項目?自己雜七雜八寫了不少了,都是老套路難有新的突破,想想倒不如研究研究大神的代碼,學(xué)習(xí)學(xué)習(xí)大神的結(jié)構(gòu)設(shè)計,技術(shù)細(xì)節(jié)等站在大神的肩膀上是吧。在選擇是翻譯Loadsh或Underscore的時候我更偏向于前者,因為念起來比較順嘴,但當(dāng)我看到Loadsh源碼的時候發(fā)現(xiàn),這個!這個!我發(fā)現(xiàn)“安得兒私購”其實也挺順嘴的,1600多行,API豐富,結(jié)構(gòu)清晰,就你了。最后在補充幾句,看源碼的感覺有點像“春天的雨,潤物細(xì)無聲”,沒感覺自己技術(shù)有多大提高,但當(dāng)看到其他類庫的時候已經(jīng)知其大概結(jié)構(gòu),當(dāng)要自己實現(xiàn)_.flatten或_.chain的時候已經(jīng)有了思路,也算是有所進(jìn)步吧。此分析文章會持續(xù)更新,如有錯誤感謝提出!
原文地址
//參考文檔:http://underscorejs.org/ //參考文檔:http://www.bootcss.com/p/underscore/ /* 建議: 1 剛開始不要一行一行跟下來敲,先了解一下庫的整體結(jié)構(gòu) 2 遇到不懂的打個斷點,多跟蹤幾遍,斷點很重要 3 有些內(nèi)部函數(shù)使用頻率很高(cb....),這些內(nèi)部函數(shù)了解清楚了后續(xù)看起來輕松不少 4 有些函數(shù)內(nèi),有較多的函數(shù)引用,建議多讀幾遍 */ (function() { //獲取根對象,瀏覽器是window(self),Node是global,window.window===window返回true,global亦然 var root = typeof self == "object" && self.self === self && self || typeof global == "object" && global.global === global && global || this || {}; //獲取現(xiàn)有的_對象,避免沖突,具體解決沖突方法后面會說 var previousUnderscore = root._; //獲取原型對象,為的是寫起來方便不用每次都xxx.proto...一大推 var ArrayProto = Array.prototype, ObjProto = Object.prototype; var SymbolProto = typeof Symbol !== "undefined" ? Symbol.prototype : null; var push = ArrayProto.push, slice = ArrayProto.slice, toString = ObjProto.toString, hasOwnProperty = ObjProto.hasOwnProperty; var nativeIsArray = Array.isArray, nativeKeys = Object.keys, nativeCreate = Object.create; //中轉(zhuǎn)函數(shù),后面用到會說 var Ctor = function(){}; /* _的構(gòu)造函數(shù), 第一步是看看obj是否是_的實例,如果是就不操作直接返回,有點像$($("#d1")),jq或zepto里也有相似的判斷 第二步是判斷this是否是_的實例,不是則進(jìn)行new 調(diào)用, 注意,在進(jìn)行new調(diào)用的時候 new會做4件事,1創(chuàng)建空對象,2空對象的__proto__指向函數(shù)的prototype,3this指向空對象(此時可能會添加屬性等),4判斷返回值, 而此時在當(dāng)前的_里this已經(jīng)指向空對象 第三步為當(dāng)前對象添加_wrapped屬性,這是為了后面的鏈?zhǔn)秸{(diào)用做準(zhǔn)備 */ var _ = function(obj) { if (obj instanceof _) return obj; if (!(this instanceof _)) return new _(obj); this._wrapped = obj; }; //根據(jù)當(dāng)前環(huán)境添加_對象 if (typeof exports != "undefined" && !exports.nodeType) { if (typeof module != "undefined" && !module.nodeType && module.exports) { exports = module.exports = _; } exports._ = _; } else { root._ = _; } // 版本號 _.VERSION = "1.8.3"; //下面就是一些常用的方法了,后面會一點一點分析 // _.each=_.forEach=function(){......} //... //... //... /* 鏈?zhǔn)胶瘮?shù) 實例化當(dāng)前對象,設(shè)置_china為true,此為判斷鏈?zhǔn)秸{(diào)用屬性,true為鏈?zhǔn)秸{(diào)用 */ _.chain = function(obj) { var instance = _(obj); instance._chain = true; return instance; }; //判斷是否繼續(xù)鏈?zhǔn)秸{(diào)用 var chainResult = function(instance, obj) { return instance._chain ? _(obj).chain() : obj; }; /* 擴(kuò)展_的方法 第一步遍歷obj里所含方法,執(zhí)行回調(diào) 回調(diào)內(nèi) 1獲取obj的function,擴(kuò)展到_里,并保存到func 2對_的prototype進(jìn)行擴(kuò)展,擴(kuò)展函數(shù)里進(jìn)行取值添加等操作(注意this指向),最后執(zhí)行func.apply(_, args)(注意apply還有打散數(shù)組的功能)把結(jié)果和this作為參數(shù)傳遞到chainResult中,判斷是否繼續(xù)鏈?zhǔn)秸{(diào)用 第二步 返回_ 最后在解釋一下為什么_.prototype[name]=function(){....},如果理解請?zhí)^此段 大家一般都是_.filter({name:"Mr.zhou"},function(){.....}) 鏈?zhǔn)秸{(diào)用說白了就是將第一個方法的執(zhí)行結(jié)果作為參數(shù)傳到第二個方法里,如此依次傳遞,直到最后一個返回結(jié)果; 想要鏈?zhǔn)秸{(diào)用常用的_.filter(...)的方法肯定是不行了,具體實現(xiàn)請看例子 var stooges = [{name: "curly", age: 25}, {name: "moe", age: 21}, {name: "larry", age: 23}]; var youngest = _.chain(stooges) .sortBy(function(stooge){ return stooge.age; }) .value(); 1 創(chuàng)建stooges對象 2 創(chuàng)建youngest變量 3 詳細(xì)看一下youngest值的計算方法 3.1 先是_.chain(stooges)這句話做了什么呢?(可以回顧一下之前的代碼) 調(diào)用_.chain(stooges),內(nèi)部對_進(jìn)行實例化,并把stooges作為_wrapped的值,并添加了一個名為_chain值為true的屬性, 最后得到的就是這樣一個對象{_wrapped:[{name: "curly", age: 25}...],_chain:true} 3.2 繼續(xù)調(diào)用 {_wrapped:[{name: "curly", age: 25}...],_chain:true}.sortBy(function(stooge){ return stooge.age; }) .value(); 等等,這樣對嗎?內(nèi)個什么對象調(diào)用.sortBy不報錯嗎?它有這個方法嗎? 是有的,你沒聽錯,那么在哪里呢? 請看_.mixin的這句換_.prototype[name]=function(){....} 這句話就是在往_的原型對象中添加方法,在這句話之前的_.mixin(_),與其內(nèi)部的_.each(_.function(obj),...)就是將_上面的所有方法的地址引用傳遞給_.prototype上,而{_wrapped:[{name: "curly", age: 25}...],_chain:true}對象又是_的實例對象,自然也就繼承了_.prototype的方法,這也就是鏈?zhǔn)秸{(diào)用的原理 3.3 最后調(diào)用value()來返回它的_wrapped就此結(jié)束 */ _.mixin = function(obj) { _.each(_.functions(obj), function(name) { var func = _[name] = obj[name]; _.prototype[name] = function() { var args = [this._wrapped]; push.apply(args, arguments); return chainResult(this, func.apply(_, args)); }; }); return _; }; //自調(diào)mixin并把_傳入 _.mixin(_); // 同mixin差不多添加方法 _.each(["pop", "push", "reverse", "shift", "sort", "splice", "unshift"], function(name) { var method = ArrayProto[name]; _.prototype[name] = function() { var obj = this._wrapped; method.apply(obj, arguments); if ((name === "shift" || name === "splice") && obj.length === 0) delete obj[0]; return chainResult(this, obj); }; }); // 同mixin差不多添加方法 _.each(["concat", "join", "slice"], function(name) { var method = ArrayProto[name]; _.prototype[name] = function() { return chainResult(this, method.apply(this._wrapped, arguments)); }; }); // _.chain的value方法 _.prototype.value = function() { return this._wrapped; }; //添加相應(yīng)方法 _.prototype.valueOf = _.prototype.toJSON = _.prototype.value; //添加相應(yīng)方法 _.prototype.toString = function() { return String(this._wrapped); }; //對AMD的兼容 if (typeof define == "function" && define.amd) { define("underscore", [], function() { return _; }); } }());
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://m.hztianpu.com/yun/87325.html
摘要:模塊化是隨著前端技術(shù)的發(fā)展,前端代碼爆炸式增長后,工程化所采取的必然措施。目前模塊化的思想分為和。特別指出,事件不等同于異步,回調(diào)也不等同于異步。將會討論安全的類型檢測惰性載入函數(shù)凍結(jié)對象定時器等話題。 Vue.js 前后端同構(gòu)方案之準(zhǔn)備篇——代碼優(yōu)化 目前 Vue.js 的火爆不亞于當(dāng)初的 React,本人對寫代碼有潔癖,代碼也是藝術(shù)。此篇是準(zhǔn)備篇,工欲善其事,必先利其器。我們先在代...
摘要:即將立秋的課多周刊第期我們的微信公眾號,更多精彩內(nèi)容皆在微信公眾號,歡迎關(guān)注。若有幫助,請把課多周刊推薦給你的朋友,你的支持是我們最大的動力。課多周刊機器人運營中心是如何玩轉(zhuǎn)起來的分享課多周刊是如何運營并堅持下來的。 即將立秋的《課多周刊》(第2期) 我們的微信公眾號:fed-talk,更多精彩內(nèi)容皆在微信公眾號,歡迎關(guān)注。 若有幫助,請把 課多周刊 推薦給你的朋友,你的支持是我們最大...
摘要:即將立秋的課多周刊第期我們的微信公眾號,更多精彩內(nèi)容皆在微信公眾號,歡迎關(guān)注。若有幫助,請把課多周刊推薦給你的朋友,你的支持是我們最大的動力。課多周刊機器人運營中心是如何玩轉(zhuǎn)起來的分享課多周刊是如何運營并堅持下來的。 即將立秋的《課多周刊》(第2期) 我們的微信公眾號:fed-talk,更多精彩內(nèi)容皆在微信公眾號,歡迎關(guān)注。 若有幫助,請把 課多周刊 推薦給你的朋友,你的支持是我們最大...
閱讀 3824·2021-11-24 10:23
閱讀 2832·2021-09-06 15:02
閱讀 1346·2021-08-23 09:43
閱讀 2417·2019-08-30 15:44
閱讀 3113·2019-08-30 13:18
閱讀 837·2019-08-23 16:56
閱讀 1807·2019-08-23 16:10
閱讀 607·2019-08-23 15:08