【笔记18】Javascript - 数组

数组

定义

回顾一下对象的定义方式?

1,字面量

2,构造函数

3,自定义构造函数

4,Object.create(原型)

数组的定义方式:就两个

new Array(lenght / content)

字面量 

数组的所有方法全来自 Array.prototype


字面量

var arr = [1,2,3,4,5];

写逗号,也行:

var arr = [1,,3]   // 稀松数组
var arr = [1,,,3] // 每个空位都算长度

看下控制台:

Javascript(笔记18) - 数组_数组

new Array()

var arr = new Array();

new Array()和字面量,定义数组很相似,唯一的区别是只传一个参数的时候:

var arr1 = new Array(10);   // 创建一个长度为10的空数组
var arr2 = [10]; // 创建一个只有一位的数组,这一位的值是10;

数组的读和写

arr[num] ;  // 不可以溢出读  返回 undefined

arr[num] = xxx; // 可以溢出写

数组的读写非常松散的,几乎不会出错;


数组常用方法

会改变原数组: push,pop,shift,unshift,sort,reverse,splice

不改变原数组: concat,join,split,toString,slice


Javascript 分三个部分:ECMAScript ,DOM, BOM

ECMAScript:大家都要遵守的标准,ES;

DOM:操作文档对象,大部分浏览器都兼容;

BOM:大部分浏览器都不兼容,但用的少;


数组的方法也分为: es3.0 、 es5.0 、es6.0;

ES3里包括了大部分数组的方法;

ES5里有一些增加,后面补上;

push

从数组的最后一位装东西。

var arr = [];

在控制台上操作:

Javascript(笔记18) - 数组_数组_02

push进去的是数据,在数组的最后一位添加数据。

可以同时添加很多数据,返回的是数组长度。

var arr = [];        
console.log(arr.push(3,5,7,9));
console.log(arr);

看控制台:

Javascript(笔记18) - 数组_数组_03


我们来写一个 push 方法:

Array.prototype.push = function () {
for (var i = 0; i < arguments.length; i++) {
this[this.length] = arguments[i];
}
return arguments.length
}
var arr = [1];
console.log(arr.push(2, 3, 4, 5, 6));
console.log(arr);

在原型上写一个 push 方法,使用这个方法追加数据,也是挺好使的。

Javascript(笔记18) - 数组_数组_04


pop

把数组的最后一位剪切出去,还能返回这一位的数据。

var arr = [1,2,3];
var sTemp = arr.pop();
console.log(sTemp);
console.log(arr);

看控制台:

Javascript(笔记18) - 数组_数组方法_05

把剪切出来的 3 返回给 sTemp,原数组里没有了。

shift

从数组前面剪切一位数据,并返回这个数据。

var arr = [1,2,3];
console.log(arr.shift());
console.log(arr);

看控制台输出:

Javascript(笔记18) - 数组_数组_06

unshift

从数组前面添加数据。

var arr = [1,2,3];
arr.unshift(-1,0); // 添加多个
console.log(arr);

看控制台输出:

Javascript(笔记18) - 数组_数组方法_07

跟,push 功能相似,只是 unshift 是从数组的最前面添加。

要像写 push 一样,给数组写个  unshift 方法就不那么容易了。


reverse

把原数据逆转顺序。

var arr = [1,2,3];
console.log(arr);
arr.reverse();
console.log(arr);

看控制台输出:

Javascript(笔记18) - 数组_数组_08

数组里的数据顺序颠倒了。

splice

切片,arr.splice(从第几位开始,截取多少长度,添加新的数据)

var arr = [1,2,3,4,5,6,7,8];
console.log(arr);
console.log(arr.splice(1,2)); // 从第一位开始,截两位,还能返回一个数组;
console.log(arr);

看控制台输出:

Javascript(笔记18) - 数组_数组方法_09

从第一位开始,截了两位,还能返回被截的数组。

注意:数组的下标是 “0” 开始,就是说第 “0” 位是数组的第一个数据;

改一下:

var arr = [1,2,3,4,5,6,7,8];
console.log(arr);
console.log(arr.splice(1,2,"2","2","3","3")); // 从第一位开始,截两位,再从这开始补4位;
console.log(arr);

看控制台输出:

Javascript(笔记18) - 数组_数组_10

splice 不但可以截取数据,还能开始的位置补数据进去,是不是很强大。

注意:第一个参数是起始位,第二个参数是截取长度,第三个参数往后都是添加数据。

再来看一个:

var arr = [1,2,3];
console.log(arr);
console.log(arr.splice(-1,1));
console.log(arr);

还能从负数开始:  -1 代表倒数第1位;

Javascript(笔记18) - 数组_数组方法_11

数组在算从哪个位数开始的时候,也是有个算法的:

pos += pos > 0 ? 0 : this.length;

怎么理解呢?这里面有个三目运算。

如果我们传入一个正数:2;

pos  = 2 + 0 = 2;

如果我们传入一个负数: -1 ;

pos = -1 + 3(this.length); = 2;   从第2位开始,正好等于倒数第1位。

感叹这个算法的巧妙和简洁;



示例:把数组的3和5之间,加个4。

var arr = [1,2,3,5];
console.log(arr);
arr.splice(3,0,4); // 从第三位开始,截0个,补一个4.
console.log(arr);

看控制台输出:

Javascript(笔记18) - 数组_数组_12

从第三位开始,截0个,补个4,这一招挺有意思的。

所以说,这个方法还是挺强大的,不过最强大的还是 sort 。 


sort

排序,根据回调函数来自定义排序。

var arr = [1,2,-1,0,8,3,5,4];
console.log(arr);
console.log(arr.sort());

看控制台输出:

Javascript(笔记18) - 数组_数组方法_13

就是给数组排序,看起来像个升序;

如果我想降序呢?就加个 reverse。

arr.sort().reverse()

现在来改个数字:

var arr = [1,2,-1,0,8,10,5,4];
console.log(arr);
console.log(arr.sort());

再看看输出:

Javascript(笔记18) - 数组_数组方法_14

是不是变了,10怎么跳错位置了?其实是按 ASC码的顺序排的。那我是想要真正的升序排序。


自定义排序

回调函数规则:

1,必须写俩形参;

2,通过俩形参比较,再看返回值;

2.1 当返回值为负数时,那么前面的数放在前面;

2.2 当返回值为正数时,那么后面的数放在前面;

2.3 当返因值为0时,不动;


// return a-b 升序;

// return b-a 降度;


arr.sort(function(a,b){

return  X;

});

var arr = [5,3,6,4,10];
console.log(arr);
arr.sort(function(a,b){ // 回调函数
if(a>b){ // 挨个比较大小
return 1; // 返回值为正,那么后面数放前面;
}else{
return -1; // 返回值为负,那么前面数放前面;
}
});
console.log(arr);

第一轮:从第0位的数开始,逐个跟后面比。数据的顺序为:5,3,6,4,10;

5跟3比:返回正,后面数放前面,即3和5对调位置;顺序变为:3,5,6,4,10;

3跟6比:返回负,前面数放前面,相当于不动;

3跟4比:返回负,不动;

3跟10比:返回负,不动;

第二轮:从第1位的数开始,逐个跟后面比。数据的顺序为:3,5,6,4,10;

5跟6比:返回负,不动;

5跟4比:返回正,后面数放前面,即4和5对调位置,顺序变为:3,4,6,5,10;

4跟10比:返回负,不动;

第三轮,从第2位的数开始,逐个跟后面比。数据的顺序为:3,4,6,5,10;

6跟5比:返回正,后面数放前面,即6和5对调位置,顺序变为:3,4,5,6,10;

5跟10比:返回负,不动;

第四轮,从第3位的数开始,逐个跟后面比。数据的顺序为:3,4,5,6,10;

6跟10比:返回负,不动;

经过四轮比较,新的顺序产生了,这是冒泡排序的算法,得到一个升序的排序。

看控制台输出:

Javascript(笔记18) - 数组_数组_15

如果我们改变一下比较的条件,就能获得降序的排序了。

var arr = [5,3,6,4,10];
console.log(arr);
arr.sort(function(a,b){
if(a < b){ // 改变a和b比较的顺序,就能获得降序排序了。
return 1;
}else{
return -1;
}
});
console.log(arr);

这个回调函数看着是有点恶心了,我们能不能改一下代码,让他们变得更通用一些,优雅一些?

推导的过程,不写了,直接一行代码搞定:各位思考一下这个数学逻辑;

var arr = [5,3,6,4,10];
console.log(arr);
arr.sort(function(a,b){
return a-b; // 升序
});
console.log(arr); // [3, 4, 5, 6, 10]

逻辑分析:直接 return a-b ,奇妙在哪里? 

如果 a > b ,那么 a - b > 0 , 为正,被返回;

如果 a < b ,那么 a - b < 0 , 为负,被返回;

如果 a = b ,那么 a - b = 0 ,为0,被返回;

这个推导,是不是省去了上面的 if else,神奇就在这了。

那我们要降序排序呢? 直接 return b -a 就完事了。

var arr = [5,3,6,4,10];
console.log(arr);
arr.sort(function(a,b){
return b -a ; // 降序
});
console.log(arr); // [10, 6, 5, 4, 3]


示例:乱序

给一个有序的数组,乱序;

var arr = [1,2,3,4,5,6,7];

思路:还是用 sort 排序,但要人为的控制  return 返回值,不就好了么? 

所以引用 Math.random(),来返回 (0-1)之间的开区间数;

var arr = [5,3,6,4,10];
console.log(arr);
arr.sort(function(a,b){
return Math.random() - 0.5; // 乱序
});
console.log(arr);

示例:按年龄排序

要求,给3个对象放进数组,并按年龄 age 排序;

var jack = {
name : "Jack",
age :20
}
var tom = {
name:"Tom",
age: 30
}
var jerry = {
name :"Jerry",
age : 40
}

拿到对象的年龄,放进回调函数里比较;

var arr = [jack,jerry,tom];
arr.sort(function(a,b){
// return a.age - b.age; // 升序
return b.age - a.age; // 降序
})

看控制台输出:

Javascript(笔记18) - 数组_数组_16

示例:按字符串长度排序

var arr = ["ac","a","abed","awe","awfaw","awf","awefawa"]

分析:取字符串长度就可以了。

arr.sort(function(a,b){
return b.length - a.length; // 降序
})

如果按字节长度呢?那还得先写个函数来计算字节长度;

// 先写个计算字节长度的函数
function retBytes(str) {
var num = str.length;
for (var i = 0; i < str.length; i++) {
if (str.charCodeAt(i) > 255) {
num++;
}
}
return num;
}
var arr = ["a中c","a国","ab我们ed","a你好we","aw博客faw","a51CTOwf","awe发"]
arr.sort(function(a,b){
return retBytes(a) - retBytes(b); // 升序
})
console.log(arr);

看控制台输出:

Javascript(笔记18) - 数组_数组方法_17


以上几个方法都会改变原数组,以下几个方法,不会改变原数组。


concat

连接数组,把后面的数组跟前面的边起来。

var arr1 = [1,2,3];
var arr2 = [4,5,6];
var arr3 = arr1.concat(arr2);
console.log(arr1);
console.log(arr2);
console.log(arr3);

看控制台输出:

Javascript(笔记18) - 数组_数组方法_18

toSTring

把数组变成字符串。

var arr1 = [1,2,3];

这个比较简单。

Javascript(笔记18) - 数组_数组方法_19

slice

和 splice 挺像,也是截取数组返回数组,但不改变原数组。

若是带一个参数:slice(从该位开始,截取到最后)

var arr1 = [1,2,3,4,5,6,7,8];
console.log(arr1);
console.log(arr1.slice(2)); // 从第2位开始,截取到最后。

Javascript(笔记18) - 数组_数组方法_20

也可以是负数。

若是带两个参数: slice(从该位开始截取,截取到该位)

var arr1 = [1,2,3,4,5,6,7,8];
console.log(arr1);
console.log(arr1.slice(2,5)); // 从第2位开始,截取到第5位,这个跟splice不一样。

从第2位开始,截取到第5位;

Javascript(笔记18) - 数组_数组_21

若是不写参数:那就全部截取。

var arr1 = [1,2,3,4,5,6,7,8];
console.log(arr1);
console.log(arr1.slice()); // [1,2,3,4,5,6,7,8] 全部截取

join

把数组的每一位连接起来,用什么来连,取决于join的参数,参数必须是字符串类型。

把数组用字符串连接起来,并返回字符串。不传连接字符,默认用逗号连。

var arr = [1,2,3,4,5];
console.log(arr.join("-")); // 用字符串 "-"

Javascript(笔记18) - 数组_数组方法_22

换一个字符串:用字符串“&&”

var arr = [1,2,3,4,5];
console.log(arr.join("&&")); // 用字符串 "&&"

Javascript(笔记18) - 数组_数组方法_23

这个方法挺有用。

split

把字符串按连接符拆开来,并返回数组,和join互逆。

split() 是把字符串返回数组,正好可以把 join 连接起来的字符串,拆开来变成数组。

var str = "1.2.3.4.5";
var arr = str.split(".");
console.log(arr);

Javascript(笔记18) - 数组_数组方法_24

var str = "1-2-3-4-5";
var arr = str.split("-");
console.log(arr); // ['1', '2', '3', '4', '5']


示例:

让我们把这些字符串,用“-”连接起来,放在一个字符串里。

var str1 = "alibaba";
var str2 = "tencent";
var str3 = "baidu";
var str4 = "toutiao";
var str5 = "sina"

放到数组里,再用 join 连,join 不传参数,按逗号连。

var arr = [str1,str2,str3,str4,str5]
arr.join("-"); // alibaba-tencent-baidu-toutiao-sina