请问这句语句var args=[].slice.call(arguments,1)是什么意思?

请问这到底是什么意思啊,没有搞懂啊?

阅读 11.2k
4 个回答

首先你要具备如下知识:

  • []是什么?

  • [].slice.call是什么?

  • arguments是什么?

我们逐一来看:

[]是什么?

[]是js语法中创建一个新数组的意思,看如下代码:

var a = [];
var b = new Array();

这两种写法并无二致。

[].slice.call是什么?

首先你知道[]是一个数组,那么[].slice是它的一个方法,是一个函数。
它的作用是返回数组中的某一段,看如下代码:

var a = [1, 2, 3, 4, 5];
var b = a.slice(2);
// b是a从2号位开始的片段
// 也就是[3, 4, 5]

在js中,函数本身也是一种对象,也是具有属性和方法的,call就是其中之一。
它的第一个参数,是指定函数执行时的this指针,后面的参数,就是函数执行的参数。
具体的不展开讲,你可以查阅MDN: Function.prototype.call()
看如下代码:

var a = function (n) {
    console.log(this, n);
}
var b = {};

a(1); // log出Window对象, 1
a.call(b, 2); // log出b对象, 2

所以说[].slice.call(arguments, 1)实际上相当于(并不一定等同于):

arguments.slice(1);

arguments是什么

arguments可以看做一个数组。每一个js函数内部都有arguments,它代表传入的参数数组。
看如下代码:

function a() {
    console.log(arguments);
}

a(1, 2, 3); // log出[1, 2, 3]

现在你应该明白了,[].slice.call(arguments, 1)返回的是arguments数组从1号位开始的片段。
看如下代码:

function a() {
    var args = [].slice.call(arguments, 1);
    console.log(args);
}

a('haha', 1, 2, 3, 4, 5); // log出[1, 2, 3, 4, 5]

a('run', '-g', '-b'); // log出['-g', '-b']

就是这样,喵。

arguments不是一个真正的数组,虽然很像!

那如果我们想获取arguments里除了第一项以外的其他所有选项怎么办?

如果是数组的话,直接数组.slice(0, 1)搞定,所以你好想让arguments也能像数组那样使用slice方法对吧?于是

var args=[].slice.call(arguments,1);

就等于,把数组的slice方法,搬到arguments上,并调用,传入参数为1

关于call的应用,看这里

楼上两位说的都很好,我再来补充一点,为什么用Array.prototype.slice而不是用split,splice或者别的api?
这里贴一段slice的polyfill就一目了然了。

(function () {
  'use strict';
  var _slice = Array.prototype.slice;

  try {
    // Can't be used with DOM elements in IE < 9
    _slice.call(document.documentElement);
  } catch (e) { // Fails in IE < 9
    // This will work for genuine arrays, array-like objects, 
    // NamedNodeMap (attributes, entities, notations),
    // NodeList (e.g., getElementsByTagName), HTMLCollection (e.g., childNodes),
    // and will not fail on other DOM objects (as do DOM elements in IE < 9)
    Array.prototype.slice = function(begin, end) {
      // IE < 9 gets unhappy with an undefined end argument
      end = (typeof end !== 'undefined') ? end : this.length;

      // For native Array objects, we use the native slice function
      if (Object.prototype.toString.call(this) === '[object Array]'){
        return _slice.call(this, begin, end); 
      }

      // For array like object we handle it ourselves.
      var i, cloned = [],
        size, len = this.length;

      // Handle negative value for "begin"
      var start = begin || 0;
      start = (start >= 0) ? start : Math.max(0, len + start);

      // Handle negative value for "end"
      var upTo = (typeof end == 'number') ? Math.min(end, len) : len;
      if (end < 0) {
        upTo = len + end;
      }

      // Actual expected size of the slice
      size = upTo - start;

      if (size > 0) {
        cloned = new Array(size);
        if (this.charAt) {
          for (i = 0; i < size; i++) {
            cloned[i] = this.charAt(start + i);
          }
        } else {
          for (i = 0; i < size; i++) {
            cloned[i] = this[start + i];
          }
        }
      }

      return cloned;
    };
  }
}());
call(obj1,'111')方法就是参数第一个是this指向的对象,第二个是要传入的参数 var a = [].slice.call(arguments,1)
相当于arguments.slice(1) 为什么要这样做,因为arguments 不提供像sort 和slice 一样的数组方法 
例子: var obj1 = {name:'zs',sayHi:function(){ console.log('hi')}} 
obj1.sayhi() ;
输入的就是 hi  
现在又来一个对象 var obj2 = {name:'ls'}  obj2.sayhi() 
嗨个锤子,根本没有这个方法肿么办呢 程序员太聪明了  
于是用发明了call   obj1.sayHi.call(obj2) 于是 obj2就调用了sayhi  
这个题的意思就是arguments 调用了slice 是一样的。
以上都是伪代码
我刚看书看到这里也不懂,哈哈哈哈
推荐问题
宣传栏