javascript框架设计之种子模块(3)

这些还不是最难的,难点在于RegExp与Array.判定RegExp的情况很少。Array则不一样。有关isArray的实现不下二十种。都是因为鸭式辨型被打破了。直到prototype.js把Object.prototype.toString发掘出来。此方法是直接输出内部的[[Class]],绝对精准。有了它,95%的陷阱被跳过了。

function isArray(arr){ return arr instanceof Array; } function isArray(arr){ return !!arr && arr.constructor === Array; } function isArray(arr) { //prototype.js 1.6 return arr != null && typeof arr === "object" && 'splice' in arr && 'join' in arr; } function isArray(arr){// Douglas Crockford(JSON作者,反对原型污染) return typeof arr.sort == "function" } function isArray(array){ //kriszyp var result = false; try{ new array.constructor (Math.pow(2,32)) } catch (e){ result = /Array/.test(e.message) } return result; }; function isArray(o){//kangax try{ Array.prototype.toString.call(o); return true; } catch (e) { } return false; } function isArray(o){ //kangax if(o && typeof o == 'object' && typeof o.length == 'number' && isFinite(o.length)) { var _origLength = o.length; o[o.length] = '__test__'; var _newLength = o.length; o.length = _origLength; return _newLength == _origLength + 1; } return false }

至于null 、 undefined 、NaN直接这样写

function isNaN(obj) { return obj !== obj } function isNull(obj) { return obj === null; } function isUndefined(obj){ return obj === void 0; }

最后要判定的是对象是window,由于ECMA是不规范的Host对象,window对象属于host.所以也就没有被约定。就算Object.prototype.toString也对它没办法

[object Object] IE6 [object Object] IE7 [object Object] IE8 [object Window] IE9 [object Window] ff3.6 [object Window] opera10 [object DOMWindow] safari 4.04 [object global] chrome5.0

不过根据window.window和window.setInterval去判定更加不靠谱,用一个技巧就可以完美识别ie6 ie7 ie8的window对象,其它还用toString,这个神奇的hack就是,window与document互相比较,如果顺序不一样,结果也是不一样的!

剩下的就是一些经典方法:

在prototype.js中,拥有isElement,isArray,isHash,isFunctoion,isString,isNumber,isDate,isUndefined。

mootools有一个typeOf判定基本类型,instanceOf判定自定义“类”

RightJS 有isFunction , isHash , isString , isNumber , isArray ,isElement, isNode.

Ext有比较全面的判断,isEmpty,isArray,isDate,isObject,isSimpleObject,isPrimitive,isFunction,isNumber,isMumeric,isString,isBoolean,isElement,isTextNode,isDefined,isIterable,应有尽有。最后,还有typeOf判断基本类型。

Underscore.js有isElement,isEmpty,isArray,isArgument,isObject,isFunction,isString,isNumber,isFinite,isNaN,isBoolean,isDate,isRegExp,isNull,isUndefined.

jQuery就不与其它框架一样了,在jQuery1.4中只有isFunction,isArray,isPlainObject,isEmptyObject。isFunction,isArray用户肯定用的较多,isPlainObject是用来判断是否是纯净的js对象。既不是DOM,BOM对象,也不是自定义的“类”的实例对象,制造它的目的最初是为了深拷贝,避开像window那样自己引用自己的对象。isEmptyObject是用于数据缓存的系统,当此对象为空时,就可以删除它。

//jQuery2.0纯净数组的判定思路 jQuery.isPlainObject = function(obj){ //首先排除基础类型不为Object的类型,然后是DOM节点与window对象 if(jQuery.type(obj) !== "object" || object.nodeType || jQuery.isWindow(obj)){ return false; } //然后回溯它的最近的原型对象是否有isPrototypeOf. //旧版本的IE一些原生的对象没有暴露constructor、prototype。因此在这里过滤掉 try{ if (obj.constructor && !hasOwn.call(obj.constructor.prototype,"isPrototypeOf")){ return false; } } case(e) { return false; } return true; }

avalon.mobile中有一个更精简的版本,只支持最新的浏览器,可以大胆的使用ecma262v5新API

avalon.isPlainObject = function(obj){ return obj && typeof obj === "object" && Object.getPrototypeOf(obj) === Object.prototype }

isArrayLike也是一个常用的方法,但是判定一个类数组太难了,唯一的识别方法就是判断有一个大于0或等于0的length属性,此外,还有一些共识,如window与函数和元素节点,如(form元素),不算类数组,虽然它们都满足前面的条件。因此,至今jQuery都没有把它暴露出来。

//jQuery2.0 function isArrayLike(obj){ var length = obj.length , type = jQuery.type(obj); if (jQuery.isWindow(obj)){ return false; } if (obj.nodeType === 1 && length){ return true } return type === "array" || type !== "function" && (length === 0 || typeof length === "number" && length > 0 && (length -1) in obj); } // avalonjs function isArrayLike (obj) { if (obj && typeof obj === "object"){ var n = obj.length if (+n === n && !( n % 1) && n >= 0){//检测length是否为非负整数 try{ if ({}.prototypeIsEnumerable.call(obj,'length') === false){ return Array.isArray(obj) || /^\s?function/.test(obj.item || obj.callee) } return true; } catch (e) { //IE的NodeList直接报错 return true; } } } return false }

在Prototype.js1.3版本中的研究成果(Object.prototype.toString.call)就应用于jQuery,在jQuery1.2中,判断一个变量是否为函数非常复杂。

复制代码 代码如下:

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wgdfdp.html