Seasons123 / blog-FE

web前端相关issue is my blog :lollipop:
2 stars 0 forks source link

《Object-Oriented JavaScript》—— 4.2.2 Array #11

Open Seasons123 opened 7 years ago

Seasons123 commented 7 years ago

4.2.2 Array

数组是一种数据存储形式,数组能存储任何类型的数据,包括另一个数组 1.创建和使用 Array()是一个用来构建数组的内建构造器函数

//例1:
var a = new Array( ) ;

//这与下面的数组文本标识法是等效的:
var a = [ ];
//例2:
var a = new Array( 1, 2, 3, 'four' );
//例3:删除特定的元素,用delete操作符
var a=[1, 2, 3];
deleta a[1];    //true
  1. 数组实际上是一个对象,继承了object所有的方法和属性(如toString、valueOf方法)。 typeof [1, 2, 3]; //"object"
    
    var a = [1, 2, 3];
    a.toString( );        // "1,2,3"  该方法已经重写了,Object的toString方法返回的是 对象的描述字符串
    a.valueOf();         //[1, 2, 3]
3.尽管数组也是一种对象,但还是有一些特殊之处:

数组的属性名是从0开始递增,并自动生成数值; 数组拥有一个用于记录元素数量的length属性; //一个数组的length属性最常见的用法是遍历数组的元素 数组在父级对象的基础上扩展了更多额外的内建方法;

**4.一些数组方法**
**(1)sort()方法用于对数组的元素进行排序。**
        语法:  ` arrayObject.sort(sortby)             sortby:可选。规定排序顺序。必须是函数。`
        返回值: `对数组的引用。请注意,数组在原数组上进行排序,不生成副本。`
        说明:

如果调用该方法时没有使用参数,将按字母顺序对数组中的元素进行排序,说得更精确点,是按照字符编 码的顺序进行排序。要实现这一点,首先应把数组的元素都转换成字符串(如有必要),以便进行比较。 如果想按照其他标准进行排序,就需要提供比较函数,该函数要比较两个值,然后返回一个用于说明这两 个值的相对顺序的数字。比较函数应该具有两个参数 a 和 b,其返回值如下: 若 a 小于 b,在排序后的数组中 a 应该出现在 b 之前,则返回一个小于 0 的值。 若 a 等于 b,则返回 0。 若 a 大于 b,则返回一个大于 0 的值。

例1:在本例中,我们将创建一个数组,并按字母顺序进行排序:

//输出: 10,5,40,25,1000,1 1,10,1000,25,40,5


例2:请注意,上面的代码没有按照数值的大小对数字进行排序,要实现这一点,就必须使用一个排序函数:

//输出: 10,5,40,25,1000,1 1,5,10,25,40,1000

该方法的内部实现原理是[插入排序](https://github.com/Seasons123/blog-FE/issues/63)

**(2)join() 方法用于把数组中的所有元素放入一个字符串,元素是通过指定的分隔符进行分隔的。**
语法: `arrayObject.join(separator)`
参数separator:`可选。指定要使用的分隔符。如果省略该参数,则使用逗号作为分隔符。`
返回值:

返回一个字符串。该字符串是通过把 arrayObject 的每个元素转换为字符串,然后把这些字符串 连接起来,在两个元素之间插入 separator 字符串而生成的。

例1:创建一个数组,然后把它的所有元素放入一个字符串:

//输出: George,John,Thomas


例2:使用分隔符来分隔数组中的元素

//输出: George.John.Thomas

Seasons123 commented 7 years ago

(3)slice() 方法可从已有的数组中返回选定的元素 该方法并不会修改数组,而是返回一个子数组。如果想删除数组中的一段元素,应该使用方法 Array.splice()。 语法:arrayObject.slice(start,end) 参数:

start   必需。规定从何处开始选取。如果是负数,那么它规定从数组尾部开始算起的位置。也就是说,-1 
指最后一个元素,-2 指倒数第二个元素,以此类推。
end 可选。规定从何处结束选取。该参数是数组片断结束处的数组下标。如果没有指定该参数,那么切分
的数组包含从 start 到数组结束的所有元素。如果这个参数是负数,那么它规定的是从数组尾部开始算起的元素。

返回值:返回一个新的数组,包含从 start 到 end (不包括该元素)的 arrayObject 中的元素。

例1:创建一个新数组,然后显示从其中选取的元素:

<script type="text/javascript">
var arr = new Array(3)
arr[0] = "George"
arr[1] = "John"
arr[2] = "Thomas"

document.write(arr + "<br />")
document.write(arr.slice(1) + "<br />")
document.write(arr)
</script>

//输出:
George,John,Thomas
John,Thomas
George,John,Thomas

例2:

<script type="text/javascript">
var arr = new Array(6)
arr[0] = "George"
arr[1] = "John"
arr[2] = "Thomas"
arr[3] = "James"
arr[4] = "Adrew"
arr[5] = "Martin"

document.write(arr + "<br />")
document.write(arr.slice(2,4) + "<br />")
document.write(arr)
</script>

//输出:
George,John,Thomas,James,Adrew,Martin
Thomas,James
George,John,Thomas,James,Adrew,Martin
Seasons123 commented 7 years ago

(4)splice() 方法从数组中添加/删除项目,然后返回被删除的项目。 注释:该方法会改变原始数组。 语法:arrayObject.splice(index,howmany,item1,.....,itemX) 参数:

index   必需。整数,规定添加/删除项目的位置,使用负数可从数组结尾处规定位置。
howmany 必需。要删除的项目数量。如果设置为 0,则不会删除项目。
item1, ..., itemX   可选。向数组添加的新项目。

返回值:Array 包含被删除项目的新数组,如果有的话。 说明:

splice() 方法可删除从 index 处开始的零个或多个元素,并且用参数列表中声明的一个或多个值来替换那
些被删除的元素。
如果从 arrayObject 中删除了元素,则返回的是含有被删除的元素的数组。注意,splice() 方法与 slice() 方
法的作用是不同的,splice() 方法会直接对数组进行修改。

例1:创建一个新数组,并向其添加一个元素:

<script type="text/javascript">
var arr = new Array(6)
arr[0] = "George"
arr[1] = "John"
arr[2] = "Thomas"
arr[3] = "James"
arr[4] = "Adrew"
arr[5] = "Martin"

document.write(arr + "<br />")
arr.splice(2,0,"William")
document.write(arr + "<br />")
</script>

//输出:
George,John,Thomas,James,Adrew,Martin
George,John,William,Thomas,James,Adrew,Martin

例2:将删除位于 index 2 的元素,并添加一个新元素来替代被删除的元素:

<script type="text/javascript">
var arr = new Array(6)
arr[0] = "George"
arr[1] = "John"
arr[2] = "Thomas"
arr[3] = "James"
arr[4] = "Adrew"
arr[5] = "Martin"

document.write(arr + "<br />")
arr.splice(2,1,"William")
document.write(arr)
</script>

//输出:
George,John,Thomas,James,Adrew,Martin
George,John,William,James,Adrew,Martin

例3:删除从 index 2 ("Thomas") 开始的三个元素,并添加一个新元素 ("William") 来替代被删除的元素:

<script type="text/javascript">
var arr = new Array(6)
arr[0] = "George"
arr[1] = "John"
arr[2] = "Thomas"
arr[3] = "James"
arr[4] = "Adrew"
arr[5] = "Martin"

document.write(arr + "<br />")
arr.splice(2,3,"William")
document.write(arr)
</script>

//输出:
George,John,Thomas,James,Adrew,Martin
George,John,William,Martin
Seasons123 commented 7 years ago

(5)push( )和pop( ) push( )方法会在数组的末端添加一个新元素,而pop( )方法则会移除最后一个元素, 也就是说a.push("new")就相当于a[a.length]="new" ,而a.pop( )则与a.length--的结果相同。 另外,push( )返回的是改变后的数组长度,而pop所返回的是被移除的元素。 例:

var a=[1, 2, 3];
a.push("new");          //6
a;         //[1, 2, 3, "new"]
a.pop( );          //"new"
a;         //[1, 2, 3]
Seasons123 commented 7 years ago

(6)Array.isArray(obj) Return value:true if the object is an Array; otherwise, false. Description:If the object is an Array, true is returned, otherwise false is. Example:

Array.isArray([1]);  //true
Array.isArray({ });   //false
Seasons123 commented 6 years ago

(7)concat() 方法用于连接两个或多个数组。 该方法不会改变现有的数组,而仅仅会返回被连接数组的一个副本。 语法: arrayObject.concat(arrayX,arrayX,......,arrayX) 返回值:返回一个新的数组。该数组是通过把所有 arrayX 参数添加到 arrayObject 中生成的。如果要进行 concat() 操作的参数是数组,那么添加的是数组中的元素,而不是数组。

在本例中,我们创建了两个数组,然后使用 concat() 把它们连接起来:

<script type="text/javascript">

var arr = new Array(3)
arr[0] = "George"
arr[1] = "John"
arr[2] = "Thomas"

var arr2 = new Array(3)
arr2[0] = "James"
arr2[1] = "Adrew"
arr2[2] = "Martin"

document.write(arr.concat(arr2))

</script>

输出: George,John,Thomas,James,Adrew,Martin

Seasons123 commented 6 years ago

(8)shift() 把数组的第一个元素删除,若空数组,不进行任何操作,返回undefined 改变原数组 返回第一个元素的值 (9) unshift() 向数组的开头添加一个或多个元素 改变原数组 返回新数组的长度

Seasons123 commented 6 years ago

Array对象常用方法小结(注意返回值、是否改变原数组): 1、 concat() 连接两个或多个数组 不改变原数组 返回被连接数组的一个副本 2、join() 把数组中所有元素放入一个字符串 不改变原数组 返回字符串 3、 slice() 从已有的数组中返回选定的元素 不改变原数组 返回一个新数组 4、 toString() 把数组转为字符串 不改变原数组 返回数组的字符串形式 改变原数组:

5、 pop() 删除数组最后一个元素,如果数组为空,则不改变数组,返回undefined 改变原数组 返回被删除的元素 6、 push() 向数组末尾添加一个或多个元素 改变原数组 返回新数组的长度 7、 reverse() 颠倒数组中元素的顺序 改变原数组 返回该数组 8、 shift() 把数组的第一个元素删除,若空数组,不进行任何操作,返回undefined 改变原数组 返回第一个元素的值 9、 sort() 对数组元素进行排序(ascii) 改变原数组 返回该数组 10、 splice() 从数组中添加/删除项目 改变原数组 返回被删除的元素 11、 unshift() 向数组的开头添加一个或多个元素 改变原数组 返回新数组的长度

Seasons123 commented 4 years ago

12.reduce() 的用法 1、语法

arr.reduce(function(prev,cur,index,arr){
...
}, init);

其中,

arr 表示原数组;
prev 表示上一次调用回调时的返回值,或者初始值 init;
cur 表示当前正在处理的数组元素;
index 表示当前正在处理的数组元素的索引,若提供 init 值,则索引为0,否则索引为1;
init 表示初始值。

看上去是不是感觉很复杂?没关系,只是看起来而已,其实常用的参数只有两个:prev 和 cur。接下来我们跟着实例来看看具体用法吧~

2、实例 先提供一个原始数组: var arr = [3,9,4,3,6,0,9]; 实现以下需求的方式有很多,其中就包含使用reduce()的求解方式,也算是实现起来比较简洁的一种吧。 1. 求数组项之和

var sum = arr.reduce(function (prev, cur) {
    return prev + cur;
},0);

由于传入了初始值0,所以开始时prev的值为0,cur的值为数组第一项3,相加之后返回值为3作为下一轮回调的prev值,然后再继续与下一个数组项相加,以此类推,直至完成所有数组项的和并返回。

2. 求数组项最大值

var max = arr.reduce(function (prev, cur) {
    return Math.max(prev,cur);
});

由于未传入初始值,所以开始时prev的值为数组第一项3,cur的值为数组第二项9,取两值最大值后继续进入下一轮回调。

3. 数组去重

var newArr = arr.reduce(function (prev, cur) {
    prev.indexOf(cur) === -1 && prev.push(cur);
    return prev;
},[]);

实现的基本原理如下:

① 初始化一个空数组
② 将需要去重处理的数组中的第1项在初始化数组中查找,如果找不到(空数组中肯定找不到),就将该项添加到初始化数组中
③ 将需要去重处理的数组中的第2项在初始化数组中查找,如果找不到,就将该项继续添加到初始化数组中
④ ……
⑤ 将需要去重处理的数组中的第n项在初始化数组中查找,如果找不到,就将该项继续添加到初始化数组中
⑥ 将这个初始化数组返回

3、其他相关方法

  1. reduceRight() 该方法用法与reduce()其实是相同的,只是遍历的顺序相反,它是从数组的最后一项开始,向前遍历到第一项。
  2. forEach()、map()、every()、some()和filter() 详情请戳→简述forEach()、map()、every()、some()和filter()的用法 重点总结: reduce() 是数组的归并方法,与forEach()、map()、filter()等迭代方法一样都会对数组每一项进行遍历,但是reduce() 可同时将前面数组项遍历产生的结果与当前遍历项进行运算,这一点是其他迭代方法无法企及的
Seasons123 commented 4 years ago

13.简述forEach()、map()、every()、some()和filter()的用法 在文章开头,先问大家一个问题: 在Javascript中,如何处理数组中的每一项数据? 有人可能会说,这还不简单,直接一个for循环遍历一下就好了。 是的,确实,这是最常见的做法。 但是,除此之外,ES5还提供了处理数组更加方便的方法,如题。 接下来,我将通过几个简单的实例来具体讲解这几个方法。

1、forEach(),用于遍历数组,无返回值 这里先给出一个数组(以下例子通用): var arr = [1,-2,3,4,-5]; 然后我要做事情的就是,将数组中的每一项翻倍。

arr.forEach(function(item,index,array){
    array[index] = item * 2;
});
console.log(arr);   // [2,-4,6,8,-10]

可以看到,forEach()可以传入一个匿名函数作为参数,而该匿名函数有含有三个参数,其依次代表数组遍历时的当前元素item,数组遍历时的当前元素的索引index,以及正在遍历的数组array。有了这三个参数,可以方便我们做很多事情,比如说示例当中将每一项数组元素翻倍,这时需要用到第一个参数item。但是,仅仅只是将item乘以2可不行,我们还得将其赋值给原来的数组,这时我们就得用到后面两个参数index和array。 根据上述可知,array[index]是全等于item的。

arr.forEach(function(item,index,array){
    console.log(array[index] === item);   // true
});

2、map(),用于遍历数组,返回处理之后的新数组

var newArr = arr.map(function(item,index,array){
    return item * 2;
});
console.log(newArr);   // [2,-4,6,8,-10]

可以看到,该方法与forEach()的功能类似,只不过map()具有返回值,会返回一个新的数组,这样处理数组后也不会影响到原有数组。 3、every(),用于判断数组中的每一项元素是否都满足条件,返回一个布尔值

var isEvery = arr.every(function(item,index,array){
    return item > 0;
});
console.log(isEvery);   // false

可以看到,示例中是要判断数组arr中的元素是否都为正数,很显然不是,所以该方法最终返回false。 4、some(),用于判断数组中的是否存在满足条件的元素,返回一个布尔值

var isSome = arr.some(function(item,index,array){
    return item < 0;
});
console.log(isSome);   // true

可以看到,该方法与every()类似,示例中是要判断数组arr中是否存在负数元素,很显然存在,所以该方法最终返回true。 5、filter(),用于筛选数组中满足条件的元素,返回一个筛选后的新数组

var minus = arr.filter(function(item,index,array){
    return item < 0;
});
console.log(minus);   // [-2, -5]

可以看到,示例中是要筛选出数组arr中的所有负数,所以该方法最终返回一个筛选后的新数组[-2, -5]。 补充: 以上五大方法除了传递一个匿名函数作为参数之外,还可以传第二个参数,该参数用于指定匿名函数内的this指向,例如:

// 只传一个匿名函数
arr.forEach(function(item,index,array){
    console.log(this);  // window
});
// 传两个参数
arr.forEach(function(item,index,array){
    console.log(this);  // [1, -2, 3, 4, -5]
},arr);

兼容性: 由于以上方法均属ES5方法,所以IE8及其以下浏览器均不兼容。 重点总结:

① forEach()无返回值,map()和filter()返回新数组,every()和some()返回布尔值
② 匿名函数中this指向默认为window,可通过传第二参数来更改之
③ 五种遍历方法均为ES5方法
Seasons123 commented 4 years ago

14、面试官连环追问:数组拍平(扁平化) flat 方法实现

Seasons123 commented 4 years ago

15.你不知道的 JSON.stringify() 的威力