Always want to target a framework of the source of a good study of programming ideas and skills, improve their own level, but seen some of the framework of the source, are feeling puzzled, see not very understand, Finally find this underscore.js because this is relatively short, more than 1000 lines, and easy to read, so decided to be it, that nonsense not much to start our source of learning.
Underscore.js source GitHub Address: Https://github.com/jashkenas/underscore/blob/master/underscore.jsthe Underscore.js version parsed in this article is 1.8.3Structure Analysislet's start with an overall structure (with comments added to explain)
1(function() {2 //creates a root object that is represented in the browser as a window (self) object and represents a global object in node. js .3 //the reason for using Self instead of window is to support Web Worker4 varRoot =typeofSelf = = ' object ' && self.self = = = Self && self | |5 typeofGlobal = = ' object ' && global.global = = = Global && Global | |6 This;7 //Save the value before the "_" (underscore variable) is overwritten8 varPreviousunderscore =root._;9 //prototype assignment for easy compressionTen varArrayproto = Array.prototype, Objproto =Object.prototype; One //assign a common method in a built-in object prototype to a reference variable for easier reference A varPush =Arrayproto.push, -Slice =Arrayproto.slice, -ToString =objproto.tostring, thehasOwnProperty =Objproto.hasownproperty; - //defines some of the ECMAScript 5 methods - varNativeisarray =Array.isarray, -Nativekeys =Object.keys, +Nativecreate =object.create; - //with the naked function of God horse, I do not know what the meaning, have to tell me + varCtor =function(){}; A //Create an underscore object at var_ =function(obj) { - //If you are on the prototype chain of "_" (that is, if the object pointed to by the _ prototype is the same object as obj, the "= = =" relationship is satisfied) - if(objinstanceof_)returnobj; - //if it is not, construct a - if(! ( This instanceof_))return New_ (obj); - //store the underscore object in the _.wrapped property in This. _wrapped =obj; - }; to //storing undersocre named variables in different objects for different hosting environments + if(typeofExports! = ' undefined ' &&!exports.nodetype) {//node. js - if(typeofModule! = ' undefined ' &&!module.nodetype &&module.exports) { theExports = Module.exports = _; * } $Exports._ = _;Panax Notoginseng}Else{//Browser -Root._ = _; the } + //Version number A_. VERSION = ' 1.8.3 '; the //here are the various methods that will be specified in future articles + . - . $ . $ . - . - . the //Create a chain function to support chained calls -_.chain =function(obj) {Wuyi varInstance =_ (obj); the //whether to use chained operations -Instance._chain =true; Wu returninstance; - }; About //returns whether the result of the call in _.chain is true, returns a wrapped underscore object, or returns the object itself $ varChainresult =function(instance, obj) { - returnInstance._chain?_ (obj). Chain (): obj; - }; - //an interface function to extend the underscore itself A_.mixin =function(obj) { + //shallow Copy object properties by looping through objects the_.each (_.functions (obj),function(name) { - varFunc = _[name] =Obj[name]; $_.prototype[name] =function() { the varargs = [ This. _wrapped]; the push.apply (args, arguments); the returnChainresult ( This, Func.apply (_, args)); the }; - }); in }; the _.mixin (_); the //add related methods in Array.prototype to the underscore object so that underscore objects can also call methods in Array.prototype directly About_.each ([' Pop ', ' push ', ' reverse ', ' shift ', ' sort ', ' splice ', ' unshift '],function(name) { the //Method Reference the varMETHOD =Arrayproto[name]; the_.prototype[name] =function() { + //assign to obj reference variable for easy invocation - varobj = This. _wrapped; the //call the array corresponding methodBayi method.apply (obj, arguments); the if(name = = = ' Shift ' | | name = = ' Splice ') && obj.length = = = 0)DeleteObj[0]; the //Support chain Operation - returnChainresult ( This, obj); - }; the }); the the //Same as above and supports chained operation the_.each ([' concat ', ' join ', ' slice '),function(name) { - varMETHOD =Arrayproto[name]; the_.prototype[name] =function() { the //returns the array object or the encapsulated array the returnChainresult ( This, Method.apply ( This. _wrapped, arguments));94 }; the }); the //returns the underscore object that is stored in the _wrapped property the_.prototype.value =function() {98 return This. _wrapped; About }; - 101 //provides some ways to make it easier for other situations102_.prototype.valueof = _.prototype.tojson =_.prototype.value;103_.prototype.tostring =function() {104 return"+ This. _wrapped; the };106 107 //some of the processing that AMD supports108 if(typeofdefine = = ' function ' &&define.amd) {109Define (' underscore ', [],function() { the return _;111 }); the }113}());
Summary of the specific analysis in the above source code in the comments written already very detailed, the following again straighten out the overall structure: first underscore wrapped in an anonymous self-executing function within the definition of a "_" variable will be underscore in the corresponding method to add to the _ prototype, created _ Object has the underscore method to add related methods in Array.prototype to the underscore object. This underscore object can also directly call the method in the Array.prototype after the article, I will focus on the method of underscore in the specific analysis, thank you for watching, but also hope to communicate with you to learn, what analysis of the wrong place welcome everyone criticism Point Reference 119 0000000515420http://yalishizhude.github.io/2015/09/22/underscore-source/
Underscore.js Source Code Analysis