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