jQuery中的isArrayLike函数

来源:互联网 发布:sql server 2014 2012 编辑:程序博客网 时间:2024/05/01 19:08

测试代码1:

var obj={name:"xx",sex:"female",length:"xx"}    alert("length" in obj && obj.length);//第一个是true,所以返回第二个值,第二个值就是xxalert("结果是=>"+"length" in obj && obj.length);//第一个是变成"结果是=>length in obj"显然直接是false(和+在一起,变成了字符串连接),所以&&操作符就直接返回falsealert("结果是:"+("length" in obj && obj.length));//把后面的结果先计算,打上括号就能够得到正确的结果! alert(isArraylike(obj));//返回false,因为length不是0,也不是number类型var obj={name:"xx",sex:"female",length:"2"}var obj1={name:"xx",sex:"female",length:0}alert(typeof("length" in obj && obj.length));//虽然在对象obj里面,length没有打上双引号,但是“length” in obj是正确的,同时obj.length是string类型alert(isArraylike(obj1));//因为obj1的length是0返回truealert(isArraylike(obj));//因为obj的length是string类型,直接返回false
测试代码2:

//测试jquery对象,length直接为numberalert("jquery对象"+isArraylike($("input")));alert("length" in $("input") && $("input").length)<div id="div1"><input type="text" id="input1"/><input type="text" class="input1"/><input type="text" class="input1"/></div>alert("结果是:"+document.getElementById("div1").nodeType);//返回1,元素为1,属性为2,文本是3,document是9,documentFragment是11
测试代码3:

var obj={name:"xx",length:0}     alert(isArraylike(obj))//返回true     var obj={name:"xx",length:-5}     alert(isArraylike(obj))//false
测试代码4:

 var obj={name:"qin",sex:"female",length:5}  alert(isArraylike(obj));//返回false,因为,虽然length是number类型,同时length>0,但是(length-1) in obj返回false,var obj={name:"qin",sex:"female",n:"xx",m:"xx",y:"xx",length:5}也就是一样的道理。var obj={0:"qin",1:"female",2:"xx",3:"xx",4:"xx",length:5}//返回结果就是true,因为(4-1) in obj是返回true的
测试代码5:

//如果是Element元素,也就是nodeType===1,而且含有length属性//alert("结果是1:"+document.getElementById("div1").length);是undefined,也就是没有length属性//document.getElementById("xx")返回的nodeType是1,但是没有length属性//document.getElementsByTagName("div")的集合有length属性,但是没有nodeType,返回的是htmlCollection集合

测试总结:三种情况下返回true。第一种:length恒等于0;第二种:本身就是Array类型;第三种:length>0,同时length是number类型,同时(length-1) in obj为true!

isArrayLike函数源码:‘

function isArraylike( obj ) {var length = "length" in obj && obj.length,type = jQuery.type( obj );//如果是函数,或者window那么直接返回falseif ( type === "function" || jQuery.isWindow( obj ) ) {return false;}if ( obj.nodeType === 1 && length ) {return true;}return type === "array" || length === 0 ||     //length是数字类型,同时length>0而且length-1要存在typeof length === "number" && length > 0 && ( length - 1 ) in obj;}

总结:如果是函数或者window对象,那么直接是false;如果是数组那么返回true;如果有length并且length是0返回true;如果length是number同时length>0同时length-1在obj里面那么返回true!什么时候nodeType是1,同时也具有length属性呢:

var div=$("#content")[0];div.length=1;//isArrayLike检测返回true

同时所有的jQuery对象都是类数组对象:

isArraylike($("#content"))//打印true

那么为什么要对上面length=0进行单独的判断呢,请看下面:

function Test(){alert(isArraylike(arguments));}Test();//这时候如果没有length===0那么就会返回false表示不是类数组,因此这里我们对这种情况单独判断!

以下是补充内容,有兴趣的可以阅读一下:

(1)这里之所以要判断(length-1) in obj是引入了稀疏数组的概念,稀疏数组在用forEach或者map迭代的时候会跳过空隙(这两个方法第一个参数是元素,第二个参数是下标,第三个是调用数组),也就是要确保数组的最后一个元素是存在的!如果要创建密集数组可以通过Array.apply(arr,Array(3))的方式,于是forEach和map就不会跳过其中的元素了!

(2)我们在上面那一篇讲稀疏数组的博客中看到了bind方法,bind方法的调用者是一个函数,传入的第一个参数是调用函数中this的指向,当然也可以传递额外的参数,这些额外的参数会作为原来绑定的那个函数的前几个参数,从而新函数传递的参数成为后面的参数。返回值是一个函数,这个函数除了参数和this指向不同以外和原来的函数是相同的,虽然是通过新函数调用的,但是arguments.callee仍然是原来的函数。
(3)通过把函数保存到本地,这种方式会改变函数中this的指向,进而导致产生错误,因为有时候内置的方法往往属于特定的对象,于是这时候要么用bind方法,要么用call或者apply方法修改this的指向从而执行特定对象的方法!

(4)我们下面给出一个js中map方法的案例:

var arr=[1,2,3];function f(elem,index,arr){//this就是map传入的第二个参数,一直就是12,不会变化!alert(this);return elem*2;}//打印[2,4,6]alert(arr.map(f,12));//输出第二个参数[0,1,2]alert([4,5,6].map(Function.prototype.call.bind(Number)));var a = ["aaa  ", "  bbb", "  ccc  "]//打印[AAA,BBB,CCC],这个call方法的this指定的是String.prototype.toUpperCasevar result=a.map(Function.prototype.call, String.prototype.toUpperCase); alert(result);//打印[aaa,bbb,ccc]表示已经去除了两端的空格了!必须要指定map第二个参数!var result=a.map(Function.prototype.call, String.prototype.trim); alert(result);//TypeError说a.map不是一个函数!,也就是这个Function.prototype.call没有指定this//而call方法的第一个参数必须是this!var result1=a.map(Function.prototype.call);

0 0
原创粉丝点击