思考:
1、数组构造器有哪几种?
2、哪些是改变自身的方法?
3、哪些是不改变自身的方法?
4、遍历的方法?
什么是数组?
知识点:
MDN中定义,JavaScript的 **Array** 对象是用于构造数组的全局对象,数组是类似于列表的高阶对象。数组是一种类列表对象,它的原型中提供了遍历和修改元素的相关操作。JavaScript 数组的长度和元素类型都是非固定的。因为数组的长度可随时改变,并且其数据在内存中也可以不连续,所以 JavaScript 数组不一定是密集型的,这取决于它的使用方式。只能用整数作为数组元素的索引,而不能用字符串。使用非整数并通过方括号或点号来访问或设置数组元素时,所操作的并不是数组列表中的元素,而是数组对象的属性集合上的变量。数组对象的属性和数组元素列表是分开存储的,并且数组的遍历和修改操作也不能作用于这些命名属性。
数组索引从0开始,想想为什么不是从 1 开始?(可从内存空间的相对位移,偏移量,算法复杂度方面思考)最后一个元素的索引等于该数组的长度减1。如果指定的索引是一个无效值,js 数组并不会报错,而是会返回 undefined。
虽然数组元素可以看做是数组对象的属性,就像 toString 一样,但是 console.log(arr.name)这样的写法是错误的,运行时会抛出 SyntaxError 异常,而原因则是使用了非法的属性名。在 js 中,以数字开头的属性不能用点号引用,必须用方括号。如 console.log(arr['name']) 是ok的。
方法: 修改器方法 VS 访问方法 VS 迭代方法
一、修改器方法,下面的这些方法会改变调用它们的对象自身的值
1、push 在数组的末尾增加一个或多个元素,并返回数组的新长度。
2、unshift 在数组的开头增加一个或多个元素,并返回数组的新长度。
3、pop 删除数组的最后一个元素,并返回这个元素。
4、shift 删除数组的第一个元素,并返回这个元素。
现学现卖,
数组实现一个栈 (Stack);
function Stack () {
var items = [] // 存储数据 // 从栈顶添加元素,也叫压栈 this.push = function (item) { items.push(item) } // 弹出栈顶元素 this.pop = function () { return items.pop() } // 返回栈顶元素 this.top = function () { return items[items.length - 1] } // isEmpty 返回栈是否为空 this.isEmpty = function () { return items.length == 0 } // size 方法返回栈的大小 this.size = function () { return items.length } // clear 清空栈 this.clear = function () { items = [] }}
数组实现一个 队列(Queue)
function Queue () {
var items = []; // 向队列尾部添加一个元素 this.enqueue = function(item){ items.push(item) } // 移除队列头部元素 this.dequeue = function(){ return items.shift() } // 返回队列头部元素 this.head = function(){ return items[0]; } // 返回队列尾部的元素 this.tail = function(){ return items[items.length - 1] } // 返回队列大小 this.size = function(){ return items.length } // clear this.clear = function(){ items = [] } // isEmpty this.isEmpty = function(){ return items.length == 0 }}
5、copyWithin
在数组内部,将一段元素序列拷贝到另一段元素序列上,覆盖原有的值。
6、fill
将数组中指定区间的所有元素的值,都替换成某个固定的值。
7、reverse
颠倒数组中元素的排列顺序,即原先的第一个变为最后一个,原先的最后一个变为第一个。
8、sort
对数组元素进行排序,并返回当前数组。
9、splice
在任意的位置给数组添加或删除任意个元素。
二、访问方法 ,下面的这些方法绝对不会改变调用它们的对象的值,只会返回一个新的数组或者返回一个其它的期望值。
基于 ES7,不会改变自身的方法也有 9 个,分别为 concat、join、slice、toString、toLocaleString、indexOf、lastIndexOf、未形成标准的 toSource,以及 ES7 新增的方法 includes。
1、concat 返回一个由当前数组和其它若干个数组或者若干个非数组值组合而成的新数组。
2、join 连接所有数组元素组成一个字符串。
3、slice 抽取当前数组中的一段元素组合成一个新数组。
4、toString 返回一个由所有数组元素组合而成的字符串。遮蔽了原型链上的 Object.prototype.toString() 方法。
5、toLocaleString 返回一个由所有数组元素组合而成的本地化后的字符串。遮蔽了原型链上的 Object.prototype.toLocaleString() 方法。
6、indexOf 返回数组中第一个与指定值相等的元素的索引,如果找不到这样的元素,则返回 -1。
7、lastIndexOf 返回数组中最后一个(从右边数第一个)与指定值相等的元素的索引,如果找不到这样的元素,则返回 -1。
8、toSource 返回一个表示当前数组字面量的字符串。遮蔽了原型链上的 Object.prototype.toSource() 方法。
9、includes 判断当前数组是否包含某指定的值,如果是返回 true,否则返回 false。
// concat方法
var array = [1, 2, 3];
var array2 = array.concat(4,[5,6],[7,8,9]);
console.log(array2); // [1, 2, 3, 4, 5, 6, 7, 8, 9]
console.log(array); // [1, 2, 3], 可见原数组并未被修改
// join方法
var array = ['We', 'are', 'Chinese'];
console.log(array.join()); // "We,are,Chinese"
console.log(array.join('+')); // "We+are+Chinese"
// slice方法
var array = ["one", "two", "three","four", "five"];
console.log(array.slice()); // ["one", "two", "three","four", "five"]
console.log(array.slice(2,3)); // ["three"]
// toString方法
var array = ['Jan', 'Feb', 'Mar', 'Apr'];
var str = array.toString();
console.log(str); // Jan,Feb,Mar,Apr
// tolocalString方法
var array= [{name:'zz'}, 123, "abc", new Date()];
var str = array.toLocaleString();
console.log(str); // [object Object],123,abc,2016/1/5 下午1:06:23
// indexOf方法
var array = ['abc', 'def', 'ghi','123'];
console.log(array.indexOf('def')); // 1
// includes方法
var array = [-0, 1, 2];
console.log(array.includes(+0)); // true
console.log(array.includes(1)); // true
var array = [NaN];
console.log(array.includes(NaN)); // true
三、迭代方法
数组遍历的方法
基于 ES6,不会改变自身的遍历方法一共有 12 个,分别为 forEach、every、some、filter、map、reduce、reduceRight,以及 ES6 新增的方法 entries、find、findIndex、keys、values。
[Array.prototype[@@iterator]()](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/@@iterator) 和上面的 values() 方法是同一个函数。
// forEach方法
var array = [1, 3, 5];
var obj = {name:'cc'};
var sReturn = array.forEach(function(value, index, array){
array[index] = value;
console.log(this.name); // cc被打印了三次, this指向obj
},obj);
console.log(array); // [1, 3, 5]
console.log(sReturn); // undefined, 可见返回值为undefined
// every方法
var o = {0:10, 1:8, 2:25, length:3};
var bool = Array.prototype.every.call(o,function(value, index, obj){
return value >= 8;
},o);
console.log(bool); // true
// some方法
var array = [18, 9, 10, 35, 80];
var isExist = array.some(function(value, index, array){
return value > 20;
});
console.log(isExist); // true
// map 方法
var array = [18, 9, 10, 35, 80];
array.map(item => item + 1);
console.log(array); // [19, 10, 11, 36, 81]
// filter 方法
var array = [18, 9, 10, 35, 80];
var array2 = array.filter(function(value, index, array){
return value > 20;
});
console.log(array2); // [35, 80]
// reduce方法
var array = [1, 2, 3, 4];
var s = array.reduce(function(previousValue, value, index, array){
return previousValue * value;
},1);
console.log(s); // 24
// ES6写法更加简洁
array.reduce((p, v) => p * v); // 24
// reduceRight方法 (和reduce的区别就是从后往前累计)
var array = [1, 2, 3, 4];
array.reduceRight((p, v) => p * v); // 24
// entries方法
var array = ["a", "b", "c"];
var iterator = array.entries();
console.log(iterator.next().value); // [0, "a"]
console.log(iterator.next().value); // [1, "b"]
console.log(iterator.next().value); // [2, "c"]
console.log(iterator.next().value); // undefined, 迭代器处于数组末尾时, 再迭代就会返回undefined
// find & findIndex方法
var array = [1, 3, 5, 7, 8, 9, 10];
function f(value, index, array){
return value%2==0; // 返回偶数
}
function f2(value, index, array){
return value > 20; // 返回大于20的数
}
console.log(array.find(f)); // 8
console.log(array.find(f2)); // undefined
console.log(array.findIndex(f)); // 4
console.log(array.findIndex(f2)); // -1
// keys方法
[...Array(10).keys()]; // [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
[...new Array(10).keys()]; // [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
// values方法
var array = ["abc", "xyz"];
var iterator = array.values();
console.log(iterator.next().value);//abc
console.log(iterator.next().value);//xyz