zoukankan      html  css  js  c++  java
  • JavaScript数组方法--slice、sort、splice

    数组常用方法应该只剩下最后这哥仨了,他们都是最早的ECMA-262标准的方法,结果写着写着,居然把他们写到最后了。

    • slice:slice() 方法返回一个新的数组对象,这一对象是一个由 begin和 end(不包括end)决定的原数组的浅拷贝。原始数组不会被改变。

    先看定义,其实该方法就是对原数组实现浅拷贝。从定义上也可以看出来,他需要两个参数,决定拷贝原数组当中从begin到end的元素。

    简单的看一下使用方法(一定要注意:浅拷贝):

    var animals = ['ant', 'bison', 'camel', 'duck', 'elephant'];
    console.log(animals.slice(2));
    console.log(animals.slice(2, 4));
    console.log(animals.slice(1, 5));

    输出结果呢?

    对照一下定义:
      animals.slice(2)输出的是元素当中2、3、4位置的元素,就是说不存在end参数的话,拷贝到最后一个元素;

      animals.slice(2,4)输出的是元素当中2、3位置的元素,不包括end位置;

      animals.slice(1,5)输出的是元素当中1、2、3、4位置的元素,依然不包括end位置。

    语法:

    arr.slice([begin, [end]]);

      也就是说begin和end两个参数都是可选的,如果值为负数,则相当于倒数。

      既然如此,重构一下吧!

    function slice(arr, begin, end) {
      if (!(arr instanceof Array)) throw new Error("请确保第一个参数类型为数组")
      var results = []
      begin = begin || 0
      end = end || arr.length
      if (begin < 0) begin += arr.length      // 如果begin < 0, begin = 数组长度+begin 
      if (begin < 0) begin = 0                // 如果还小于0, 则直接修正为0
      if (end < 0) end += arr.length          // 如果end < 0, end = 数组长度+end 
      if (end > arr.length) end = arr.length  // 如果end > 数组长度, end = 数组长度
      for (var i = begin; i < end; i++) {
        results[results.length] = arr[i]
      }
      return results
    }

    其实,任何方法,如果真的理解该方法了,重构也真没什么困难的!

    • sort:sort() 方法用原地算法对数组的元素进行排序,并返回数组。排序算法现在是稳定的。默认排序顺序是根据字符串Unicode码点。

    关于算法,这个可真没什么发言权,完全不懂,只能做一个简单的冒泡排序。

    先看一下sort的用法吧!

    var months = ['March', 'Jan', 'Feb', 'Dec'];
    months.sort();
    console.log(months);
    var array1 = [1, 30, 4, 21, 100000];
    array1.sort();
    console.log(array1);
    

      结果:

    第一个好理解,数组array1的排序结果是不是错了?事实上并没有,因为sort默认顺序是字符串Unicode码点,即使你所有元素是数字,如果不指定排序方法,他也是按照字符串Unicode码点来排序的。这就引出了sort的参数compareFunction

    arr.sort([compareFunction])
    

      

    也就是说compareFunction也需要两个参数,firstEl和secondEl,依赖比较函数的返回结果决定是升序还是降序排列。如果compareFunction(firstEl,secondEl)< 0的话升序,反之降序。

    直接重构吧!

    function sort (arr, fn) {
        if (!(arr instanceof Array)) throw new Error("请传入数组类型的参数")
        if (!fn) {
          // 定义默认
          fn = function (a, b) { return a - b }
        }
        // 判断是否全都为数字
        let isAllNumber = true
        for (let i = 0; i < arr.length; i++) {
          isAllNumber = typeof arr[i] === "number"
          if (!isAllNumber) break
        }
        if (!isAllNumber) {
          // 如果有非数字元素,按Unicode码点升序
          fn = function (a, b) {
            return "" + a > "" + b
          }
        }
        // 冒泡排序
        for (let i = 0; i < arr.length - 1; i++) {
          for (let j = 0; j < arr.length - 1 - i; j++) {
            let bool = isAllNumber ? (fn(arr[j], arr[j + 1]) > 0) : fn(arr[j], arr[j + 1])
            if (bool) {
              let temp = arr[j + 1]
              arr[j + 1] = arr[j]
              arr[j] = temp
            }
          }
        }
        return arr
      }

    不多说。

    • splice:splice() 方法通过删除或替换现有元素来修改数组,并以数组形式返回被修改的内容。此方法会改变原数组。

    数组常用方法当中最后一个,也是非常非常重要的一个方法。

    该方法可以添加、删除、替换数组当中的元素,判断的方法,就是传递的参数。

    var months = ['Jan', 'March', 'April', 'June'];
    months.splice(1, 0, 'Feb');
    console.log(months);
    months.splice(4, 1, 'May');
    console.log(months);
    var fruits = ['apple', 'orange', 'pear']
    fruits.splice(2,1)
    console.log(fruits)

    结果:

    看出什么了?

    months.splice(1, 0, 'Feb'): 是在months数组的索引为1的位置插入了元素'Feb'

    months.splice(4, 1, 'May'):是将months数组的索引为4的位置的元素替换成了'May'

    fruits.splice(2,1):是将fruits数组的索引为2的元素删除

    array.splice(start[, deleteCount[, item1[, item2[, ...]]]])
    

     参数start,决定了我们的操作从数组当中哪个位置开始。

       参数deleteCount,决定了将要从start开始删除几个元素,如果是0,表示不删除元素。

     参数item1……,决定了删除deleteCount个元素后在插入什么元素。

      也就是说从start位置删除deleteCount个元素,再插入item1...等元素,这完全依赖于后续的参数。返回由从start开始到 end = start+deleteCount, 不包含end位置的元素所组成的新的数组。

    function splice (arr, start, deleteCount) {
        if (!(arr instanceof Array)) throw new Error("请确保第一个参数类型为数组")
        start = start || 0
        var rest = []
        for (var j = 3; j < arguments.length; j++) {
          rest[rest.length] = arguments[j]
        }
        var results = []
        // 修正起始位置   小于0的话,就加上数组长度,如果还小于0,修正为0   大于数组长度的话 就修正为数组长度
        start = start < 0 ?
          (start + arr.length < 0 ? 0 : start + arr.length) :
          (start > arr.length ? arr.length : start)
        // 如果deleteCount数值过大,则修正为从起始位置到数组结尾的长度
        if (deleteCount > (arr.length - start)) { deleteCount = arr.length - start }
        // 获取删除的元素,并组成新的数组实例
        for (var i = start; i < (start + deleteCount); i++) {
          results[results.length] = arr[i]
        }
        // 元素删除之后,将所有数组元素响应的前置
        for (var i = start + deleteCount; i < arr.length; i++) {
          arr[i - deleteCount] = arr[i]
        }
        // 修正数组长度
        arr.length = arr.length - deleteCount
        // 将添加的元素填充到对应位置
        for (var i = rest.length - 1; i >= 0; i--) {
          for (var j = arr.length; j > start; j--) {
            arr[j] = arr[j - 1]
          }
          arr[start] = rest[i]
        }
        return results
      }

    有点复杂吧!其实只要理解了splice方法,下面也就是重构的代码实现了,为什么会这么复杂,主要是splice方法可以做的工作有点多了,导致重构的代码量变大。

  • 相关阅读:
    爬取淘宝商品信息
    eclipse 搭建Robotium环境--apk 环境搭建
    android studio2.0 搭建Robotium环境--有被测源代码的情况下
    mysql 特殊语句
    电脑浏览器访问文件夹
    mindmanager 15 停止工作
    yum被lock Existing lock /var/run/yum.pid: another copy is running as pid 1580. Another app is currently holding the yum lock; waiting for it to exi
    jenkins安装及部署
    ant+jmeter
    charles抓包及篡改
  • 原文地址:https://www.cnblogs.com/zhuhuoxingguang/p/10696689.html
Copyright © 2011-2022 走看看