Skip to content

Commit da9d3c9

Browse files
Merge pull request wangzheng0822#3 from myLightLin/master
Add:Array.md
2 parents 704a1af + 9513527 commit da9d3c9

File tree

1 file changed

+306
-0
lines changed

1 file changed

+306
-0
lines changed

javascript/05_array/Array.md

Lines changed: 306 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,306 @@
1+
与 Java 、PHP 等语言不同,在 JavaScript 中,数组其实是一种特殊的对象。
2+
#### 数组的创建与读写
3+
以下两种方式都可创建数组:
4+
```
5+
// 字面量方式,常用
6+
var num = [1,5,6,10];
7+
print(num.length); // 4
8+
9+
// 构造函数方式
10+
var num = new Array(1,5,6,10);
11+
print(num.length); // 4
12+
```
13+
值得注意的是,JavaScript 中的数组数据可以是不同类型,它的语法相对宽松,例如可以指定不同类型数据`var example = [1,"Mike",true,null];`另外,可以通过`Array.isArray()`来判断一个对象是否是数组,例如:
14+
```
15+
var num = [1,5,6,10];
16+
print(Array.isArray(num)); // true
17+
```
18+
如何读写数组呢?可以使用循环。
19+
```
20+
var num = [1,5,6,10];
21+
for (var i = 0; i < num.length; i++) {
22+
console.log(num[i]+" ");
23+
}
24+
```
25+
#### 数组的深复制与浅复制
26+
当我们把数组赋给另外一个数组,然后改变其中一个数组的值,另一数组也会随之改变,这就是数组的浅复制。而深复制指的就是不改变原来的数组而去创建一个新的数组,这种情况是经常使用的,为了不破坏原数组。下面的代码展示了这两种复制
27+
```
28+
// 浅复制
29+
var num = [1,2,3,4,5];
30+
var newNum = num;
31+
num[0] = 10;
32+
console.log(newNum[0]); // 10
33+
34+
// 深复制
35+
function copy (arr1,arr2) {
36+
for(var i=0;i<arr1.length;i++){
37+
arr2[i] = arr1[i];
38+
}
39+
}
40+
var num = [1,5,6,7,9];
41+
var newNum = [];
42+
copy(num,newNum);
43+
num[0] = 10;
44+
console.log(newNum[0]); // 仍然为 1
45+
```
46+
#### 存取函数
47+
JavaScript 提供了一组用来访问数组元素的函数,叫存取函数。最常用的存取函数就是 indexOf() 函数,该函数返回指定查找的值在目标值中是否存在,如果存在,返回该值在数组中的索引,不存在则返回 -1。
48+
```
49+
var word = ["A","B","C","D"];
50+
var result = word.indexOf("A");
51+
console.log(result); // 0
52+
var test = word.indexOf("F");
53+
console.log(test); // -1
54+
```
55+
除此之外,还有 join 和 toString 函数,concat 和 splice 函数。前两个函数可以将数组转化为字符串,后面两个函数可以通过已有的数组创建新数组,其中 concat 方法通过合并多个数组来形成新数组,而 splice 方法是截取一个数组的子集作为一个新数组。它们的使用示例如下
56+
```
57+
var arr = ["Mike","John","Hexo"];
58+
console.log(arr.join()); // Mike,John,Hexo
59+
console.log(arr.toString()); // Mike,John,Hexo
60+
61+
var arr1 = [1,10,"Mike"];
62+
var arr2 = [8,7,6];
63+
var cat = arr1.concat(arr2);
64+
console.log(cat); // [1, 10, "Mike", 8, 7, 6]
65+
var num = [1,2,3,4,5,6,7];
66+
var a = num.splice(3,2); // 3 表示索引,2 表示删除 2 个
67+
console.log(num); // [1, 2, 3, 6, 7]
68+
```
69+
#### 可变函数
70+
不去引用数组中的某个元素,就能改变数组内容,这种函数称它为可变函数。
71+
###### push() 和 unshift()、pop() 和 shift()
72+
push() 方法可以在数组末尾添加元素,而 unshift() 方法可以在数组开头添加元素;相对应的,pop 可以删除数组末尾的元素,而 shift 删除数组的第一个元素。
73+
```
74+
var nums = [9,58,15,16,23];
75+
nums.push(111);
76+
console.log(nums); // 9, 58, 15, 16, 23, 111
77+
nums.unshift(1);
78+
console.log(nums); // 1, 9, 58, 15, 16, 23, 111
79+
nums.pop();
80+
console.log(nums); // 1, 9, 58, 15, 16, 23
81+
nums.shift();
82+
console.log(nums); // 9, 58, 15, 16, 23
83+
```
84+
###### splice()、sort()、reverse()
85+
前面提到的 splice 不仅可以用来删除元素,还可以添加元素进数组。用 sort 可以为数组排序,reverse 将数组内的元素翻转。
86+
```
87+
var num = [98,99,100,101];
88+
num.splice(1,0,89); // 1 表示索引,0 表示不删除元素,89 表示将 89 这个元素添加进数组
89+
console.log(num); // 98, 89, 99, 100, 101
90+
num.reverse();
91+
console.log(num); // 101, 100, 99, 89, 98
92+
```
93+
关于 sort 方法非常有意思,它只能对那些字符串类型的元素排列得比较准确,但如果是数字,结果就不那么令人满意了。看看例子.
94+
```
95+
var str = ["hello","client","zero"];
96+
str.sort();
97+
console.log(str); // ["client", "hello", "zero"] 按照字母 a-z 排列准确
98+
var nums = [1,200,51,66,88];
99+
nums.sort();
100+
console.log(nums); // [1, 200, 51, 66, 88] 有趣的事情来了,因为 200 的 2 比 51 的 5 先,所以 200 排在 51 前头
101+
```
102+
那如何解决这种排序的错误呢?方法就是在调用 sort() 的时候传入一个函数,该函数可以比较出大小。
103+
```
104+
function compare(num1,num2){
105+
return num1 - num2;
106+
}
107+
var nums = [3,1,2,100,4,200];
108+
nums.sort(compare);
109+
console.log(nums); // 1, 2, 3, 4, 100, 200
110+
```
111+
可以看到,已经排序正确了,compare 函数就是利用了两数相减,如果结果为正,那么被减数大于减数,如果结果为 0,则两数相等,而如果结果为负,说明被减数小于减数。
112+
#### 迭代器方法
113+
迭代函数通过对数组中的元素逐个应用,来操作返回相应的值。
114+
###### 不返回新数组的 forEach() 、every()、some()、reduce()
115+
```
116+
// 用 forEach 开方
117+
function square(num) {
118+
console.log(num,num*num);
119+
}
120+
var num = [1,2,3,4,5];
121+
num.forEach(square);
122+
console.log(num);
123+
/* 1 1
124+
2 4
125+
3 9
126+
4 16
127+
5 25
128+
*/
129+
```
130+
```
131+
/*
132+
every() 返回值为布尔类型,对于应用的所有元素,该函数返回 true,则该方法返回 true
133+
*/
134+
function isEven(num){
135+
return num % 2 == 0;
136+
}
137+
var num = [2,4,6,8,10];
138+
var even = num.every(isEven);
139+
if(even){
140+
console.log("所有的数字都是偶数");
141+
}else{
142+
console.log("不是所有的数字都是偶数");
143+
}
144+
```
145+
```
146+
/*
147+
some() 与 every() 的不同就是只要有一个元素使改函数返回 true ,那么该方法就返回 true
148+
*/
149+
function isEven(num){
150+
return num % 2 == 0;
151+
}
152+
var num = [1,2,3,4,5,6,7,8];
153+
var someEven = num.some(isEven);
154+
if(even){
155+
console.log("有些数字是偶数");
156+
}else{
157+
console.log("没有数字是偶数");
158+
}
159+
```
160+
```
161+
/*
162+
reduce() 有两个功能,一是可以对数组元素进行求和,二是将数组元素连接成字符串。
163+
*/
164+
fucntion add(num1,num2){
165+
return num1 + num2;
166+
}
167+
var num = [1,2,3,4];
168+
var sum = num.reduce(add);
169+
console.log(sum); // 10
170+
171+
function concat(str,i) {
172+
return str + i;
173+
}
174+
var words = ["I am ","a ","coder "];
175+
var re = words.reduce(concat);
176+
console.log(re); // I am a coder
177+
```
178+
###### 返回新数组的 map() 和 filter()
179+
map 的作用与 forEach 是一样的,区别就是 map 函数返回的是一个新数组。
180+
```
181+
function addFive(grade){
182+
return grade += 5;
183+
}
184+
var grade = [77,82,88,95,90];
185+
var result = grade.map(addFive);
186+
console.log(result); // 82, 87, 93, 100, 95
187+
```
188+
而 filter 和 every 相似,区别在于当所有的元素使改函数为 true 时,它并不返回布尔类型,而是返回一个新数组。下面这个例子十分有趣,它随机产生10个 0 到 100 的数字作为分数,然后把大于 60 的及格分数筛选出来。
189+
```
190+
function passing(num){
191+
return num >= 60;
192+
}
193+
var grades = [];
194+
for(var i = 0;i < 11;i++){
195+
grade[i] = Math.floor(Math.random() * 101);
196+
}
197+
var pass = grades.filter(passing);
198+
console.log("随机产生的 10 个同学的分数为:");
199+
console.log(grades);
200+
console.log("及格的分数有:");
201+
console.log(pass);
202+
```
203+
上述代码的输出结果为
204+
> 随机产生的 10 个同学的分数为:
205+
21, 4, 89, 45, 5, 51, 71, 7, 46, 53, 47
206+
及格的分数有:
207+
89, 71
208+
#### 二维数组
209+
JavaScript 可以通过在数组里在嵌套一个数组来形成二维数组。
210+
```
211+
var grades = [[88,86,82],[91,82,83],[77,72,79]];
212+
console.log(grades[1][2]); // 83
213+
```
214+
#### 处理二维数组
215+
对于二维数组的处理可以分为两种,一种按列访问,一种是按行访问。
216+
按列访问,外层循环对应行,内层循环对应列。例如,上述的数组,每一行对应一个学生的成绩记录,可以通过相加所有成绩,然后除以科目数来得到该生的平均成绩。
217+
```
218+
var grades = [[88,86,82],[91,82,83],[77,72,79]];
219+
var total = 0;
220+
var average = 0.0;
221+
for(var row = 0;row<grades.length;++row){
222+
for(var col = 0;col<grades[row].length;++col){
223+
total += grades[row][col];
224+
}
225+
average = total/grades[row].length;
226+
console.log("student "+parseInt(row+1)+" average: "+average.toFixed(2)); // toFixed 表示按照 2 位来保留小数
227+
total = 0;
228+
average = 0.0;
229+
}
230+
```
231+
上述代码的输出结果为
232+
> student 1 average: 85.33
233+
student 2 average: 85.33
234+
student 3 average: 76.00
235+
236+
237+
对于按行访问,则外层循环对应列,内城循环对应行,例如还是上述数组,现在的数组表示一个学生各科的分数,我们来求其平均成绩
238+
```
239+
var grades = [[88,86,82],[91,82,83],[77,72,79]];
240+
var total = 0;
241+
var average = 0.0;
242+
for(var col = 0;col <grades.length;++col ){
243+
for(var row= 0;row<grades[col ].length;++row){
244+
total += grades[row][col];
245+
}
246+
average = total/grades[col ].length;
247+
console.log("exam "+parseInt(col +1)+" average: "+average.toFixed(2));
248+
total = 0;
249+
average = 0.0;
250+
}
251+
```
252+
输出结果为:
253+
> exam 1 average: 85.33
254+
exam 2 average: 80.00
255+
exam 3 average: 81.33
256+
257+
其实只要调整 for 循环的顺序就可以控制是按行还是按列来输出,此外,JavaScript 还可以处理一些参差不齐的数组,比如一个二维数组中的数组,有的是两个元素,有的是四个元素,并不是都相同,在这种情况下,JavaScript 依然可以处理运行而不报错,这是因为不管多或少,都可以通过 length 属性来计算。
258+
#### 对象数组
259+
如果你有阅读到这里,你应该可以发现上面的所有例子里数据类型都是基本数据类型,不是数字就是字符串。对象数组,顾名思义,就是数组里面的元素可以是对象,这个与 java 的语法很相似,基本上所有的编程语言都是相通的。看看下面这个例子:
260+
```
261+
function point(x,y){
262+
this.x = x;
263+
this.y = y;
264+
}
265+
function show(arr){
266+
for(var i=0;i<arr.length;i++){
267+
console.log(arr[i].x + ", "+arr[i].y);
268+
}
269+
}
270+
var p1 = new Point(1,2);
271+
var p2 = new Point(2,4);
272+
var p3 = new Point(8,1);
273+
var p4 = new Point(2,9);
274+
var point = [p1,p2,p3,p4];
275+
for(var i=0;i<point.lengh;i++){
276+
console.log("Point "+parseInt(i+1)+": "+point[i].x+", "+point[i].y);
277+
}
278+
```
279+
上述程序的输出结果为:
280+
> Point 1: 1, 2
281+
Point 2: 2, 4
282+
Point 3: 8, 1
283+
Point 4: 2, 9
284+
285+
也可以用之前的 puh() 等操作方法来操作对象数组
286+
```
287+
var p5 = new Point(11,13);
288+
point.push(p5);
289+
console.log("添加了 p5 后:");
290+
show(point);
291+
point.shift();
292+
console.log("删除第一个元素后:")
293+
show(point);
294+
```
295+
输出结果为:
296+
> 添加了 p5 后:
297+
1,2
298+
2,4
299+
8,1
300+
2,9
301+
11,13
302+
删除第一个元素后:
303+
2,4
304+
8,1
305+
2,9
306+
11,13

0 commit comments

Comments
 (0)