理解 Array.prototype.slice.apply

来源:互联网 发布:微信淘客软件 编辑:程序博客网 时间:2024/05/18 03:04

1. 首先,我们都理解在js中改变this引用有三种方法,call(), apply(), bind();

2. bind方法是改变函数内this引用,简单不再描述;

3. 至于 call() 和 apply() 两个方法,区别在于,前者是不定长的入参,后者是一个数组;下边重点说apply方法使用;

原理

    我们知道js中存在一种类数组对象,比如 {0:1,length:1}    或者 DOM 对象,或者 arguments 对象;

    数组只是一种特殊的对象,数组的特殊性体现在,它的键默认是按次序排列的整数(0,1,2...),所以数组不用为每个元素指定键名,而对象的每个成员都必须指定键名。

    所以 JavaScript中的数组也可以看成是这样的对象

   var array = [1, 2, 3];   var obj = {      0: 1,      1: 2,      2: 3,      length:3   }

注意了,这个length属性很重要,有了length就可以像数组一样遍历这个对象了。

再来实现一个简单的slice方法,

function slice(start, end) {    var array = [];    start = start ? start : 0;    end = end ? end : this.length;    for (var i = start, j = 0; i < end; i++, j++) {        array[j] = this[i];    }    return array;}
举例:Array.prototype.slice.apply({0:1,length:1});

    通过apply,将slice方法中的this指向该对象,遍历生成新的数组对象。


注意点:

1.  使用apply 时要注意:apply或call 只是切换了函数内部 this 的调用,但是执行的方法依然是原始对象上的方法, 即使你在 Array.prototype.slice.call(obj)的 obj 上 覆盖了slice 方法 ,依然会执行 Array 上的 slice 方法;

2.  由于apply方法(或者call方法)也可以绑定函数执行时所在的对象,但是会立即执行函数,因此不得不把绑定语句写在一个函数体内。建议使用函数改变this指向时使用 bind 方法。

3. 

bind方法每运行一次,就返回一个新函数,这会产生一些问题。比如,监听事件的时候,不能写成下面这样。

element.addEventListener('click', o.m.bind(o));

上面代码表示,click事件绑定bind方法生成的一个匿名函数。这样会导致无法取消绑定,所以,下面的代码是无效的。

element.removeEventListener('click', o.m.bind(o));

正确的方法是写成下面这样:

var listener = o.m.bind(o);element.addEventListener('click', listener);//  ...element.removeEventListener('click', listener);

0 0