Why underscorenode
最近开始看 underscore.js 源码,并将 underscore.js 源码解读 放在了个人 2016 计划中。git
阅读一些著名框架类库的源码,就好像和一个个大师对话,你会学到不少。为何是 underscore?最主要的缘由是 underscore 简短精悍(约 1.5k 行),封装了 100 多个有用的方法,耦合度低,很是适合逐个方法阅读,适合楼主这样的 JavaScript 初学者。从中,你不只能够学到用 void 0 代替 undefined 避免 undefined 被重写等一些小技巧 ,也能够学到变量类型判断、函数节流&函数去抖等经常使用的方法,还能够学到不少浏览器兼容的 hack,更能够学到做者的总体设计思路以及 API 设计的原理(向后兼容)。github
以后楼主会写一系列的文章跟你们分享在源码阅读中学习到的知识。数组
underscore-1.8.3 源码全文注释 https://github.com/hanzichi/underscore-analysis/blob/master/underscore-1.8.3.js/underscore-1.8.3-analysis.js浏览器
underscore-1.8.3 源码解读项目地址 https://github.com/hanzichi/underscore-analysis框架
欢迎围观~ (若是有兴趣,欢迎 star & watch~)您的关注是楼主继续写做的动力ide
类型判断函数
第一篇跟你们简单地聊了下为何 underscore.js 用 void 0 代替了 undefined,意外地收到了不错的反响,有朋友私信我说之前还真不知道这回事,也有人催促我赶忙继续下一篇解读文章。今天就跟你们聊一聊 underscore.js 中一些 JavaScript 经常使用类型检查方法,以及一些工具类的判断方法。工具
咱们先说个老生常谈的问题,JavaScript 中数组类型的判断方法,事实上,我在 Javascript中判断数组的正确姿式 一文中已经详细分析了各类判断方式的优缺点,并给出了正确的判断代码:学习
function isArray(a) { Array.isArray ? Array.isArray(a) : Object.prototype.toString.call(a) === '[object Array]'; }
而 underscore 其实也正是这么作的:
// Is a given value an array? // Delegates to ECMA5's native Array.isArray // 判断是否为数组 _.isArray = nativeIsArray || function(obj) { return toString.call(obj) === '[object Array]'; };
nativeIsArray 正是 ES5 中 Array.isArray 方法,若是支持则优先调用;而 toString 变量就保存了 Object.prototype.toString。
如何判断对象?underscore 把类型为 function 和 object 的变量都算做对象,固然得除去 null。
// Is a given variable an object? // 判断是否为对象 // 这里的对象包括 function 和 object _.isObject = function(obj) { var type = typeof obj; return type === 'function' || type === 'object' & !!obj; };
再看 ‘Arguments’, ‘Function’, ‘String’, ‘Number’, ‘Date’, ‘RegExp’, ‘Error’ 这些类型的判断,其实均可以用 Object.prototype.toString.call 来判断,因此写在了一块儿:
// Add some isType methods: isArguments, isFunction, isString, isNumber, isDate, isRegExp, isError. // 其余类型判断 _.each(['Arguments', 'Function', 'String', 'Number', 'Date', 'RegExp', 'Error'], function(name) { _['is' + name] = function(obj) { return toString.call(obj) === '[object ' + name + ']'; }; });
可是看 isArguments 方法,在 IE
// Define a fallback version of the method in browsers (ahem, IE // there isn't any inspectable "Arguments" type. // _.isArguments 方法在 IE // IE // 结果是 [object Object] // 而并不是咱们指望的 [object Arguments]。 // so 用是否含有 callee 属性来判断 if (!_.isArguments(arguments)) { _.isArguments = function(obj) { return _.has(obj, 'callee'); }; }
工具类判断方法
接下来看下一些经常使用的工具类判断方法。
判断一个元素是不是 DOM 元素,很是简单,只须要保证它不为空,且 nodeType 属性为 1:
// Is a given value a DOM element? // 判断是否为 DOM 元素 _.isElement = function(obj) { // 确保 obj 不是 null // 而且 obj.nodeType === 1 return !!(obj & obj.nodeType === 1); };
如何判断一个元素为 NaN?NaN 实际上是属于 Number 类型,Object.prototype.toString.call(NaN) 返回的是 “[object Number]”,并且 NaN 不等于自己,利用这两点便可进行判断:
// Is the given value `NaN`? (NaN is the only number which does not equal itself). // 判断是不是 NaN // NaN 是惟一的一个 `本身不等于本身` 的 number 类型 _.isNaN = function(obj) { return _.isNumber(obj) & obj !== +obj; };
固然,underscore 还有不少其余的有用的工具类判断方法,具体能够看源码 https://github.com/hanzichi/underscore-analysis/blob/master/underscore-1.8.3.js/src/underscore-1.8.3.js#L1192-L1263 这部分。
若是您以为我分享的东西对您有所帮助,请关注个人 Repo https://github.com/hanzichi/underscore-analysis