zoukankan      html  css  js  c++  java
  • JavaScript数组操作

    0 写在前面

      数组在任何语言中,都是一种十分重要的数据类型。因此,在JavaScript中,熟练掌握数组以及字符串的操作,是十分必要的。

      为此,我在这里列举并练习了一些有关于数组与类数组的基本操作。

    1 数组的常用操作

    1-1 数组常用操作的大致分类

    • 在原数组上进行修改(不占用额外空间)的方法
      • push,pop,unshift,shift,reverse,sort,splice
    • 不在原数组上进行修改(占用额外空间)的方法
      • slice,concat,join,split,toString

    1-2 修改原数组的方法

    1-2-1 push

    【用法】

      arr.push(ele)

    【说明】

      在arr尾部添加新元素ele(可以为数据列表)

    【原型链编程】

      push的用法十分简单,我们可以根据其特点重写其方法进行练习。这里练习原型链编程,即在Array类的原型上修改push方法。

      代码如下

     1     // declare an Array
     2     var arr = [1,2,3,4,5];
     3     var arr1 = new Array(1,2,3,4,5);
     4     // override push
     5     Array.prototype.myPush = function(){
     6         for(var i = 0 ; i < arguments.length ; i ++){
     7             this[this.length] = arguments[i];
     8         }
     9         return this.length;
    10     }

    1-2-2 pop

    【用法】

      arr.pop()

    【说明】

      在arr尾部弹出并删除末尾元素

    1-2-3 unshift

    【用法】

      arr.unshift(ele)

    【说明】

      在arr头部插入元素ele(可以为数据列表)

    1-2-4 shift

    【用法】

      arr.shift()

    【说明】

      在arr头部弹出并删除首个元素

    1-2-5 splice

    【用法】

      arr.splice(i,n[,args])

    【说明】

      在arr的第i位开始,删除n个元素。后面的[,args]为用逗号分隔的可选参数列表,表示向“切口”出添加的数据。

    【拓展】

      可以使用splice代替insert的功能,只需将n=0即可,表示向第i位插入[,args]这么多数据。

    【代码示例】

      原型链编程:实现unshift方法的重写。思路:每次向数组首插入数据。

     1     <script>
     2     // override unshift
     3     Array.prototype.myUnshift = function(){
     4         var n = arguments.length;
     5         for(var i = 0 ; i < n ; i ++){
     6             this.splice(i,0,arguments[i]);
     7         }
     8         return this.length;
     9     }
    10     </script>

    【补充】

      若第一位索引位i的值为负数,系统则会按照以下方式进行处理

    1 function splice(pos){
    2     pos  += (pos >= 0) ? 0 : this.length;
    3 } 

      即对于负数的索引为:从数组向前进行查找。

    1-2-6 sort(重要)

    【使用】

      arr.sort([function(a,b){}])

    【说明】

      sort内的参数为可选项,类比于C++中的cmp函数进行理解,内部参数为一个函数形式:若返回负值则将a放置在b前面,整值则将b放在a前面。

      由此可知,JavaScript中的sort方法也是基于比较的(对数组中的元素两两分别进行比较)(经过验证发现JavaScript中的sort是稳定的)

    【默认】

      在sort不传递参数的情况下,默认进行的排序是将arr的内容视为字符串按照其字典序进行升序排列。

    【拓展】

      根据其传入的参数方法,可以实现任意我们想实现的排序方式。

      以下来看多组示例代码。

    【代码示例】

      【例1】按照数值顺序升序排列。

    1     <script>
    2         // asc sort by value
    3         var arr = [3,2,1,10,29,392,12,3,-3,-3029,-1,0];
    4         arr.sort(function(a,b){
    5             return a - b;
    6         })
    7     </script>

      降序只需修改返回值为return b - a即可

      【例2】按照对象中某一属性排序,如按照rank升序

     1     <script>
     2         var chen = {
     3             name : "ChenXianxian",
     4             age : 20,
     5             gender : 'male',
     6             rank : 1
     7         }        
     8         var meng = {
     9             name : "MengZY",
    10             age : 20,
    11             gender : 'male',
    12             rank : 32
    13         }
    14         var fei = {
    15             name : "FeiY",
    16             age : 20,
    17             gender : 'male',
    18             rank : 23
    19         }
    20         var liu = {
    21             name : "LiuCJ",
    22             age : 20,
    23             gender : 'undefined',
    24             rank : 12
    25         }
    26         var arr3 = [chen,liu,meng,fei];
    27         arr3.sort(function(a,b){
    28             return a.rank - b.rank;
    29         })
    30     </script>

      执行结果如下

       

      【例3】将有序数组随机打乱顺序

      思路:将排序的交换变成随机正负数返回即可。

    1     <script>
    2         var arr4 = [1,2,3,4,5,6,7,8,9];
    3         arr4.sort(function(a,b){
    4             return Math.random() - 0.5;
    5         })
    6     </script>

      【例4】按照字节数排序

      扩展知识:ASCII码小于255的占用1个字节,超过255的则占用2字节。

      在sort中对a和b的比较也可以定义函数进行比较,这里练习字符串字节数的计算函数

     1     <script>
     2         // asc sort by bytes
     3         var arr5 = ['abdofajefid','a','ab','哈哈哈c','哈哈','a哈a哈a'];
     4 
     5         function getBytes(str){
     6             var res = str.length;
     7             var n = str.length;
     8             for(var i = 0 ; i < n ; i ++){
     9                 if(str.charCodeAt(i) > 255){
    10                     res ++;
    11                 }
    12             }
    13             return res;
    14         }
    15 
    16         arr5.sort(function(a,b){
    17             return getBytes(a) - getBytes(b);
    18         })
    19     </script>

    1-3 不修改原数组的方法

    1-3-1 concat

    【用法】

      arr1.concat(arr2)

    【说明】

      返回结果是一个新的字符串arr1与arr2拼接,但是不对arr1和arr2进行修改。

     1-3-2 toString

    【用法】

      arr.toString()

    【说明】

      将数组arr的内容转化成一个字符串。

    1-3-3 slice

    【用法】

      arr.slice(i,j)

      arr.slice(i)

      arr.slice()

    【说明】

      arr.slice(i,j) 表示从arr中截取第[i,j)位

      arr.slice(i) 若i为正,表示从arr第i位开始截取(i从0开始计数);若i为负,表示从arr倒数第i位开始截取(i从1开始计数)

      arr.slice() 表示截取完整的arr

    【注意】

      arr.slice()由于不会修改原数组,因此其返回值必须有一个变量接收,否则操作就失去了意义。

    1-3-4 join/split

    【用法】

      arr.join(regex)

      arr.split(regex)

    【说明】

      将arr按照regex的内容进行拼接或拆分,拼接是在原数组的基础上补上一个regex中的内容,拆分则是将字符串中的该字符删掉。

    【举例】

    1 <script>
    2     var arr = [1,2,3,4,5,6];
    3     arr.join("-"); // "1-2-3-4-5-6"
    4     arr.join("");  // "123456"
    5     var str = "1,2,3,4,5,6";
    6     arr.split(","); // ["1","2","3","4","5","6"]
    7 </script>

    【注意】

      若要进行大量字符串的拼接操作,请使用 arr.join(""); 的方式进行操作。

      这是由于循环使用运算符'+'进行拼接会降低程序执行效率。

    2 类数组

    2-1 类数组概述

      类数组在形式上表现为数组的特征,但是本质是一个对象,使用对象中的属性模拟数组特性。

      如:函数参数传递列表arguments就是一个类数组,形式上表现为一个数组,但不具有数组所通常具有的方法(在第1部分提到的方法)

    2-2 类数组的基本形式

      类数组的基本形式如下

     1     <script>
     2         // ArrayLike
     3         var obj = {
     4             "0" : 1,
     5             "1" : 2,
     6             "2" : 3,
     7             "length" : 3,
     8             "push" : Array.prototype.push;
     9         }
    10     </script>

      其中的几个关键要素:按照相似于数组的索引方法,将key值设置为数组下标的形式;必须有length属性来记录数组长度。

      由此便可实现,按照下标索引类数组中的数据(如obj[0]或obj['0']取出的都是数值1),使用push方法向类数组中添加元素。

      此外还可根据需要自行添加类数组的行为:如添加Array.prototype.splice方法等等(注意原型上的属性值不要加())。

    2-3 类数组使用的注意事项

      在2-2接种提到,类数组中的一个必要属性是length

      在这里我们回顾在1-2-1小节中编写的push方法,该方法在原型上的实现为在arr的length位添加push进的数值。因此可知length为下一次添加进类数组的数据位置提供了必要的索引方式。

      我们来看一个例子

     1     <script>
     2         // example
     3         var obj1 = {
     4             "2" : 'a',
     5             "3" : 'b',
     6             "length" : 2,
     7             "push" : Array.prototype.push
     8         }
     9         obj1.push('c');
    10         obj1.push('d');
    11     </script>

      执行结果中,obj1 = {"2" : 'c' , "3" : 'd' , "length" : 4 , "push" : Array.prototype.push},由此可知此处的push修改的是obj1中的length位置索引到的数据值,并length++。

    2-4 类数组向数组的转换

      由于类数组不含有数组的常用方法,因此将类数组转换为数组会大大简化操作。

      类数组转换成数组的方法如下:

    var arr = Array.prototype.slice.call(arrayLike);

      注意必须使用call来改变this指向arrayLike这个类数组,结果用变量arr进行接收。

    3 数组操作的两个练习

    3-1 封装type区分引用值类型

      主要实现思路为,先利用typeof本身提供的功能区分原始值与引用值,但是引用值(null,object和array)是区分不开的。因此需要调用Object.prototype.toString.call(target)来判断target的类型。

      需要注意的一点是以下两种声明方式使得变量的类型不一样:

      var a = 1;

      var a = Number(1);

      同样表示整数1,但是前者是整数Number,后者是一个包装类的实现是一个object,我们希望我们的程序能够对以上两种不同情况进行区分。

      可以将封装好的type方法放进工具类库如:tool.js里面,以便随时需要用到时调用之。

      代码实现如下:

     1     <script>
     2         // abstract function type
     3         var template = {
     4             "[object Array]" : 'array',
     5             "[object Object]" : 'object',
     6             "[object Number]" : 'object_number',
     7             "[object Boolean]" : 'object_boolean',
     8             "[object String]" : 'object_string'
     9         }
    10         function type(target){
    11             if(typeof(target) == "null"){
    12                 return "null";
    13             }
    14             else if(typeof(target) == "object"){
    15                 var str = Object.prototype.toString.call(target);
    16                 return template[str];
    17             }
    18             else{
    19                 return typeof(target);
    20             }
    21         }
    22     </script>

      检查结果

      经验证发现,实验结果符合预期。

    3-2 数组去重

      需求十分简单,给定一个数组,编写一个删除重复元素的算法。

      实现思路也十分简单,由于对象object本身就是一个键值对key-value的组合,所以自带map的特性。删除重复元素完全可以当作一个hashmap的问题来进行处理。

      实现代码如下

     1     <script>
     2         // delete repeat number in array
     3         var arr = [1,1,1,1,1,1,1,2,2,2,1,3,1,1,2,1,2,3,1,2,2,2,1];
     4         function rmRepeat(arr){
     5             var obj = {},
     6                 res = [],
     7                 n   = arr.length;
     8             for(var i = 0 ; i < n ; i ++){
     9                 if(!obj[arr[i]]){
    10                     res.push(arr[i]);
    11                     obj[arr[i]] = 'xxx';
    12                 }
    13             }
    14             return res;
    15         }
    16     </script>

      同样,也可以把数组去重作为一个数组操作方法放到Array的原型链上

     1     <script>
     2             // delete repeat number in array - proto method
     3             Array.prototype.unique = function(){
     4                 var n = this.length,
     5                     obj = {},
     6                     res = [];
     7                 for(var i = 0 ; i < n ; i ++){
     8                     if(!obj[this[i]]){
     9                         obj[this[i]] = 'xxx';
    10                         res.push(this[i]);
    11                     }
    12                 }
    13                 return res;
    14             }
    15         </script>

    【注意】

      在实现上需要注意一点:方法二的第9行,对obj对象(map)的value值的赋值,必须不能为一个可能为false的值

      可能为false的值有以下6种:

    • 0

    • “”

    • false

    • null

    • undefined

    • NaN

       因此再此我的处理方法是手动赋值为一个字符串,保证其不可能为空。

     4 总结

      数组是一种重要的数据类型,必须熟练数组的常用操作、类数组的意义以及掌握在原型链上编程的方法。

  • 相关阅读:
    用localeCompare实现中文排序
    点击一个链接同时打开两个页面
    汉字和Unicode编码互转
    javascript中document学习
    javascript页面表格排序
    JavaScript 仿LightBox内容显示效果
    JavaScript面向对象的简单介绍
    JavaScript键盘上下键的操作(选择)
    关于clientWidth、offsetWidth、clientHeight、offsetHeigh
    动态(按需)加载js和css文件
  • 原文地址:https://www.cnblogs.com/chrischen98/p/10783987.html
Copyright © 2011-2022 走看看