【笔记18】Javascript - 数组
数组
定义
回顾一下对象的定义方式?
1,字面量
2,构造函数
3,自定义构造函数
4,Object.create(原型)
数组的定义方式:就两个
new Array(lenght / content)
字面量
数组的所有方法全来自 Array.prototype
字面量
写逗号,也行:
var arr = [1,,3] // 稀松数组
var arr = [1,,,3] // 每个空位都算长度
看下控制台:
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
从数组的最后一位装东西。
在控制台上操作:
push进去的是数据,在数组的最后一位添加数据。
可以同时添加很多数据,返回的是数组长度。
var arr = [];
console.log(arr.push(3,5,7,9));
console.log(arr);
看控制台:
我们来写一个 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 方法,使用这个方法追加数据,也是挺好使的。
pop
把数组的最后一位剪切出去,还能返回这一位的数据。
var arr = [1,2,3];
var sTemp = arr.pop();
console.log(sTemp);
console.log(arr);
看控制台:
把剪切出来的 3 返回给 sTemp,原数组里没有了。
shift
从数组前面剪切一位数据,并返回这个数据。
var arr = [1,2,3];
console.log(arr.shift());
console.log(arr);
看控制台输出:
unshift
从数组前面添加数据。
var arr = [1,2,3];
arr.unshift(-1,0); // 添加多个
console.log(arr);
看控制台输出:
跟,push 功能相似,只是 unshift 是从数组的最前面添加。
要像写 push 一样,给数组写个 unshift 方法就不那么容易了。
reverse
把原数据逆转顺序。
var arr = [1,2,3];
console.log(arr);
arr.reverse();
console.log(arr);
看控制台输出:
数组里的数据顺序颠倒了。
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);
看控制台输出:
从第一位开始,截了两位,还能返回被截的数组。
注意:数组的下标是 “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);
看控制台输出:
splice 不但可以截取数据,还能开始的位置补数据进去,是不是很强大。
注意:第一个参数是起始位,第二个参数是截取长度,第三个参数往后都是添加数据。
再来看一个:
var arr = [1,2,3];
console.log(arr);
console.log(arr.splice(-1,1));
console.log(arr);
还能从负数开始: -1 代表倒数第1位;
数组在算从哪个位数开始的时候,也是有个算法的:
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);
看控制台输出:
从第三位开始,截0个,补个4,这一招挺有意思的。
所以说,这个方法还是挺强大的,不过最强大的还是 sort 。
sort
排序,根据回调函数来自定义排序。
var arr = [1,2,-1,0,8,3,5,4];
console.log(arr);
console.log(arr.sort());
看控制台输出:
就是给数组排序,看起来像个升序;
如果我想降序呢?就加个 reverse。
现在来改个数字:
var arr = [1,2,-1,0,8,10,5,4];
console.log(arr);
console.log(arr.sort());
再看看输出:
是不是变了,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比:返回负,不动;
经过四轮比较,新的顺序产生了,这是冒泡排序的算法,得到一个升序的排序。
看控制台输出:
如果我们改变一下比较的条件,就能获得降序的排序了。
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; // 降序
})
看控制台输出:
示例:按字符串长度排序
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);
看控制台输出:
以上几个方法都会改变原数组,以下几个方法,不会改变原数组。
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);
看控制台输出:
toSTring
把数组变成字符串。
这个比较简单。
slice
和 splice 挺像,也是截取数组返回数组,但不改变原数组。
若是带一个参数:slice(从该位开始,截取到最后)
var arr1 = [1,2,3,4,5,6,7,8];
console.log(arr1);
console.log(arr1.slice(2)); // 从第2位开始,截取到最后。
也可以是负数。
若是带两个参数: 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位;
若是不写参数:那就全部截取。
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("-")); // 用字符串 "-"
换一个字符串:用字符串“&&”
var arr = [1,2,3,4,5];
console.log(arr.join("&&")); // 用字符串 "&&"
这个方法挺有用。
split
把字符串按连接符拆开来,并返回数组,和join互逆。
split() 是把字符串返回数组,正好可以把 join 连接起来的字符串,拆开来变成数组。
var str = "1.2.3.4.5";
var arr = str.split(".");
console.log(arr);
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