美文网首页前端开发攻城狮
JavaScript 数组对象原型方法(二)

JavaScript 数组对象原型方法(二)

作者: 未来与传说 | 来源:发表于2017-12-06 20:54 被阅读0次

    Array.prototype.sort(compareFunction)

    • 默认排序顺序是根据字符串Unicode码点。
    • 在适当的位置对数组的元素进行排序
    • 返回排序后的数组。原数组已经被排序后的数组代替

    参数

    • [compareFunction] (可选)

    如果没有指明 compareFunction ,那么元素会按照转换为的字符串的诸个字符的Unicode位点进行排序。例如 "Banana" 会被排列到 "cherry" 之前。数字比大小时,9 出现在 80 之前,但这里比较时数字会先被转换为字符串,所以 "80" 比 "9" 要靠前。

    如果指明了 compareFunction ,那么数组会按照调用该函数的返回值排序。即 a 和 b 是两个将要被比较的元素:

    • 如果 compareFunction(a, b) 小于 0 ,那么 a 会被排列到 b 之前;
    • 如果 compareFunction(a, b) 等于 0 , a 和 b 的相对位置不变(受浏览器影响可能会变)
    • 如果 compareFunction(a, b) 大于 0 , b 会被排列到 a 之前。
    • compareFunction(a, b) 必须总是对相同的输入返回相同的比较结果,否则排序的结果将是不确定的。

    示例一

    var fruit = ['cherries', 'apples', 'bananas'];
    fruit.sort(); 
    // ['apples', 'bananas', 'cherries']
    
    var scores = [1, 10, 21, 2]; 
    scores.sort(); 
    // [1, 10, 2, 21]
    // 注意10在2之前,
    // 因为在 Unicode 指针顺序中"10"在"2"之前
    
    var things = ['word', 'Word', '1 Word', '2 Words'];
    things.sort(); 
    // ['1 Word', '2 Words', 'Word', 'word']
    // 在Unicode中, 数字在大写字母之前,
    // 大写字母在小写字母之前.
    

    示例二

    var numbers = [4, 2, 5, 1, 3];
    numbers.sort(function(a, b) {
      return a - b;
    });
    console.log(numbers);
    // [1, 2, 3, 4, 5]
    

    示例三

    var items = [
      { name: 'Edward', value: 21 },
      { name: 'Sharpe', value: 37 },
      { name: 'And', value: 45 },
      { name: 'The', value: -12 },
      { name: 'Magnetic' },
      { name: 'Zeros', value: 37 }
    ];
    items.sort(function (a, b) {
      if (a.value > b.value) {
        return 1;
      }
      if (a.value < b.value) {
        return -1;
      }
      // a 必须等于 b
      return 0;
    });
    

    由于 { name: 'Magnetic' },{ name: 'Zeros', value: 37 } 这两组数据无法完成数据比较因此顺序不会受到变化


    Array.prototype.includes(searchElement,fromIndex)

    • 判断一个数组是否包含一个指定的值
    • 返回值boolean类型

    携带参数

    • [searchElement](必须) 需要查看的元素值
    • [fromIndex](可选) 从该索引处开始查找 searchElement。如果为负值,则以array.length + fromIndex 的索引开始搜索。fromIndex默认为 0。

    示例一

    [1, 2, 3].includes(2);     // true
    [1, 2, 3].includes(4);     // false
    [1, 2, 3].includes(3, 3);  // false
    [1, 2, 3].includes(3, -1); // true
    [1, 2, NaN].includes(NaN); // true
    

    如果 传入fromIndex大于数组长度则返回false
    通用,允许查看类数组对象等,如示例二

    示例二

    (function() {
      console.log([].includes.call(arguments, 'a')); // true
      console.log([].includes.call(arguments, 'd')); // false
    })('a','b','c');
    

    es5原型扩展

    // https://tc39.github.io/ecma262/#sec-array.prototype.includes
    if (!Array.prototype.includes) {
      Object.defineProperty(Array.prototype, 'includes', {
        value: function(searchElement, fromIndex) {
    
          // 1. Let O be ? ToObject(this value).
          if (this == null) {
            throw new TypeError('"this" is null or not defined');
          }
    
          var o = Object(this);
    
          // 2. Let len be ? ToLength(? Get(O, "length")).
          var len = o.length >>> 0;
    
          // 3. If len is 0, return false.
          if (len === 0) {
            return false;
          }
    
          // 4. Let n be ? ToInteger(fromIndex).
          //    (If fromIndex is undefined, this step produces the value 0.)
          var n = fromIndex | 0;
    
          // 5. If n ≥ 0, then
          //  a. Let k be n.
          // 6. Else n < 0,
          //  a. Let k be len + n.
          //  b. If k < 0, let k be 0.
          var k = Math.max(n >= 0 ? n : len - Math.abs(n), 0);
    
          // 7. Repeat, while k < len
          while (k < len) {
            // a. Let elementK be the result of ? Get(O, ! ToString(k)).
            // b. If SameValueZero(searchElement, elementK) is true, return true.
            // c. Increase k by 1.
            // NOTE: === provides the correct "SameValueZero" comparison needed here.
            if (o[k] === searchElement) {
              return true;
            }
            k++;
          }
    
          // 8. Return false
          return false;
        }
      });
    }
    

    Array.prototype.map(callback,thisArg)

    • 一维数组的结构及值数据值不变,如果一维数据的值是对象类型,则callback改变其对象,原数组值对象类型会改变。如示例二
    • 创建一个新数组,其结果是该数组中的每个元素都调用一个提供的函数后返回的结果。
    • callback 函数只会在有值的索引上被调用;那些从来没被赋过值或者使用 delete 删除的索引则不会被调用

    示例一

    var a = [1,3,5,7,9];
    var c = a.map((item)=>{
      return item*2;
    })
    console.log(a);  // [1, 3, 5, 7, 9]
    console.log(c);  // [2, 6, 10, 14, 18]
    

    示例二

    var e = [{a:1},{b:2},3];
    var f = e.map( (item)=>{
      if(typeof(item)=="number"){
        return item*3;
      }else{
        item.a = "a";
      }
      return item;
    } )
    console.log(e);  // [{a:"a"},{b:2},3];
    console.log(f);   //  [{a:"a"},{b:2},9];
    

    参数

    • [callback(value,index,arr)] 回调函数

      • [value] 当前元素
      • [index] 当前元素索引
      • [arr] map方法被调用的数组
    • [thisArg] (可选) 执行 callback 函数时 使用的this 值。

    特殊示例

    // 下面的例子演示如何在一个String上使用 map 方法获取字符串中每个字符所对应的 ASCII 码组成的数组
    
    var a = Array.prototype.map.call("Hello World", function(x) { 
      return x.charCodeAt(0); 
    })
    // a的值为[72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100]
    
    var elems = document.querySelectorAll('select option:checked');
    var values = Array.prototype.map.call(elems, function(obj) {
      return obj.value;
    });
    
    

    经典案例

    // 下面的语句返回什么呢:
    ["1", "2", "3"].map(parseInt);
    // 你可能觉的会是[1, 2, 3]
    // 但实际的结果是 [1, NaN, NaN]
    
    // 通常使用parseInt时,只需要传递一个参数.
    // 但实际上,parseInt可以有两个参数.第二个参数是进制数.
    // 可以通过语句"alert(parseInt.length)===2"来验证.
    // map方法在调用callback函数时,会给它传递三个参数:当前正在遍历的元素, 
    // 元素索引, 原数组本身.
    // 第三个参数parseInt会忽视, 但第二个参数不会,也就是说,
    // parseInt把传过来的索引值当成进制数来使用.从而返回了NaN.
    
    function returnInt(element) {
      return parseInt(element, 10);
    }
    
    ['1', '2', '3'].map(returnInt); // [1, 2, 3]
    // 意料之中的结果
    
    // 也可以使用简单的箭头函数,结果同上
    ['1', '2', '3'].map( str => parseInt(str) );
    
    // 一个更简单的方式:
    ['1', '2', '3'].map(Number); // [1, 2, 3]
    // 与`parseInt` 不同,下面的结果会返回浮点数或指数:
    ['1.1', '2.2e2', '3e300'].map(Number); // [1.1, 220, 3e+300]
    

    兼容环境

    // 实现 ECMA-262, Edition 5, 15.4.4.19
    // 参考: http://es5.github.com/#x15.4.4.19
    if (!Array.prototype.map) {
      Array.prototype.map = function(callback, thisArg) {
    
        var T, A, k;
    
        if (this == null) {
          throw new TypeError(" this is null or not defined");
        }
    
        // 1. 将O赋值为调用map方法的数组.
        var O = Object(this);
    
        // 2.将len赋值为数组O的长度.
        var len = O.length >>> 0;
    
        // 3.如果callback不是函数,则抛出TypeError异常.
        if (Object.prototype.toString.call(callback) != "[object Function]") {
          throw new TypeError(callback + " is not a function");
        }
    
        // 4. 如果参数thisArg有值,则将T赋值为thisArg;否则T为undefined.
        if (thisArg) {
          T = thisArg;
        }
    
        // 5. 创建新数组A,长度为原数组O长度len
        A = new Array(len);
    
        // 6. 将k赋值为0
        k = 0;
    
        // 7. 当 k < len 时,执行循环.
        while(k < len) {
    
          var kValue, mappedValue;
    
          //遍历O,k为原数组索引
          if (k in O) {
    
            //kValue为索引k对应的值.
            kValue = O[ k ];
    
            // 执行callback,this指向T,参数有三个.分别是kValue:值,k:索引,O:原数组.
            mappedValue = callback.call(T, kValue, k, O);
    
            // 返回值添加到新数组A中.
            A[ k ] = mappedValue;
          }
          // k自增1
          k++;
        }
    
        // 8. 返回新数组A
        return A;
      };      
    }
    

    相关文章

      网友评论

        本文标题:JavaScript 数组对象原型方法(二)

        本文链接:https://www.haomeiwen.com/subject/fkwlixtx.html