zoukankan      html  css  js  c++  java
  • [].slice.call的理解

    首先要说明[].slice.call()Array.prototype.slice.call() 有什么区别?

    [].slice === Array.prototype.slice
    true
    

    []为创建数组,当[].slice的时候,自然会去找原型链

    [].__proto__.slice === Array.prototype.slice
    true
    

    Array.prototype.slice是定义的方法,可以被重写

    [].silce是使用定义的方法

    1. 自身的属性不同(因为原型与[]的区别)
    Object.getOwnPropertyNames(Array.prototype)
    (37) ["length", "constructor", "concat", "pop", "push", "shift", "unshift", "slice", "splice", "includes", "indexOf", "keys", "entries", "forEach", "filter", "map", "every", "some", "reduce", "reduceRight", "toString", "toLocaleString", "join", "reverse", "sort", "lastIndexOf", "copyWithin", "find", "findIndex", "fill", "remove", "removeFirstIf", "removeIf", "repeat", "last", "lastDef", "clone"]
    
    Object.getOwnPropertyNames([])
    ["length"]
    

    所以在本质上[]和Array.prototype没有本质区别,但是调用上是有区别的,但是根据专业检测,[]要更快一点

    在MDN上 slice的解释是

    slice()方法返回一个从开始到结束(不包括结束)选择的数组的一部分进行浅拷贝到一个新的数组对象,并且原对象不会被修改

    var animals = ['ant', 'bison', 'camel', 'duck', 'elephant'];
    
    console.log(animals.slice(2));
    // expected output: Array ["camel", "duck", "elephant"]
    
    console.log(animals.slice(2, 4));
    // expected output: Array ["camel", "duck"]
    
    console.log(animals.slice(1, 5));
    // expected output: Array ["bison", "camel", "duck", "elephant"]
    

    参数有两个slice(begin,end)

    begin :

    • 如果没有参数那就从0开始
    • 有就从索引处来时(第一位为0)
    • 如果该参数为负数,则表示从原数组中的倒数第几个元素开始提取,slice(-2)表示提取原数组中的倒数第二个元素到最后一个元素 (包含最后一个元素)

    end :

    • 如果没有参数,默认取到数组末尾
    • 如果大于数组长度,取到数组末尾
    • slice(1,4) 提取原数组中的第二个元素开始直到第四个元素的所有元素 (索引为 1, 2, 3的元素)
    • 如果该参数为负数, 则它表示在原数组中的倒数第几个元素结束抽取
    var a = [1,2,3,4,5,6,7,8];
    a.slice(3,-2)
    (3) [4, 5, 6]
    

    返回值

    一个含有提取元素的新数组

    slice 不修改原数组,只会返回一个浅复制了原数组中的元素的一个新数组。

    • 如果该元素是个对象引用 (不是实际的对象),slice 会拷贝这个对象引用到新的数组里。两个对象引用都引用了同一个对象。如果被引用的对象发生改变,则新的和原来的数组中的这个元素也会发生改变。

    • 对于字符串、数字及布尔值来说(不是 StringNumber 或者 Boolean 对象),slice 会拷贝这些值到新的数组里。在别的数组里修改这些字符串或数字或是布尔值,将不会影响另一个数组。

    如果向两个数组任一中添加了新元素,则另一个不会受到影响。

    以上大致是MDN上面对slice的专业解释

    slice 这个方法在不接受任何参数的时候会返回 this 本身

    arguments 是属于函数内部的变量,其值是函数参数列表,一个类数组对象,是具有长度属性的,却并不是数组,不具备slice()这个方法,那就意味着 arguments.slice() 行不通

    这里可以改变this的call出现了,假如我用call将arguments把this给slice会发生什么?

    slice会得到具有长度属性的对象,就实现了对象转数组的

    function list() {
      return Array.prototype.slice.call(arguments);
    }
    console.log(list(1, 2, 3));
    

    一定有人会问,为什么将arguments的call给slice就可以变成数组?内部到底发生了什么

    我们可以实现一个自己的slice(),就明白了

    Myslice()

    Array.prototype.Myslice = function (begin,end){
    
      var start = begin || 0;   //判断begin时候存在 不存在给0 这里判断可以加强
      var len = this;    //获取this.length  这里得到了call进来的对象
      
      start = (start >= 0) ? start : Math.max(0, len + start); //判断参数是不是是不是大于1,负数情况下的begin取值
      end = (typeof end == 'number') ? Math.min(end, len) : len;  //判断end是不是大于this.length的长度
      if(end<0){
        end = end + len  //判断负值的情况
      }
      var result = new Array();
      
      for (let i = 0; i < end.length; i++) {
        result.push(this[i])
      }
      return result;
    }
    function list() {
      return Array.prototype.Myslice.call(arguments);
    }
    console.log(list(1, 2, 3));
    

    相信看到这里就明白为什么Array.prototype.slice.call 是如何将对象变成数组的~~~

    最后贴上JavaScript sclie的源码

    Array.prototype.slice = function(begin, end) {
      end = typeof end !== 'undefined' ? end : this.length
    
      if (Object.prototype.toString.call(this) === '[object Array]') {
        return _slice.call(this, begin, end)
      }
    
      var i,
        cloned = [],
        size,
        len = this.length
    
      var start = begin || 0
      start = start >= 0 ? start : Math.max(0, len + start)
    
      var upTo = typeof end == 'number' ? Math.min(end, len) : len
      if (end < 0) {
        upTo = len + end
      }
    
      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
    }
    
    function list() {
      return Array.prototype.slice.call(arguments)
    }
    console.log(list(1, 2, 3))
    

    文章为个人总结,若有错误,请指出

  • 相关阅读:
    HDU2149-Public Sale
    分页和多条件查询功能
    hdu 4691 最长的共同前缀 后缀数组 +lcp+rmq
    BZOJ 2588 Count on a tree (COT) 是持久的段树
    windows 设置脚本IP
    hdu 4912 Paths on the tree(树链拆分+贪婪)
    分散式-ubuntu12.04安装hadoop1.2.1
    struts详细解释拦截器
    Codeforces 459E Pashmak and Graph(dp+贪婪)
    C#中的数据格式转换 (未完待更新)
  • 原文地址:https://www.cnblogs.com/wuvkcyan/p/9446800.html
Copyright © 2011-2022 走看看