很早就想研究underscore源码了,虽然underscore.js这个库有些过期了,可是我仍是想学习一下库的架构,函数式编程以及经常使用方法的编写这些方面的内容,又刚好没什么其它要研究的了,因此就告终研究underscore源码这一心愿吧。html
underscore.js源码研究(1)
underscore.js源码研究(2)
underscore.js源码研究(3)
underscore.js源码研究(4)
underscore.js源码研究(5)
underscore.js源码研究(6)
underscore.js源码研究(7)
underscore.js源码研究(8)node
参考资料:underscore.js官方注释,undersercore 源码分析,undersercore 源码分析 segmentfaultgit
对于类型判断,大部分元素能够经过Object.prototype.toString的结果进行判断,包括:Arguments, Function, String, Number, Date, RegExp, Symbol, Map, WeakMap, Set, WeakSet。实例以下:正则表达式
//判断是否为函数,判断其余的只要把下面的Function改为其它的就能够了 function isFunction (obj) { return Object.prototype.toString.call(obj) === '[object Function]'; } //创建一个函数 var haha = function haha() { consolog.log('haha'); } console.log(isFunction(haha)); //输出true console.log(isFunction(123)); //输出false
注意,IE9 之前的版本以及早期 V8 引擎对类型判断有一些小bug,underscore.js修复了这些问题,具体可自行查看underscore.js源码。编程
判断是否为DOM节点,使用nodeType属性:segmentfault
function isElement(obj) { return !!(obj && obj.nodeType === 1); }
判断是否为数组,优先使用Array.isArray,不支持则使用Object.prototype.toStringapi
var isArray = Array.isArray || function(obj) { return Object.prototype.toString.call(obj) === '[object Array]'; }
使用typeof来判断是否为对象。数组
function isObject(obj) { var type = typeof obj; return type === 'function' || type ==='object' && !!obj; }
能够看到,函数会被判断为对象,空对象{},undefined,null,NaN 等则不被认为是对象。架构
判断是否有限。主要是使用js全局提供的isFinite函数来判断。函数式编程
function isFinite(obj) { return !_.isSymbol(obj) && isFinite(obj) && !isNaN(parseFloat(obj)); }
最后那个!isNaN(parseFloat(obj))是为了排除bool值。
判断是否为NaN,主要经过js全局提供的isNaN来判断。
function isNaN(obj) { return _.isNumber(obj) && isNaN(obj); }
判断是否为Boolean。
function isBoolean(obj) { return obj === true || obj === false || Object.prototype.toString.call(obj) === '[object Boolean]'; }
判断是不是null,直接判断便可。
function isNull(obj) { return obj === null; }
判断是不是undefined,利用void 0。
function isUndefined(obj) { return obj === void 0; }
不少时候咱们都要判断2个元素的相等性,在这个时候咱们能够先判断它们的类型,而后再判断它们的值。能够有一些特殊的状况:
它们的解决方案以下:
这里我不打算写通常的比较状况,只是把几个特殊的状况写一下:
主要是转化为字符串再比较
Eq = function(a, b) { if (Object.prototype.toString.call(a) !== Object.prototype.toString.call(b)) return false; return '' + a === '' + b; }
须要排除0和NaN的状况,而且利用+a把a转化为数字。
Eq = function(a, b) { if (Object.prototype.toString.call(a) !== Object.prototype.toString.call(b)) return false; return +a === 0 ? 1 / +a === 1 / b : +a === +b; }
利用+a把a转化为数字。
Eq = function(a, b) { if (Object.prototype.toString.call(a) !== Object.prototype.toString.call(b)) return false; return +a === +b; }
利用SymbolProto.valueOf方法。
Eq = function(a, b) { if (Object.prototype.toString.call(a) !== Object.prototype.toString.call(b)) return false; return SymbolProto.valueOf.call(a) === SymbolProto.valueOf.call(b); }
注意:不能直接用'=='或者'==='来判断对象的相等性,缘由以下:
var a = new Object(); var b = new Object(); a.name = "mm"; b.name = "mm"; console.log(a == b); //false