首先看一些在object块定义的经常使用的类型判断函数。node
_.isElement = function(obj) { return !!(obj && obj.nodeType === 1); };
nodeType相关知识点:git
节点类型 | 描述 | 名称 | |
---|---|---|---|
1 | Element | 元素 | ELEMENT_NODE |
2 | Attr | 属性 | ATTRIBUTE_NODE |
3 | Text | 文本内容 | TEXT_NODE |
8 | Comment | 注释 | COMMENT_NODE |
9 | Document | 整个文档(DOM)树的根节点 | DOCUMENT_NODE |
11 | DocumentFragment | 某个文档片断 | DOCUMENT_FRAGMENT_NODE |
其实通常来讲是会隐式转换的...可能这里是在强制转换避免出错吧。github
_.isArray = nativeIsArray || function(obj) { return toString.call(obj) === '[object Array]'; };
呐呐...underscore的开头就引用了js原生的一些方法:正则表达式
var ArrayProto = Array.prototype, ObjProto = Object.prototype, FuncProto = Function.prototype; var push = ArrayProto.push, slice = ArrayProto.slice, toString = ObjProto.toString, hasOwnProperty = ObjProto.hasOwnProperty; var nativeIsArray = Array.isArray, nativeKeys = Object.keys, nativeBind = FuncProto.bind, nativeCreate = Object.create;
而关于[object Array]
...数组
当判断一个对象是否为数组时,不能用typeof
运算符进行操做,由于会返回object
:函数
typeof([]) // "object"
那这个时候怎么判断数组是否是数组呢...虽然如今有原生的isArray
来判断:spa
Array.isArray([]) // true
可是依然存在一种调用object的toString()
方法来判断的办法:prototype
Object.prototype.toString.call([]) // "[object Array]"
这个办法还能够用来判断别的各类类型:code
_.each(['Arguments', 'Function', 'String', 'Number', 'Date', 'RegExp', 'Error'], function(name) { _['is' + name] = function(obj) { return toString.call(obj) === '[object ' + name + ']'; }; });
_.each
方法以后会细说,当作原生的forEach
来看呐。对象
_.isObject = function(obj) { var type = typeof obj; return type === 'function' || type === 'object' && !obj; };
嗯...这里要注意的是运算符的优先级,&&优先级高于||,因此这里把函数也做为object来看待了...
_.isObject(function f() {}) // true
if (!_.isArguments(arguments)) { _.isArguments = function(obj) { return _.has(obj, 'callee'); }; }
由于IE<9下对arguments调用Object.prototype.toString.call()
,返回的是[object Object]
,而非[object Arguments]
,因此遇到这种状况须要判断一下是否还有callee属性。
if (typeof /./ != 'function' && typeof Int8Array != 'object') { _.isFunction = function(obj) { return typeof obj === 'function' || false; }; }
Safari5及以前版本、Chrome7及以前版本在对正则表达式调用typeof
操做符时会返回function
,因此就是为了功能兼容吧。
_.isFinite = function(obj) { return isFinite(obj) && !isNaN(parseFloat(obj)); };
用到了JavaScript的全局函数isFinite
,会检查参数是否为无穷大。
isFinite(function f() {}) // false,由于值为NaN isFinite(123) // true
_.isNaN = function(obj) { return _.isNumber(obj) && obj !== +obj; };
首先判断是否为数字,其次判断其自己是否与本身相等。
嗯,这是只针对数字的判断。
还有这样一个bug...???
_.isBoolean = function(obj) { return obj === true || obj === false || toString.call(obj) === '[object Boolean]'; };
其实我感受可能直接用toString.call(obj) === '[object Boolean]'
就能够...
_.isNull = function(obj) { return obj === null; }; _.isUndefined = function(obj) { return obj === void 0; };
这里就涉及到了为何用void 0
而不是undefined
,
在非严格模式下,咱们能够为全局标识符
undefined
赋值--《你不知道的js》
可是我没运行出来。并且严格模式下也没有报错...
function foo() { undefined = 2 } console.log(undefined) // undefined
能够声明一个名为undefined
的局部变量却是真的。
function foo() { var undefined = 2 console.log(undefined) // 2 } foo()
因此说明使用undefined
不少时候是不靠谱的。
那void 0
呢,表达式void
没有返回值,所以返回结果是undefined
,void
并不改变表达式的结果,只是让表达式不返回值。在这个层面上讲,void 0
,void a
都是同样的。
var obj = {a: 3} void obj // undefined
_.isEmpty = function(obj) { if (obj === null) return true; if (isArrayLike(obj) && (_.isArray(obj) || _.isString(obj) || _.isArguments(obj))) return obj.length === 0; return _.keys(obj).length === 0; };
判断是否为空的方法:
key
组成的数组的长度~_.has = function(obj, key) { return obj != null && hasOwnProperty.call(obj, key); };
首先要肯定传入的对象不能为空,而后用hasOwnProperty
来检查是否为对象的属性。