导航

在深入看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 都有缺点,无法正确判断。

时间关系,先写这些