在深入看jquery源码中,大家会发现源码写的相当巧妙。那我今天也通过几个源码中用到的技巧来抛砖引玉,希望大家能共同研究源码之精华,不要囫囵吞枣。
1.将类数组转化成数组
我想大家首先想到的方法是for in循环,这是很对的,也是行之有效的。但是并非是效果最优的。因为需要循环,然后把循环出来的值push进新数组里,估计怎么也得10行代码吧。。。
那么jquery中是怎么用的呢? Array原型上的slice方法。
我们在控制台中打上Array.prototype.slice 那么会出来一个完整的slice方法。同样,如果打上Array.prototype.push ,也会出来一个完整的push方法。那么我们可以认定,数组的这些方法都是定义在Array 的prototype上的。
现在定义一个类数组。至于什么是类数组,我在这里就不赘述了,忘了的同学可以查查资料。
var obj={0:‘zhangsan‘,1:24,2:‘male‘,length:3};
ok,大家知道,类数组有lengh属性,与数组类似,但是两者的最大区别就是:类数组无法使用数组上的方法。那么怎么办呢?这时主角要出场了,热烈欢迎!!
Array.prototype.slice.call()
看一下完整的解决方法,然后再分析:
var obj={0:‘zhangsan‘,1:24,2:‘male‘,length:3}; var res = Array.prototype.slice.call(obj); console.log(res); //["zhangsan", 24, "male"]
就这么简单的一行,结果就出现了,是不是比循环的十几行要优化多了?
好了,现在详细方希Array.prototype.slice.call()
首先看call方法,大家可能都知道,call是会让调用它的方法里的this关键字指向发生变化
function tests(){ alert(this); } tests.call(‘test‘); // test
好,那么通过上面这个例子,我们可以知道Array.prototype.slice.call() 改变的是数组原型的slice方法中的this值。
纠结的事情来了,这个this在哪啊?明明没有看到this啊。 这就对应了一句话:所见并非即所得。
虽然我们在这句话中没有见到this,但是可以想象在js源码的slice方法中一定有this。
既然slice里的this关键字改成obj了,那么obj可以用slice方法了。
现在再解释一下slice方法,是从一个起始点到终点,如slice(0)就代表从第0项到最后。
那么完整解释一下这句话: Array.prototype.slice.call(obj) 就是把obj从第0项到最后一项的值存到一个新数组中,如何判断哪个是最后一项?length属性,看length等于3,那么最后一项就是索引为2的那一项。
现在再看obj
var obj={0:‘zhangsan‘,1:24,2:‘male‘,length:3};
很明显,第0项就是zhangsan,第1项是24,第2项是male,第2项是最后一项。
所以结果是:["zhangsan", 24, "male"]
希望我的分析能给大家一点点别样的灵感。下面的分析就不这么细了
2.将一个数组合并到另一个数组: Array.prototype.push.apply(arr1,arr2)
var arr1 = [1,2,3]; var arr2 = [4,5,6]; arr1.push(arr2) //[1,2,3,[4,5,6]]
这显然不是我们想要的,
var arr1 = [1,2,3]; var arr2 = [4,5,6]; Array.prototype.push.apply(arr1,arr2); console.log(arr1) //[1,2,3,4,5,6]
这样就能完美的解决。但这个方法不是万能的,当要插入的数组数值很大时就会出现错误。所以我们用时要注意。
3.判断变量的详细类型
Object.prototype.toString.call(obj)
用这个方法可以详细的判断出类型到底是object 还是array还是date 等,而原生的typeof instanceof 都有缺点,无法正确判断。
时间关系,先写这些