javascript 数组声明-第十九节 数组字段 - 用于Web后端开发的Javascript - 零程序员

2023-09-02 0 7,911 百度已收录

本内容为《Web前端开发Javascript视频》讲义,请配合大佬的视频课程《Javascript》。

数组是值的有序集合; 每个值称为一个元素,每个元素在链表中都有一个位置,用数字表示,称为索引或下标;

尽管 ECMAScript 字段像其他语言中的字段一样是有序列表,但与其他语言不同的是:

JavaScript 字段是无类型的,数组元素可以是任何类型; 即使在同一领域,不同的元素也可以有不同的类型;

JS字段的索引是一个从零开始的32位整数,第一个元素的索引为0;

ES字段是动态的,即其大小可以动态调整,并且可以随着数据的添加和删除而手动减小或减小;

创建一个链表:

有两种方法:

第一个:使用构造函数Array()创建:

语法:var arr = new Array();

var arr = new Array(长度); // 长度是一个整数

var arr = new Array(元素, 元素,…元素);

var arr = new Array();  // 空数组
arr = new Array(3);  // 指定长度
arr = new Array("wangwei","wujing","jingguo");  // 显式指定元素

如果您事先知道要存储在字段中的项目数,则可以将该数字传递给构造函数。 这个数字实际上就是字段的长度属性(实际上是预先分配了一个字段空间,但是字段中没有存储任何值,甚至字段的索引也是未定义的);

直接传递item,即参数为链表的元素;

如果需要创建一个只有一个值的字段,且该值为数字,则只能使用字符串作为数字; 如果值为非整数,则会抛出异常;

var arr = new Array(3);  // 有3个空元素
arr = new Array("3");    // 有1个元素,值为“3”
var arr = new Array(18.5);  // RangeError: Invalid array length

也可以省略new运算符,它实际上执行数据类型转换,例如:

var colors=Array(3);
var names=Array("Wang");

第二种方法:使用链表文字(直接数量)创建:

 var empty = [];  // 空数组
var num = [2,3,5,7,11];
var names = ["wangwei","wujing","jianguo"];

这是最简单的创建链表的方法,即用方括号[]来分隔数组元素,并用冒号分隔;

当为[ ]空链表时,相当于new Array();

数组字面量中的值不一定是常量,也可以是任意表达式,例如:

var year = 2020;
var years = [year,year+1,year+2,year+3];

还可以包含对象或其他字段,例如:

var objArr = [{name:"wangwei",age:18},[1,2],[3,{x:4,y:5}]];

如果省略字段中的值,则省略的元素的值是未定义的:

var count = [1,,3];  // 数组3个元素,第2个的值是undefined

允许使用可选的尾随逗号,但省略最后一个元素:

count = [1,2,];  // 2
count = [,,,];   // 3

不推荐,有些浏览器会解析成3个字段,因为它们对链表的实现不一致;

javascript 数组声明-第十九节 数组字段 - 用于Web后端开发的Javascript - 零程序员

总结:在实际场景中,使用链表字面量比构造函数更简单、更灵活。

数组的内存分配:

数组使用显存中一系列连续的区域来存储一些值; 在 JavaScript 中,数组是哈希映射,在显存中不连续。 它可以通过多种数据结构来实现,数组就是其中之一。 因此,如果使用大字段需要很长时间;

ES6 中引入了类型化字段,JavaScript 引擎已经为相同数据类型的字段分配了连续的存储空间,例如 ArrayBuffer 就使用了连续的显存空间。

数组元素的读写:

要读取或设置数组元素的值,请使用“[ ]”运算符并提供相应的从 0 开始的数字索引下标;

var citys = new Array("蚌埠","宿州","南京");
var c1 = citys[0];  // 读取第一个元素
citys[0] = "怀远";  // 写第一个元素

读取和设置元素值的句型是一样的;

当越界访问不存在的数据元素时,会返回undefined;

如果某个值的索引超过了链表中现有的项数,则会手动将数组缩小到索引值的宽度加1;

var colors=["red","blue"];
colors[2]="green";   // 明确添加了一个新元素
var i = 3;
colors[i] = "purple";
colors[i+1] = "yellow";

数组的最大索引为4294967294(2的32次方-2);

数组是一种特殊的对象方式; 使用方括号访问数组元素就像使用方括号访问对象属性一样; 它将指定的数字索引值转换为字符串并将其用作属性名称;

var n = [];
n[0] = "one";
n[1] = "two";
console.log(n[1]);
var p = {};
p[0] = "one";  // 将0转换为”0”
p[1] = "two";
console.log(p[1]);
var o = {0:"wangwei",1:"wujing",2:"huiyuan"};
o[1] = "lili";
console.log(o[1]);  // lili

所有字段都是对象,因此您可以为它们创建具有任何名称的属性。 此时,如果这个任意名称不是非负整数,则只能作为常规对象属性,而不能作为链表的索引; 类似地,如果偶然,当使用一个非负整数的字符串时,它会被视为链表索引而不是对象属性; 当使用浮点数和整数相等时也是如此:

var arr = [1,2];
arr[-1.23] = true;  // 创建了一个名为“-1.23”的属性
arr["1000"] = 18;   // 数组的第1001个元素
arr[1.000] = 10;    // 等同 arr[1] 
console.log(arr)

事实上,数组索引只是一种特殊类型的对象属性名,这意味着ES链表没有“越界”错误的概念,即当试图查询任何对象中都不存在的属性时,不存在“越界”错误的概念。会报错,但是会得到一个未定义的值。

所有索引都是属性名,但只有2的32次方以内的整数属性名才是索引; 外部索引只能是属性名称。

var 索引 = Math.pow(2,32) - 1; // 4294967295

var arr = 新数组(索引);

arr[索引] = "零"; // 索引作为索引

索引 = 索引 + 3;

arr[索引] = "净"; // 索引作为属性

console.log(arr[索引]);

控制台.log(arr); // 从宽度我们可以看到4294967295

一般来说,数组的实现是经过优化的。 使用数字索引访问数组元素通常比访问常规对象属性快得多,因此尝试使用链表来传输数据;

var p = ["王伟",true,18];

控制台.log(p[0]);

(当然,这种数据结构不太人性化,如果有明确的固定结构,可以使用这些方法)

长度属性:

javascript 数组声明-第十九节 数组字段 - 用于Web后端开发的Javascript - 零程序员

数组对象的 length 属性返回或指定数组元素的数量。 喜欢:

console.log(颜色.长度);

注:由于下标从0开始,所以Length为最后一个元素的下标加1;

length属性是可写的,即链表的宽度可以动态缩小或减小,即可以通过设置length属性来指定链表的粗细。

var colors=["red","blue","green","skey","gray"];
console.log(colors.length);
colors.length = 3;
console.log(colors.length);
console.log(colors);

说明:小于length的元素被删除;

var names=["wangwei"];
names.length = 4;
console.log(names);

如果 length 属性设置为小于链表中项目数的值,则每个新项目将具有未定义的值; (本质上,它并没有向链表添加新元素,只是在链表末尾创建一个空元素。Area实际上就是前面提到的稀疏域);

使用length属性可以方便地在链表末尾添加新项;

var colors=["red","blue","green"];
colors[colors.length]="black";
colors[colors.length]="brown";
console.log(colors);

该数组的最大索引为 4294967294(2 的 32 次方 - 2),这意味着它可以包含 4292967295 个元素。 当索引大于该值且不非负时,数组会手动更新其长度属性; 超出这个范围,长度不会更新; 例如:

var index = Math.pow(2,32) - 1;  // 4294967295
var arr = new Array(index);
arr[index + 3] = "zero";
console.log(arr[index + 3]);
index = index + 4;
arr[index] = "net";
console.log(index);
console.log(arr.length);
console.log(arr)

在ES中,可以使用Object.defineProperty()将链表的length属性设置为只读,如:

var arr = ["wangwei",true,18];
Object.defineProperty(arr, "length", {writable: false});
console.log(arr.length);  // 3
arr.length = 0;
console.log(arr.length);  // 3

稀疏链表和稠密链表:

稀疏数组 稀疏链表:ES中的字段是稀疏的,即链表元素的索引不必是连续的,它们之间可以有间隙; 例如:

var arr = new Array(5);   // 数组没有元素,但length是5
arr = [];   // 空数组,length为0
arr = [1,,4];   // 
arr[1000] = 0;  // 赋值添加了一个元素,length为1001
arr = [1,2,3,4,5];
delete arr[2];  // 使用delete也能生成稀疏数组
console.log(arr);

如果链表是稀疏链表,则长度值小于元素数量; 否则,该属性是数组元素的数量; (即稀疏链表的长度宽度和数量不一致);

遍历期间会跳过此类间隙:

var a1 = [1,,,4];
for(i in a1)
    console.log(i);

但输出链表中间隙位置的值时javascript 数组声明,是未定义的;

Dense([dens])arrays 密集(dense)数组:

与稀疏对应的是稠密链表,即元素之间没有间隙。 事实上,密集链表基本上就是普通的普通链表;

var arr1 = [1, 2, 3];
var arr2 = new Array(1, 2, 3); 
var dense = Array.apply(null, Array(3));   //  初始化时
var dense = Array(undefined, undefined, undefined); //  等同于
for(i in dense)
    console.log(i,dense[i]);

区别:

var array = new Array(3);   //稀疏数组
array[2] = "wangwei";
for(var i in array)
  console.log(i,array[i]);
// 区别
var dense = Array.apply(null, Array(3));  // 密集数组
dense[2] = "wujing";
for(var i in dense)
  console.log(i,dense[i]);

喜欢:

// 密集数组
console.time('one');
Array.apply(null,Array(1e5)).forEach(function(){});
console.timeEnd('one');
// 稀疏数组
console.time('two');
Array(1e5).forEach(function(){});
console.timeEnd('two');
// one: 8.589111328125ms
// two: 2.122314453125ms

实际应用中,大多数es链表都不是稀疏链表; 如果使用稀疏链表,则可以像非稀疏链表一样处理它们,只不过它们包含一些未定义的值。

稀疏链表通常比稠密链表实现更慢并且具有更高的内存利用率。 在这样的链表中查找元素的时间与查找常规元素属性的时间一样长; 另外,一般情况下,我们希望直接声明一个链表,并为其赋予一些特定的初始值。 为了防止出现问题,通常希望将其声明为密集链表;

压缩稀疏链表:可以通过filter()方法压缩其中的间隙,因为过滤器会跳过间隙并返回密集链表,例如:

var a1 = [1,,,4];
var a2 = a1.filter(function(x){return true;});
for(i in a2)
    console.log(i);

团体模式:

ES在Array.prototype中定义了很多操作链表的方法;

将链表转换为字符串:

所有对象都有 toLocaleString()、toString() 和 valueOf() 方法,其中 valueOf() 返回链表本身,toString 方法将链表表示为字符串,每个元素按顺序排列并与以冒号分隔的字符串返回。 (通过对每个项目调用 toString() 方法然后用冒号将它们连接在一起构成); 例如:

var colors=["red","blue",["green","black"]];
console.log(colors.valueOf());  // ["red", "blue", Array(2)]
console.log(colors.toString()); // red,blue,green,blank
console.log(colors);        // ["red", "blue", Array(2)]

上面的console.log()被替换为alert。 由于alert需要接收字符串参数,因此会在后台调用toString(),这会得到与直接调用toString()方法相同的结果;

这里的 toString() 方法返回与不带参数的 join() 方法相同的字符串。

toLocaleString() 是 toString() 方法的本地化版本,通常返回与 toString() 和 valueOf() 方法相同的值,但并非总是如此(它使用本地化分隔符); 当调用链表的toLocaleString()方法时,后台会为每一项调用toLocaleString()方法,而不是tostring()方法。

var p1={
    toLocaleString:function(){return "wangwei"},
    toString:function(){return "wangwei"}
}
var p2={
    toLocaleString:function(){return "wujing"},
    toString:function(){return "Wu"}
}
var person=[p1,p2];
console.log(person);
console.log(person.toString());
console.log(person.toLocaleString());

join() 方法:使用不同的分隔符将链表中的所有元素转换为字符串。 分隔符由用户指定,如:

var colors = ["red","green","blue"];
console.log(colors.join());
console.log(colors.join(","));
console.log(colors.join("|"));
console.log(colors.join(""));
console.log(colors.join(" "));
var arrStr = new Array(10);
console.log(arrStr.join('-'));  // 9个-----

如果不指定分隔符,或者传入undefined,则使用默认的冒号分隔符;

join()方法是split()方法的逆操作,它将一个字符串分割成几个块以创建一个链表。

注意:如果链表中的某一项的值为 null 或未定义,则该值在上述所有方法中都返回空字符串。

String split()方法:将字符串转换为链表;

语法:var aObj=str.split("分隔符");

var str = "red,blue,green";     // 字符串
var aStr=str.split(",");        // 数组
var aStr=str.split("");     // 单个字符数组

如果将空字符串声明为分隔符,则 split 将返回字符串的每个字符; 一般用于需要对字符进行一一处理的情况。

队列模式:

栈和队列是限制插入和删除数据项操作的数据结构;

栈数据结构的访问规则是LIFO(先进后出),而队列数据结构的访问规则是FIFO(先进先出)。

最近添加到堆栈中的项目是第一个要删除的项目; 栈中的插入和删除操作只发生在一个位置,即栈底; 将一项添加到堆栈中称为放入堆栈; 从栈中删除一项,称为出栈;

队列在列表末尾添加项目并从列表后端删除项目; 您可以使用push()方法将项目添加到链表的末尾,并使用shift()方法从链表的后端删除项目。 这两个方法模拟队列;

推()方法:

将一个或多个元素添加到链表末尾并返回链表的新宽度; 它会改变原来的链表;

语法:数组名.push( [ 元素 1, [ 元素 2, […, [元素 N ] ] ] ); element:可选,可以是一个或多个JavaScript对象,以“,”分隔。 喜欢:

var colors=new Array();
var count = colors.push("red","green");
console.log(colors);
console.log(count);  // 2
count = colors.push(["black","blue"]);
console.log(colors);
console.log(count);  // 3

push()方法实际上和手动添加数据是一样的。

弹出()方法:

与push()方法相反,它会删除链表末尾的一个元素并返回; 它会改变原来的链表;

语法:数组名.pop();

var colors=new Array();
colors.push("red","green","blue");
var item = colors.pop();
console.log(item);      // blue
console.log(colors);

unshift() 方法:

在链表顶部插入元素,一次可以插入一个或多个元素,所有元素按顺序插入,操作完成后返回新链表的宽度; 原来的链表会被改变; 它类似于push();

语法:数组名.unshift([Element1, [Element2, [Element3, […, [ElementN]]]]]);

var colors=new Array();
colors.push("red","green","blue");
var newLen = colors.unshift("black","gray");
newLen = colors.unshift("r",["g","b"]);
console.log(newLen);
console.log(colors);

unshift()方法会导致所有下标发生改变;

一次插入多个参数时,插入元素的顺序与其在参数列表中的顺序一致;

如果不关心元素插入的位置,建议使用push方法,因为unshift()方法可能会影响借助下标可以完成的精确估计。

移位()方法:

shift() 删除链表的第一个元素并返回; 该方法执行后,将该字段的剩余元素向前连接,并重新调整下标索引号,从0开始按顺序分配给所有元素; 原始数据将被更改; 与pop方法类似;

语法:数组名.shift();

var colors=new Array();
colors.push("red","green","blue");
var shiftItem = colors.shift();
console.log(colors);
console.log(shiftItem);

调用push()方法和shift()可以使Array对象表现得像一个队列(先进先出);

var colors=new Array();
var count = colors.push("red","green","blue");
count = colors.push("black");
var item = colors.shift();
console.log(colors);

使用unshift()和pop()方法,可以模拟一个相反方向的队列,即在链表后端添加项,在尾部删除项;

var colors=new Array();
var count = colors.push("red","green","blue");
count = colors.unshift("black");
var item = colors.pop();
console.log(colors);

数组排序:

排序算法:选择排序和冒泡排序;

选择排序的原理:首先找到未排序序列中最小(最大)的元素,将其存放到已排序序列的起始位置,然后继续从剩余未排序元素中找到最小(最大)元素,然后放置在最后的排序序列中; 依此类推,直到所有元素都排序完毕,如下:

2,5,8,1,4原始链表

1, 5, 8, 2, 4 第一次,将小值1放在起始位置

1, 2, 8, 5, 4 第二次,从5824中找到2,放在1前面

1, 2, 4, 8, 5 第三次,从854中找到4,放在2前面

1, 2, 4, 5, 8 第三次,从85中找出5,放在4前面

var arr = [3,5,8,1,4];
// 第一次排序,找到最小值1,第2次把i初始值换成2,把arr[0]换成arr[1]
for(var i = 1; i arr[i]){
        var temp;
        temp = arr[0];
        arr[0] = arr[i];
        arr[i] = temp;
    }
}
// 排序所有
for(var i = 1; i<arr.length; i++){
    for(var j = i; j  arr[j]){
            var temp;
            temp = arr[j];
            arr[j] = arr[i-1];
            arr[i-1] = temp;
        }
    }
}
console.log(arr);
// 封装成函数
function selectSort(arr){
    var len = arr.length;
    for(var i = 1; i<len; i++){
        for(var j = i; j  arr[j]){
                var temp;
                temp = arr[j];
                arr[j] = arr[i-1];
                arr[i-1] = temp;
            }
        }
    }
    return arr;
}
console.log(selectSort(arr));

冒泡排序:重复访问待排序数组,每次比较两个相邻元素,如果顺序错误则交换;

4, 8, 8, 8, 8

javascript 数组声明-第十九节 数组字段 - 用于Web后端开发的Javascript - 零程序员

1, 4, 5, 5, 5

8, 1, 4, 4, 4

5, 5, 1, 2, 2

2, 2, 2, 1, 1

5小于2javascript 数组声明,不动,8小于5,不动,1大于8,改变,交换后4大于8,改变,5小于2,不动,1大于5,更换,4更换后大于5,更换,1大于2,更换

var arr = [3,5,8,1,4];
// 封装成函数
function bubbleSort(arr){
    var len = arr.length;
    for(var i = 1; i<len; i++){
        for(var j = 0; j  arr[j + 1]){
                var temp;
                temp = arr[j];
                arr[j] = arr[j+1];
                arr[j+1] = temp;
            }
        }
    }
    return arr;
}
console.log(bubbleSort(arr));

数组中有两个方法可以直接用来重新排序:reverse()和sort()方法;

reverse() 方法反转 Array 对象中所有元素的顺序并更改原始字段;

var values = [1,2,3,4,5];
values.reverse();
alert(values);
 
var colors=new Array();
colors.push("red","green","blue");
colors.reverse();
alert(colors);

verse()方法直观但不够灵活;

sort()方法:对数组元素进行排序并返回; 默认情况下,链表中的所有元素都按相反顺序排序:这会改变原始链表;

var values = [0,1,5,10,15];
values.sort();
console.log(values);
var arr = new Array("banana",undefined,"cherry",null,"apple");
arr.sort();
console.log(arr);

如果链表元素未定义或为空,则它们将排列在链表的末尾;

实际上,sort()方法将元素转换为字符串进行排序;

sort()方法可以接收比较函数来确定排序规则; 比较函数接收两个参数,如果第一个参数位于第二个参数之前,则返回正数;如果两个参数相等,则返回 0。 如果第一个参数位于第二个参数之后,则返回负数; 例如:

function compare(value1,value2){
    if(value1value2){
        return 1;
    }else{
        return 0;
    }
}
var values = [0,1,5,10,15];
values.sort(compare);

对于数值类型或 valueOf() 方法返回数值类型的对象类型,可以使用更简单的比较函数,只需将两个值相减即可,例如:

function compare(value1,value2){
    return value1 - value2;
}

说明:由于该函数通过返回大于零、等于零或小于零的值来影响排序结果,因此加法操作会适当处理所有此类情况。

// 或者使用匿名函数
values.sort(function(value1,value2){
    return value1 - value2;  // 升序
    // return value2 - value1;     // 降序
});
console.log(values);

如果只是反转,使用reverse()会更快;

随机排序:

var arr = [1,2,3,4,5,6,7,8,9];
var randomArr = arr.sort(function(){
    return Math.random() - 0.5;
});
console.log(randomArr);

对于字符串排序,主要问题是大小写:

var str = ["wangwei","juzi","Wujing"];
// console.log(str.sort());  // "Wujing", "juzi", "wangwei"
str.sort(function(s,t){
    var s = s.toLowerCase();
    var t = t.toLowerCase();
    if(s  t) return 1;
    return 0;
});
console.log(str);

另外,有时需要按字符串宽度排序。 这时还应该判断该字符是否是国庆字符:

function getDword(str){
    var len = str.length;
    for(var i=0; i 255)
            len++;
    }
    return len;
}
var arr = ['zero零点','王唯','零点说','zeronetwork','零点网络'];
var sortArr = arr.sort(function(s1,s2){
    return getDword(s1) - getDword(s2);
});
console.log(sortArr);

对象排序,主要比较的是对象的valueof()值:

var o = {valueOf:function(){return "b";}};
var arr = [o,
    {valueOf:function(){return 15}},
    {valueOf:function(){return 18}},
    {valueOf:function(){return 4}}
];
arr.sort(function(o1,o2){return o1 - o2});
console.log(arr);
for(var i in arr)
    console.log(arr[i].valueOf());

或者按指定的对象属性排序:

var wang = {name:"wangwei",sex:"男",age:18};
var wu = {name:"wujing",sex:"女",age:28};
var guo = {name:"jianguo",sex:"男",age: 25};
var arr = [wang,wu,guo];
var pArr = arr.sort(function(p1,p2){
    return p1.age - p2.age;
});
console.log(pArr);

Web后端开发Javascript-零点程序员-王伟

收藏 (0) 打赏

感谢您的支持,我会继续努力的!

打开微信/支付宝扫一扫,即可进行扫码打赏哦,分享从这里开始,精彩与您同在
点赞 (0)

悟空资源网 javascript javascript 数组声明-第十九节 数组字段 - 用于Web后端开发的Javascript - 零程序员 https://www.wkzy.net/game/188833.html

常见问题

相关文章

官方客服团队

为您解决烦忧 - 24小时在线 专业服务