数组是值的有序集合。每个值叫做一个元素,而每个元素在数组中有一个位置,以数字表示,称为索引。

Array的定义

var a = new Array();//空数组
var a  = new Array(10);//传入一个参数
//若传入参数为number类型时用于指定数组的长度;
//若传入的参数为非number类型时作为数组的元素
var names = new Array("张三", "李四", "王五");//传入多个参数作为数组的元素
var names = ["张三", "李四", "王五"];//字面量的方式

var a = new Array();//空数组
var a  = new Array(10);//传入一个参数
//若传入参数为number类型时用于指定数组的长度;
//若传入的参数为非number类型时作为数组的元素
var names = new Array("张三", "李四", "王五");//传入多个参数作为数组的元素
var names = ["张三", "李四", "王五"];//字面量的方式

Array的实例方法

所谓实例方法是Array实例化得到的实例对象调用使用的方法

继承方法

数组是一种特殊的对象,会从原型链中找到Object的toString()、toLocaleString()和valueOf()方法,便因此继承得到这三个方法

toString和toLocaleString

返回由数组中的每个元素以字符串的形式输出,toLocaleString具有同样的效果,与前者的差异主要为了处理本地化,比如一些地区的特殊语言

console.log([1,2,3].toString())  //1,2,3
 //若数组中的元素值为null或者undefined将输入空字符串
   console.log([1,2,3,null,undefined].toString())//1,2,3,,
  console.log([1,2,3].toString())  //1,2,3
 //若数组中的元素值为null或者undefined将输入空字符串
   console.log([1,2,3,null,undefined].toString())//1,2,3,,
valueOf

返回数组本身

console.log([1,2,3,undefined,undefined].valueOf())
 // [1, 2, 3, undefined, undefined]
 console.log([1,2,3,undefined,undefined].valueOf())
 // [1, 2, 3, undefined, undefined]

改变自身方法

pop

删除最后一项,并返回删除元素的值,同时数组本身发生变化

var arr=[1,2,3]
var newarr=arr.pop()
console.log(newarr) //3
console.log(arr) //[1,2]
var b=[]
var newb=b.pop()
console.log(newb) //undefined
console.log(b)  //[]
var arr=[1,2,3]
var newarr=arr.pop()
console.log(newarr) //3
console.log(arr) //[1,2]
var b=[]
var newb=b.pop()
console.log(newb) //undefined
console.log(b)  //[]
shift

删除原数组第一项,并返回删除元素的值,同时数组本身发生变化

var arr=[1,2,3]
var newarr=arr.shift()
console.log(newarr) //3
console.log(arr) //[2,3]
var b=[]
var newb=b.shift()
console.log(newb) //undefined
console.log(b)  //[]
var arr=[1,2,3]
var newarr=arr.shift()
console.log(newarr) //3
console.log(arr) //[2,3]
var b=[]
var newb=b.shift()
console.log(newb) //undefined
console.log(b)  //[]
push

往原数组最后添加一个元素

var arr = [1,2,3,4,5];
var newarr=arr.push(6)
console.log(newarr)  //6
console.log(arr)  //[1,2,3,4,5,6]
var arr = [1,2,3,4,5];
var newarr=arr.push(6)
console.log(newarr)  //6
console.log(arr)  //[1,2,3,4,5,6]
unshift

往原数组最前端添加一个元素

var arr = [1,2,3,4,5];
var newarr=arr.unshift(6)
console.log(newarr)  //6
console.log(arr)  //[6,1,2,3,4,5]
var arr = [1,2,3,4,5];
var newarr=arr.unshift(6)
console.log(newarr)  //6
console.log(arr)  //[6,1,2,3,4,5]
reverse

数组翻转,并返回翻转后的数组,数组本身跟着翻转

var arr = [1,2,3,4,5];
 var newarr=arr.reverse()
 console.log(newarr) //[5, 4, 3, 2, 1]
 console.log(arr)  //[5, 4, 3, 2, 1]
 var arr = [1,2,3,4,5];
 var newarr=arr.reverse()
 console.log(newarr) //[5, 4, 3, 2, 1]
 console.log(arr)  //[5, 4, 3, 2, 1]
sort

数组排序,并返回排序后的数组,数组本身跟着排序

默认情况下sort方法是按ascii字母顺序排序的

var arr=[111,119,12,102];
var newarr=arr.sort();
console.log(newarr)//[102, 111, 119, 12]
console.log(arr);//[102, 111, 119, 12]
var arr=[111,119,12,102];
var newarr=arr.sort();
console.log(newarr)//[102, 111, 119, 12]
console.log(arr);//[102, 111, 119, 12]

改变默认比较数字大小来排序

function compare(){
  return arguments[0]-arguments[1]
}
var arr=[102, 111, 119, 12];
arr.sort(compare);
console.log(arr); //[12, 102, 111, 119]
function compare(){
  return arguments[0]-arguments[1]
}
var arr=[102, 111, 119, 12];
arr.sort(compare);
console.log(arr); //[12, 102, 111, 119]
splice

剪接数组,返回剪接后的元素数组,可以实现shiftpop,unshift,push一样的效果

参数为0个

var arr=[111,119,12,102];
var newarr=arr.splice();
console.log(newarr)//[]
console.log(arr);//[111,119,12,102]
var arr=[111,119,12,102];
var newarr=arr.splice();
console.log(newarr)//[]
console.log(arr);//[111,119,12,102]

参数为1个一个参数表示从索引为几的位置开始截取,长度默认数组长度

var arr=[111,119,12,102];
var newarr=arr.splice(0); //从索引为0的位置开始截取,长度默认数组长度
console.log(newarr)//[111, 119, 12, 102]
console.log(arr);//[]
var arr1=[111,119,12,102];
var newarr1=arr1.splice(3);从索引为3的位置开始截取,长度默认数组长度
console.log(newarr1)//[102]
console.log(arr1);//[111, 119, 12]
var arr=[111,119,12,102];
var newarr=arr.splice(0); //从索引为0的位置开始截取,长度默认数组长度
console.log(newarr)//[111, 119, 12, 102]
console.log(arr);//[]
var arr1=[111,119,12,102];
var newarr1=arr1.splice(3);从索引为3的位置开始截取,长度默认数组长度
console.log(newarr1)//[102]
console.log(arr1);//[111, 119, 12]

参数是2个第一个参数表示从索引为几的位置开始截取,第二是长度

var arr=[111,119,12,102,333];
var newarr=arr.splice(0,2);
console.log(newarr)//[111, 119]
console.log(arr);//[12, 102, 333]
var arr1=[111,119,12,102,333];
var newarr1=arr1.splice(3,1);
console.log(newarr1)//[102]
console.log(arr1);//[111, 119, 12,333]
var arr=[111,119,12,102,333];
var newarr=arr.splice(0,2);
console.log(newarr)//[111, 119]
console.log(arr);//[12, 102, 333]
var arr1=[111,119,12,102,333];
var newarr1=arr1.splice(3,1);
console.log(newarr1)//[102]
console.log(arr1);//[111, 119, 12,333]

参数大于2个splice(start,deleteLength,val1,val2,...)从start位置开始删除deleteLength项,并从该位置起插入val1,val2,...

var arr = ['a','b','c','d','e'];
var newarr=arr.splice(3,1,1,2,3,4,5)
console.log(newarr)//["d"]
console.log(arr)//["a", "b", "c", 1, 2, 3, 4, 5, "e"]
var arr = ['a','b','c','d','e'];
var newarr=arr.splice(3,1,1,2,3,4,5)
console.log(newarr)//["d"]
console.log(arr)//["a", "b", "c", 1, 2, 3, 4, 5, "e"]

同shift

var arr = ['a','b','c','d','e'];
 var newarr=arr.splice(0,1);
 console.log(newarr)//["a"]
 console.log(arr)//["b", "c", "d", "e"]
 var arr = ['a','b','c','d','e'];
 var newarr=arr.splice(0,1);
 console.log(newarr)//["a"]
 console.log(arr)//["b", "c", "d", "e"]

同pop

var arr = ['a','b','c','d','e'];
 var newarr=arr.splice(arr.length-1,1);
 console.log(newarr)//["e"]
 console.log(arr)//["a", "b", "c", "d"]
 var arr = ['a','b','c','d','e'];
 var newarr=arr.splice(arr.length-1,1);
 console.log(newarr)//["e"]
 console.log(arr)//["a", "b", "c", "d"]

同push

var arr = ['a','b','c','d','e'];
 var newarr= arr.splice(arr.length,9999999,'f')
 console.log(newarr)//[]
 console.log(arr)//["a", "b", "c", "d", "e", "f"]
 var arr1 = ['a','b','c','d','e'];
 var newarr1= arr1.splice(arr1.length,0,'f')
 console.log(newarr1)//[]
 console.log(arr1)//["a", "b", "c", "d", "e", "f"]
 var arr = ['a','b','c','d','e'];
 var newarr= arr.splice(arr.length,9999999,'f')
 console.log(newarr)//[]
 console.log(arr)//["a", "b", "c", "d", "e", "f"]
 var arr1 = ['a','b','c','d','e'];
 var newarr1= arr1.splice(arr1.length,0,'f')
 console.log(newarr1)//[]
 console.log(arr1)//["a", "b", "c", "d", "e", "f"]

同unshift

var arr = ['a','b','c','d','e'];
 var newarr= arr.splice(0,0,'f')
 console.log(newarr)//[]
 console.log(arr)//["f", "a", "b", "c", "d", "e"]
 var arr = ['a','b','c','d','e'];
 var newarr= arr.splice(0,0,'f')
 console.log(newarr)//[]
 console.log(arr)//["f", "a", "b", "c", "d", "e"]

迭代方法

filter

对数组中的每一个元素调用指定的过滤函数,并将返回值为true的元素集合组成新的数组。

var arr=[1,2,3,'a','b','c',4,5]
var newarr=arr.filter(function(value,index,array){
  return typeof(value)=='number'
})
console.log(arr)//[1, 2, 3, "a", "b", "c", 4, 5]
console.log(newarr)//[1, 2, 3, 4, 5]
var arr=[1,2,3,'a','b','c',4,5]
var newarr=arr.filter(function(value,index,array){
  return typeof(value)=='number'
})
console.log(arr)//[1, 2, 3, "a", "b", "c", 4, 5]
console.log(newarr)//[1, 2, 3, 4, 5]
forEach

用来遍历数组中的每一个元素

var arr=[1,2,3,'a','b','c']
arr.forEach(function(value,index,array){
  console.log(value)
})
//1
//2
//3
//a
//b
//c
var arr=[1,2,3,'a','b','c']
arr.forEach(function(value,index,array){
  console.log(value)
})
//1
//2
//3
//a
//b
//c
every

数组中每一个元素都满足参数中提供测试函数,则返回真。

var arr=[2,3,-1];
var arrboolean=arr.every(function(value,index,array){
         return value>0
})
console.log(arrboolean) //false
var bb=[2,3,1];
var bbboolean=bb.every(function(value,index,array){
   return value>0
})
console.log(bbboolean) //true
var arr=[2,3,-1];
var arrboolean=arr.every(function(value,index,array){
         return value>0
})
console.log(arrboolean) //false
var bb=[2,3,1];
var bbboolean=bb.every(function(value,index,array){
   return value>0
})
console.log(bbboolean) //true
some

数组中至少有一个元素参数中提供测试函数,则返回真。

var arr=[2,3,-1];
var arrboolean=arr.some(function(value,index,array){
         return value>0
})
console.log(arrboolean) //true
var arr=[2,3,-1];
var arrboolean=arr.some(function(value,index,array){
         return value>0
})
console.log(arrboolean) //true
map

数组中所有的元素依次调用一个函数,根据函数结果返回一个新数组。

var arr = [1, 2, 3];
var newarr=arr.map(function (n) {
  return n + 1;
});

console.log(newarr) // [2, 3, 4]
console.log(arr) // [1, 2, 3]

var arr = [1, 2, 3];
var newarr=arr.map(function (n) {
  return n + 1;
});

console.log(newarr) // [2, 3, 4]
console.log(arr) // [1, 2, 3]

查找元素

indexOf

返回数组中第一个元素索引(第一个参数需检索的字符串值,第二个参数可选的整数参数。
规定在字符串中开始检索的位置。它的合法取值是 0 到 数组的length - 1。
如省略该参数,则将从字符串的首字符开始检索。)

var arr=[1,'a',5,'a',7,'a',9]
console.log(arr.indexOf('a')) //1
console.log(arr.indexOf('a',2))//3
var arr=[1,'a',5,'a',7,'a',9]
console.log(arr.indexOf('a')) //1
console.log(arr.indexOf('a',2))//3
lastIndexOf

返回一个指定的字符串值最后出现的位置,在一个字符串中的指定位置从后向前搜索
(第一个参数需检索的字符串值,第二个参数可选的整数参数。
规定在字符串中开始检索的位置。它的合法取值是 0 到 数组的length - 1。
如省略该参数,则将从字符串的最后一个字符处开始检索。)

var arr=[1,'a',5,'a',7,'a',9]
console.log(arr.lastIndexOf('a')) //5
console.log(arr.lastIndexOf('a',2))//3
var arr=[1,'a',5,'a',7,'a',9]
console.log(arr.lastIndexOf('a')) //5
console.log(arr.lastIndexOf('a',2))//3

归并方法

join

将数组转成字符串

var arr = [1,2,3,4,5];
var newarr=arr.join('||');
console.log(newarr) //"1||2||3||4||5"

var arr = [1,2,3,4,5];
var newarr=arr.join('||');
console.log(newarr) //"1||2||3||4||5"
concat

返回一个包含原数组元素和其他元素新的组合数组
传递参数

var arr = [1,2,3];
var arr1 = ['a','b','c'];
var newarr=arr.concat(arr1)
console.log(newarr)//[1, 2, 3, "a", "b", "c"]
var arr = [1,2,3];
var arr1 = ['a','b','c'];
var newarr=arr.concat(arr1)
console.log(newarr)//[1, 2, 3, "a", "b", "c"]

不传递参数 复制当前的数组

var arr = [1,2,3];
var newarr=arr.concat()
console.log(newarr)//[1, 2, 3]
var arr = [1,2,3];
var newarr=arr.concat()
console.log(newarr)//[1, 2, 3]
reduce

从左向右,使用指定函数聚集数组的每个元素

var values = [1,2,3,4,5];
var i = 0;
var sum = values.reduce(function (sum, current, index, array) {
  console.log('和:',sum, '当前值',current,'计算次数:',++i,'索引:',index);
  return sum + current;
});
console.log(sum);
/* 结果
 和:1   当前值 2  计算次数: 1  索引: 1
 和:3   当前值 3  计算次数: 2  索引: 2
 和:6   当前值 4  计算次数: 3  索引: 3
 和:10  当前值 5  计算次数: 4  索引: 4
 15
 */
var values = [1,2,3,4,5];
var i = 0;
var sum = values.reduce(function (sum, current, index, array) {
  console.log('和:',sum, '当前值',current,'计算次数:',++i,'索引:',index);
  return sum + current;
});
console.log(sum);
/* 结果
 和:1   当前值 2  计算次数: 1  索引: 1
 和:3   当前值 3  计算次数: 2  索引: 2
 和:6   当前值 4  计算次数: 3  索引: 3
 和:10  当前值 5  计算次数: 4  索引: 4
 15
 */

数组的扁平化

var matrix = [
      [1, 2],
      [3, 4],
      [5, 6]
    ];
    var flatten = matrix.reduce(function (previous, current) {
      console.log(previous);//2次循环  [1, 2] [1, 2, 3, 4]
      return previous.concat(current);
    });
    console.log(flatten);//[1, 2, 3, 4, 5, 6]
var matrix = [
      [1, 2],
      [3, 4],
      [5, 6]
    ];
    var flatten = matrix.reduce(function (previous, current) {
      console.log(previous);//2次循环  [1, 2] [1, 2, 3, 4]
      return previous.concat(current);
    });
    console.log(flatten);//[1, 2, 3, 4, 5, 6]
reduceRight

从右向左,使用指定函数聚集数组的每个元素

var values = [1,2,3,4,5];
var i = 0;
var sum = values.reduceRight(function (sum, current, index, array) {
  console.log('和:',sum, '当前值',current,'计算次数:',++i,'索引:',index);
  return sum + current;
});
console.log(sum);
/* 结果
 和:5  当前值 4  计算次数: 1  索引:  3
 和:9   当前值 3  计算次数: 2  索引: 2
 和:12   当前值 2  计算次数: 3  索引: 1
 和:14  当前值 1  计算次数: 4  索引: 0
 15
 */
var values = [1,2,3,4,5];
var i = 0;
var sum = values.reduceRight(function (sum, current, index, array) {
  console.log('和:',sum, '当前值',current,'计算次数:',++i,'索引:',index);
  return sum + current;
});
console.log(sum);
/* 结果
 和:5  当前值 4  计算次数: 1  索引:  3
 和:9   当前值 3  计算次数: 2  索引: 2
 和:12   当前值 2  计算次数: 3  索引: 1
 和:14  当前值 1  计算次数: 4  索引: 0
 15
 */
slice

截取(切片)数组,返回截取的数组,原数组不变

参数为0个

var arr=[111,119,12,102];
var newarr=arr.slice();arr.slice()等价于arr.slice(0)
console.log(newarr)//[111, 119, 12, 102]
console.log(arr);//[111,119,12,102] //新数组和老数组一样,但引用不一样
newarr.push(67)//给新数组增加元素并不影响原数组
console.log(newarr)//[111, 119, 12, 102,67]
console.log(arr);//[111,119,12,102]
var arr=[111,119,12,102];
var newarr=arr.slice();arr.slice()等价于arr.slice(0)
console.log(newarr)//[111, 119, 12, 102]
console.log(arr);//[111,119,12,102] //新数组和老数组一样,但引用不一样
newarr.push(67)//给新数组增加元素并不影响原数组
console.log(newarr)//[111, 119, 12, 102,67]
console.log(arr);//[111,119,12,102]

参数为1个一个参数表示从索引为几的位置开始截取,长度默认数组长度

var arr=[111,119,12,102];
var newarr=arr.splice(0); //从索引为0的位置开始截取,长度默认数组长度
console.log(newarr)//[111, 119, 12, 102]
console.log(arr);//[111,119,12,102]
var arr1=[111,119,12,102];
var newarr1=arr1.slice(3);从索引为3的位置开始截取,长度默认数组长度
console.log(newarr1)//[102]
console.log(arr1);//[111, 119, 12,102]
var arr=[111,119,12,102];
var newarr=arr.splice(0); //从索引为0的位置开始截取,长度默认数组长度
console.log(newarr)//[111, 119, 12, 102]
console.log(arr);//[111,119,12,102]
var arr1=[111,119,12,102];
var newarr1=arr1.slice(3);从索引为3的位置开始截取,长度默认数组长度
console.log(newarr1)//[102]
console.log(arr1);//[111, 119, 12,102]

参数是2个第一个参数表示从索引为几的位置开始截取,第二参数是结束位置

var arr=[111,119,12,102,333];
var newarr=arr.splice(0,2);
console.log(newarr)//[111, 119]
console.log(arr);//[111,119,12,102,333]
var arr=[111,119,12,102,333];
var newarr=arr.slice(3,2);//若第二个参数<=第一个参数,返回空数组
console.log(newarr)//[]
console.log(arr);//[111,119,12,102,333]
var arr=[111,119,12,102,333];
var newarr=arr.slice(3,3);
console.log(newarr)//[]
console.log(arr);//[111,119,12,102,333]
var arr=[111,119,12,102,333];
var newarr=arr.splice(0,2);
console.log(newarr)//[111, 119]
console.log(arr);//[111,119,12,102,333]
var arr=[111,119,12,102,333];
var newarr=arr.slice(3,2);//若第二个参数<=第一个参数,返回空数组
console.log(newarr)//[]
console.log(arr);//[111,119,12,102,333]
var arr=[111,119,12,102,333];
var newarr=arr.slice(3,3);
console.log(newarr)//[]
console.log(arr);//[111,119,12,102,333]

参数是负数从右面最后一个元素开始计算的,右面的第一个为0,往前--

var arr = ['a','b','c','d','e'];
var newarr=arr.slice(-3,-1)
console.log(newarr)//["c", "d"]
console.log(arr)//['a','b','c','d','e']
var arr = ['a','b','c','d','e'];
var newarr=arr.slice(-3,-1)
console.log(newarr)//["c", "d"]
console.log(arr)//['a','b','c','d','e']

常使用的功能:类数组对象转化为数组

var arr=[].slice.call({0:"aa",1:"bbb",2:"ccc",length:3})
  console.log(arr)//["aa", "bbb", "ccc"]
  var arr=[].slice.call({0:"aa",1:"bbb",2:"ccc",length:3})
  console.log(arr)//["aa", "bbb", "ccc"]

ES6新方法

copyWithin

将指定位置的成员复制到其他位置替换原理的元素,然后返回当前数组,原数组跟着变化

  • target(必需):从该位置开始替换数据。
  • start(可选):从该位置开始读取数据,默认为 0。如果为负值,从右向左。
  • end(可选):到该位置前停止读取数据,默认等于数组长度。如果为负值,从右向左。

参数为0个

var arr=[111,119,12,102];
var newarr=arr.copyWithin();//arr.slice()等价于arr.slice(0)
console.log(newarr) //[111, 119, 12, 102]
console.log(arr); //[111, 119, 12, 102] 新数组和老数组一样,连引用都一样
newarr.push(67) //因此往新数组增加一个元素,原数组也会跟着变化
console.log(newarr) //[111, 119, 12, 102, 67]
console.log(arr);   //[111, 119, 12, 102, 67]
var arr=[111,119,12,102];
var newarr=arr.copyWithin();//arr.slice()等价于arr.slice(0)
console.log(newarr) //[111, 119, 12, 102]
console.log(arr); //[111, 119, 12, 102] 新数组和老数组一样,连引用都一样
newarr.push(67) //因此往新数组增加一个元素,原数组也会跟着变化
console.log(newarr) //[111, 119, 12, 102, 67]
console.log(arr);   //[111, 119, 12, 102, 67]

参数为1个一个参数表示从索引为几的位置开始替换

var arr=[111,119,12,102];
var newarr=arr.copyWithin(1);
console.log(newarr) //[111, 111, 119, 12]
console.log(arr); //[111, 111, 119, 12]
var arr=[111,119,12,102];
var newarr=arr.copyWithin(3);
console.log(newarr) //[111, 111, 12, 111]
console.log(arr); //[111, 111, 12, 111]
var arr=[111,119,12,102];
var newarr=arr.copyWithin(1);
console.log(newarr) //[111, 111, 119, 12]
console.log(arr); //[111, 111, 119, 12]
var arr=[111,119,12,102];
var newarr=arr.copyWithin(3);
console.log(newarr) //[111, 111, 12, 111]
console.log(arr); //[111, 111, 12, 111]

参数是2个第一个参数表示从索引为几的位置开始替换,第二参数是从该位置开始读取数据

var arr=[111,119,12,102,333];
var newarr=arr.copyWithin(0,2);
console.log(newarr)//[12, 102, 333, 102, 333]
console.log(arr);//[12, 102, 333, 102, 333]
var arr=[111,119,12,102,333];
var newarr=arr.copyWithin(3,2);
console.log(newarr)//[111, 119, 12, 12, 102]
console.log(arr);//[111, 119, 12, 12, 102]
var arr=[111,119,12,102,333];
var newarr=arr.copyWithin(0,2);
console.log(newarr)//[12, 102, 333, 102, 333]
console.log(arr);//[12, 102, 333, 102, 333]
var arr=[111,119,12,102,333];
var newarr=arr.copyWithin(3,2);
console.log(newarr)//[111, 119, 12, 12, 102]
console.log(arr);//[111, 119, 12, 12, 102]

参数是3个第一个参数表示从索引为几的位置开始替换,第二参数是从该位置开始读取数据,第三个参数是读取数据结束位置

var arr=[111,119,12,102,333];
var newarr=arr.copyWithin(0,2,3);
console.log(newarr)//[12, 119, 12, 102, 333]
console.log(arr);//[12, 119, 12, 102, 333]
var arr=[111,119,12,102,333];
var newarr=arr.copyWithin(0,2,2);//若第三个参数<=第二个参数,返回原数组
console.log(newarr)//[111,119,12,102,333]
console.log(arr);//[111,119,12,102,333]
var arr=[111,119,12,102,333];
var newarr=arr.copyWithin(0,2,1);
console.log(newarr)//[111,119,12,102,333]
console.log(arr);//[111,119,12,102,333]
var arr=[111,119,12,102,333];
var newarr=arr.copyWithin(0,2,3);
console.log(newarr)//[12, 119, 12, 102, 333]
console.log(arr);//[12, 119, 12, 102, 333]
var arr=[111,119,12,102,333];
var newarr=arr.copyWithin(0,2,2);//若第三个参数<=第二个参数,返回原数组
console.log(newarr)//[111,119,12,102,333]
console.log(arr);//[111,119,12,102,333]
var arr=[111,119,12,102,333];
var newarr=arr.copyWithin(0,2,1);
console.log(newarr)//[111,119,12,102,333]
console.log(arr);//[111,119,12,102,333]

第二三参数是负数从右面最后一个元素开始计算的,右面的第一个为0,往前--

var arr=[111,119,12,102,333];
var newarr=arr.copyWithin(0,-4,-2);
console.log(newarr)//[119, 12, 12, 102, 333]
console.log(arr);//[119, 12, 12, 102, 333]
var arr=[111,119,12,102,333];
var newarr=arr.copyWithin(0,-4,-2);
console.log(newarr)//[119, 12, 12, 102, 333]
console.log(arr);//[119, 12, 12, 102, 333]
find()

用于找出第一个符合条件的元素。
它的参数是一个回调函数,所有元素依次执行该回调函数,直到找出第一个返回值为true的元素,
然后返回该元素。如果没有符合条件的元素,则返回undefined

  • function(currentValue, index,arr)(必需)-函数参数: currentValue必需。当前元素 index可选。当前元素的索引 arr 可选。当前元素所属的数组对象。
  • thisValue(可选):传递给函数的值一般用 "this" 值。如果这个参数为空, "undefined" 会传递给 "this" 值
var arr=[111,119,12,102,333];
var newarr=arr.find(function(value, index, arr) {
  return value <100;
})
console.log(newarr) //12
console.log(arr)  //[111, 119, 12, 102, 333]
var arr=[111,119,112,102,333];
var newarr=arr.find(function(value, index, arr) {
  return value <100;
})
console.log(newarr) //undefined
console.log(arr)  //[111, 119, 112, 102, 333]

var arr=[111,119,12,102,333];
var newarr=arr.find(function(value, index, arr) {
  return value <100;
})
console.log(newarr) //12
console.log(arr)  //[111, 119, 12, 102, 333]
var arr=[111,119,112,102,333];
var newarr=arr.find(function(value, index, arr) {
  return value <100;
})
console.log(newarr) //undefined
console.log(arr)  //[111, 119, 112, 102, 333]
findIndex

返回第一个符合条件的数组元素的索引
它的参数是一个回调函数,所有元素依次执行该回调函数,直到找出第一个返回值为true的元素的索引
如果没有符合条件的元素,则返回-1。

  • function(currentValue, index,arr)(必需)函数参数: currentValue必需。当前元素index可选。当前元素的索引 arr 可选。当前元素所属的数组对象。
  • thisValue(可选):传递给函数的值一般用 "this" 值。如果这个参数为空, "undefined" 会传递给 "this" 值
var arr=[111,119,12,102,333];
var newarr=arr.findIndex(function(value, index, arr) {
  return value <100;
})
console.log(newarr) //2
console.log(arr)  //[111, 119, 12, 102, 333]

var arr=[111,119,112,102,333];
var newarr=arr.findIndex(function(value, index, arr) {
  return value <100;
})
console.log(newarr) //-1
console.log(arr)  //[111, 119, 112, 102, 333]

var arr=[111,119,12,102,333];
var newarr=arr.findIndex(function(value, index, arr) {
  return value <100;
})
console.log(newarr) //2
console.log(arr)  //[111, 119, 12, 102, 333]

var arr=[111,119,112,102,333];
var newarr=arr.findIndex(function(value, index, arr) {
  return value <100;
})
console.log(newarr) //-1
console.log(arr)  //[111, 119, 112, 102, 333]

为了弥补了数组的indexOf方法的不足:

[NaN].indexOf(NaN)
// -1

[NaN].findIndex(y => Object.is(NaN, y))
// 0
[NaN].indexOf(NaN)
// -1

[NaN].findIndex(y => Object.is(NaN, y))
// 0

可以借助Object.is方法做到。

fill

使用给定值来填充一个数组,返回一个新数组,原数组也变

  • value(必需):填充的值。
  • start(可选):开始填充位置。
  • end(可选):停止填充位置 (默认为 array.length)。

参数是1个

var arr=[111,119,12,102,333];
var newarr=arr.fill(666);
console.log(newarr)//[666, 666, 666, 666, 666]
console.log(arr)  //[666, 666, 666, 666, 666]
var arr=[111,119,12,102,333];
var newarr=arr.fill(666);
console.log(newarr)//[666, 666, 666, 666, 666]
console.log(arr)  //[666, 666, 666, 666, 666]

参数是2个第二参数是从该位置开始读取数据

var arr=[111,119,12,102,333];
var newarr=arr.fill(0,2);
console.log(newarr)//[111, 119, 0, 0, 0]
console.log(arr);//[111, 119, 0, 0, 0]
var arr=[111,119,12,102,333];
var newarr=arr.fill(0,2);
console.log(newarr)//[111, 119, 0, 0, 0]
console.log(arr);//[111, 119, 0, 0, 0]

参数是3个第二参数是从该位置开始读取数据,第三个参数停止填充位置

var arr=[111,119,12,102,333];
var newarr=arr.fill(0,2,4);
console.log(newarr)//[111, 119, 0, 0, 333]
console.log(arr);//[111, 119, 0, 0, 333]
var arr=[111,119,12,102,333];
var newarr=arr.fill(0,2,1);//若第三个参数<=第二个参数,返回原数组
console.log(newarr)//[111,119,12,102,333]
console.log(arr);//[111,119,12,102,333]
var arr=[111,119,12,102,333];
var newarr=arr.fill(0,2,2);
console.log(newarr)//[111,119,12,102,333]
console.log(arr);//[111,119,12,102,333]
var arr=[111,119,12,102,333];
var newarr=arr.fill(0,2,4);
console.log(newarr)//[111, 119, 0, 0, 333]
console.log(arr);//[111, 119, 0, 0, 333]
var arr=[111,119,12,102,333];
var newarr=arr.fill(0,2,1);//若第三个参数<=第二个参数,返回原数组
console.log(newarr)//[111,119,12,102,333]
console.log(arr);//[111,119,12,102,333]
var arr=[111,119,12,102,333];
var newarr=arr.fill(0,2,2);
console.log(newarr)//[111,119,12,102,333]
console.log(arr);//[111,119,12,102,333]

第二三参数是负数从右面最后一个元素开始计算的,右面的第一个为0,往前--

var arr=[111,119,12,102,333];
var newarr=arr.fill(0,-4,-2);
console.log(newarr)//[119, 12, 12, 102, 333]
console.log(arr);//[119, 12, 12, 102, 333]
var arr=[111,119,12,102,333];
var newarr=arr.fill(0,-4,-2);
console.log(newarr)//[119, 12, 12, 102, 333]
console.log(arr);//[119, 12, 12, 102, 333]
includes

返回一个布尔值,表示某个数组是否包含给定的值

  • searchElement 必须。需要查找的元素值。
  • fromIndex 可选。从该索引处开始查找 searchElement。如果为负值,则按升序从 array.length + fromIndex 的索引开始搜索。默认为 0。
var arr=[111,119,12,102,333];
var newarr=arr.includes(333);
console.log(newarr) //true
var arr=[111,119,12,102,333];
var newarr=arr.includes(3333);
console.log(newarr) //false
var arr=[111,119,12,102,333];
var newarr=arr.includes(333);
console.log(newarr) //true
var arr=[111,119,12,102,333];
var newarr=arr.includes(3333);
console.log(newarr) //false

第二个参数表示搜索的起始位置,默认为0

var arr=[111,119,12,102,333];
var newarr=arr.includes(333,5);//值大于等于数组长度,搜索不到
console.log(newarr)//false
var newar1r=arr.includes(333,4);
console.log(newar1r)//true
var arr=[111,119,12,102,333];
var newarr=arr.includes(333,5);//值大于等于数组长度,搜索不到
console.log(newarr)//false
var newar1r=arr.includes(333,4);
console.log(newar1r)//true

如果第二个参数为负数,则整个数组都会被搜索。

var arr=[111,119,12,102,333];
var newarr=arr.includes(333,-2);
console.log(newarr)//true
var newar1r=arr.includes(333,-99);
console.log(newar1r)//true
var arr=[111,119,12,102,333];
var newarr=arr.includes(333,-2);
console.log(newarr)//true
var newar1r=arr.includes(333,-99);
console.log(newar1r)//true
entries,keys和values

用于遍历数组,可以用for...of循环进行遍历;
唯一的区别是keys()是对键名的遍历、values()是对键值的遍历,entries()是对键值对的遍历。

for (let index of ['a', 'b'].keys()) {
  console.log(index);
}
// 0
// 1

for (let elem of ['a', 'b'].values()) {
  console.log(elem);
}
// 'a'
// 'b'

for (let [index, elem] of ['a', 'b'].entries()) {
  console.log(index, elem);
}
// 0 "a"
// 1 "b"
for (let index of ['a', 'b'].keys()) {
  console.log(index);
}
// 0
// 1

for (let elem of ['a', 'b'].values()) {
  console.log(elem);
}
// 'a'
// 'b'

for (let [index, elem] of ['a', 'b'].entries()) {
  console.log(index, elem);
}
// 0 "a"
// 1 "b"

可以调用遍历器对象的next方法,进行遍历。

var str = 'hello';
var iterator = str[Symbol.iterator]();
var result = iterator.next();
while (!result.done) {
    VAR = result.value;
    console.log(VAR)
    result = iterator.next();
}
var str = 'hello';
var iterator = str[Symbol.iterator]();
var result = iterator.next();
while (!result.done) {
    VAR = result.value;
    console.log(VAR)
    result = iterator.next();
}

Array的静态方法

所谓静态方法就是只能Array对象本身调用而通过Array对象实例化得到的实例不能调用

Array.isArray

用于判断实例是否为真正的Array类型

var arr=[]
var str='a'
var bool=false
var obj={}
var nu=null
var undefine=undefined
var sym = Symbol();
console.log(Array.isArray(arr))//true
console.log(Array.isArray(str))//false
console.log(Array.isArray(bool))//false
console.log(Array.isArray(obj))//false
console.log(Array.isArray(nu))//false
console.log(Array.isArray(undefine))//false
console.log(Array.isArray(sym))//false
var arr=[]
var str='a'
var bool=false
var obj={}
var nu=null
var undefine=undefined
var sym = Symbol();
console.log(Array.isArray(arr))//true
console.log(Array.isArray(str))//false
console.log(Array.isArray(bool))//false
console.log(Array.isArray(obj))//false
console.log(Array.isArray(nu))//false
console.log(Array.isArray(undefine))//false
console.log(Array.isArray(sym))//false

Array.from

用来将(ArrayLike)类似数组对象转换成数组
何谓ArrayLike对象指一个对象的数组集合,其表现出来的特征就是具有length属性同时元素的key是0,1,2,3这种

var obj = {
      "0" : 1,
      "1" : 2,
      length: 2
  };
  var obj = {
      "0" : 1,
      "1" : 2,
      length: 2
  };

最常见的有两种:DOM中的NodeList和函数中的arguments。

Array.from(arrayLike, mapFn, thisArg)

  • arrayLike(必需) 想要转换成数组的伪数组对象或可迭代对象。
  • mapFn (可选参数)如果指定了该参数,新数组中的每个元素会执行该回调函数。
  • thisArg (可选参数)可选参数,执行回调函数 mapFn 时 this 对象。
let arrayLike = {
 '0': 'a',
 '1': 'b',
 '2': 'c',
 length: 3
 };
 // ES5 的写法
 var arr1 = [].slice.call(arrayLike); // ['a', 'b', 'c']
 // ES6 的写法
 let arr2 = Array.from(arrayLike); // ['a', 'b', 'c']

 // NodeList 对象未使用Array.from转换
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
   <div >111</div>
   <div>222</div>
   <div>333</div>
   <script>
       let ps = document.querySelectorAll('div');
       console.log(ps)
     /*  NodeList{
       0:div
       1:div
       2:div
       length:3
       }*/
       //ArrayLike对象不能调用数组实例方法(例如push/forEach/splice)
      console.log(ps.push('222'))  //Uncaught TypeError: ps.push is not a function
   </script>
</body>
</html>
 // NodeList 对象使用Array.from转换
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
   <div >111</div>
   <div>222</div>
   <div>333</div>
   <script>
       let div = document.querySelectorAll('div');
       let arrdiv=Array.from(div)
       console.log(arrdiv)
       /*
       Array{
         0:div
         1:div
         2:div
        length:3
        }
        */
       arrdiv.forEach(function (div) {
           console.log(div);//<div>111</div><div>222</div><div>333</div>
       });
   </script>
</body>
</html>
 // arguments 对象
 function foo() {
 var args = Array.from(arguments);
 // ...
 }
 let arrayLike = {
 '0': 'a',
 '1': 'b',
 '2': 'c',
 length: 3
 };
 // ES5 的写法
 var arr1 = [].slice.call(arrayLike); // ['a', 'b', 'c']
 // ES6 的写法
 let arr2 = Array.from(arrayLike); // ['a', 'b', 'c']

 // NodeList 对象未使用Array.from转换
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
   <div >111</div>
   <div>222</div>
   <div>333</div>
   <script>
       let ps = document.querySelectorAll('div');
       console.log(ps)
     /*  NodeList{
       0:div
       1:div
       2:div
       length:3
       }*/
       //ArrayLike对象不能调用数组实例方法(例如push/forEach/splice)
      console.log(ps.push('222'))  //Uncaught TypeError: ps.push is not a function
   </script>
</body>
</html>
 // NodeList 对象使用Array.from转换
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
   <div >111</div>
   <div>222</div>
   <div>333</div>
   <script>
       let div = document.querySelectorAll('div');
       let arrdiv=Array.from(div)
       console.log(arrdiv)
       /*
       Array{
         0:div
         1:div
         2:div
        length:3
        }
        */
       arrdiv.forEach(function (div) {
           console.log(div);//<div>111</div><div>222</div><div>333</div>
       });
   </script>
</body>
</html>
 // arguments 对象
 function foo() {
 var args = Array.from(arguments);
 // ...
 }

扩展运算符(...)也具有同样的作用。

// arguments 对象
 function foo() {
 var args = [...arguments];
 }
 // NodeList 对象
 [...document.querySelectorAll('div')]
 // arguments 对象
 function foo() {
 var args = [...arguments];
 }
 // NodeList 对象
 [...document.querySelectorAll('div')]

第二个参数

Array.from([1, 2, 3], (x) => x * x)
//  等同于
Array.from([1,2,3]).map(x => x * x);
 // [1, 4, 9]

Array的操作

Array遍历

forEach遍历
var arr =[1,2,3,4];
arr.forEach((value,index,arr)=>{
     console.log(value);
});
var arr =[1,2,3,4];
arr.forEach((value,index,arr)=>{
     console.log(value);
});

forEach遍历数组,第一个参数是每个元素,第二个参数是索引,第三个参数是数组本身;
使用forEach遍历的过程中不能被终止,必须每一个值遍历一遍后才能停下来。

for in遍历
var arr =[1,2,3,4];
for(var value in arr){
   console.log(value)
 }
var arr =[1,2,3,4];
for(var value in arr){
   console.log(value)
 }

for in用来循环遍历对象的key,一般不推荐遍历数组,因为for in遍历后的不能保证顺序,而且原型链上的属性也会被遍历到,
因此一般常用来遍历非数组的对象并且使用hasOwnProperty()方法去过滤掉原型链上的属性

for of遍历
var arr =[1,2,3,4];
 for(var value of arr){
   console.log(value)
}
for(var value of arr){
  console.log(value)
 if(value===2){
   console.log('我要跳出循环了')
   break
   }
 }
var arr =[1,2,3,4];
 for(var value of arr){
   console.log(value)
}
for(var value of arr){
  console.log(value)
 if(value===2){
   console.log('我要跳出循环了')
   break
   }
 }

for of 避开了for-in循环的所有缺陷
与forEach()不同的是,它可以正确响应break、continue和return语句

Array去重

双层循环法一

外部循环控制元素arr[i]从左到右遍历,内部循环控制元素arr[j]从arr[i]元素后取值,如果arr[i]===arr[j]时,arr[i]指针后移,arr[j]也指向i的下一条的指针,不等时则push到新数组;
当内部循环大于arr的长度时,外循环继续++

function unique(arr){
    var result = []
    for(var i = 0; i < arr.length; i++){
        for(var j = i + 1; j < arr.length; j++){
            if(arr[i] === arr[j]){
                j = ++i;
            }
        }
        result.push(arr[i]);
    }
    return result;
}
var newarr=unique([1,2,2,4,4,3,1,2,5,1])
console.log(newarr) //[4, 3, 2, 5, 1]
function unique(arr){
    var result = []
    for(var i = 0; i < arr.length; i++){
        for(var j = i + 1; j < arr.length; j++){
            if(arr[i] === arr[j]){
                j = ++i;
            }
        }
        result.push(arr[i]);
    }
    return result;
}
var newarr=unique([1,2,2,4,4,3,1,2,5,1])
console.log(newarr) //[4, 3, 2, 5, 1]
双层循环法二

外部循环控制元素arr[i]从左到右依次遍历(也就是循环的次数),内部循环控制元素arr[j]从返回数组result开始遍历,如果arr[i]===arr[j]时跳出内部循环同时将arr[i]push到result数组中,
arr[i]指针后移,以此逻辑循环输出

function unique(arr) {
  var result = [];

  for (var i = 0; i < arr.length; i++) {
   for (var j = 0; j < result.length; j++) {
      if (result[j] === arr[i])
        break;
      }
      if (j === result.length){
         result.push(arr[i]);
      }

   }
  return result;
}

var newarr=unique([1,2,2,4,4,3,1,2,5,1])
console.log(newarr) //[1, 2, 4, 3, 5]
function unique(arr) {
  var result = [];

  for (var i = 0; i < arr.length; i++) {
   for (var j = 0; j < result.length; j++) {
      if (result[j] === arr[i])
        break;
      }
      if (j === result.length){
         result.push(arr[i]);
      }

   }
  return result;
}

var newarr=unique([1,2,2,4,4,3,1,2,5,1])
console.log(newarr) //[1, 2, 4, 3, 5]
对象属性不可重复:

利用对象的key值不可重复性进行数组的去重

function unique(arr) {
  var result = [];
  var  obj = {};
  for (var i = 0; i < arr.length; i++) {
       if(!obj[arr[i]]){
            obj[arr[i]] = 1;
            result.push(arr[i]);
        }
   }
  console.log(obj)
  return result;
}

var newarr=unique([1,2,2,4,4,3,1,2,5,1])
console.log(newarr) //[1, 2, 4, 3, 5]

function unique(arr) {
  var result = [];
  var  obj = {};
  for (var i = 0; i < arr.length; i++) {
       if(!obj[arr[i]]){
            obj[arr[i]] = 1;
            result.push(arr[i]);
        }
   }
  console.log(obj)
  return result;
}

var newarr=unique([1,2,2,4,4,3,1,2,5,1])
console.log(newarr) //[1, 2, 4, 3, 5]
排序后比较

先对数组进行排序,然后从最后开始比较,遇到相同的元素则删除

function unique(arr) {
  arr.sort(function(a,b){
        return a - b;
  })
  for (var i = arr.length-1;i > 0; i--) {
       if(arr[i] === arr[i-1]){
           arr.splice(i,1);
         }
   }
  return arr;
}

var newarr=unique([1,2,2,4,4,3,1,2,5,1])
console.log(newarr) //[1, 2, 3, 4, 5]
function unique(arr) {
  arr.sort(function(a,b){
        return a - b;
  })
  for (var i = arr.length-1;i > 0; i--) {
       if(arr[i] === arr[i-1]){
           arr.splice(i,1);
         }
   }
  return arr;
}

var newarr=unique([1,2,2,4,4,3,1,2,5,1])
console.log(newarr) //[1, 2, 3, 4, 5]
indexOf或者includes判别
function unique(arr) {
   var result=[]
  for (var i =0 ;i<arr.length; i++) {
    if(result.indexOf(arr[i])<0){  //!result.includes(arr[i])
        result.push(arr[i]);
    }
   }
    return result;
}

var newarr=unique([1,2,2,4,4,3,1,2,5,1])
console.log(newarr) //[1, 2, 4, 3, 5]
function unique(arr) {
   var result=[]
  for (var i =0 ;i<arr.length; i++) {
    if(result.indexOf(arr[i])<0){  //!result.includes(arr[i])
        result.push(arr[i]);
    }
   }
    return result;
}

var newarr=unique([1,2,2,4,4,3,1,2,5,1])
console.log(newarr) //[1, 2, 4, 3, 5]
set

利用Set数据结构,它类似于数组,但其元素都是唯一的。

function unique(arr) {
    var newarr=Array.from(new Set(arr))
    return newarr
}

var newarr=unique([1,2,2,4,4,3,1,2,5,1])
console.log(newarr) //[1, 2, 4, 4, 5]

function unique(arr) {
    var newarr=Array.from(new Set(arr))
    return newarr
}

var newarr=unique([1,2,2,4,4,3,1,2,5,1])
console.log(newarr) //[1, 2, 4, 4, 5]

数组的拷贝

数组的拷贝分为浅拷贝和深拷贝,两者都可以实现在已有对象或者数组上再生一份的作用。
对象在内存中存储是以引用地址的形式村咋,由此拷贝的时候就存在两种情况了:拷贝引用和拷贝实例,
这就成就了浅拷贝和深拷贝。

数组的浅拷贝

直接使用=号来进行复制实现浅拷贝

var arr = [1,2,3,4,5]
var newarr = arr
console.log(arr) //[1, 2, 3, 4, 5]
console.log(newarr) //[1, 2, 3, 4, 5]
arr.push(6)  //往arr push一个元素,newarr跟着变化
console.log(arr)  //[1, 2, 3, 4, 5, 6]
console.log(newarr) //[1, 2, 3, 4, 5,6]
var arr = [1,2,3,4,5]
var newarr = arr
console.log(arr) //[1, 2, 3, 4, 5]
console.log(newarr) //[1, 2, 3, 4, 5]
arr.push(6)  //往arr push一个元素,newarr跟着变化
console.log(arr)  //[1, 2, 3, 4, 5, 6]
console.log(newarr) //[1, 2, 3, 4, 5,6]

利用slice实现

var arr = [1,2,3,4,5]
var newarr = arr.slice()
console.log(arr) //[1, 2, 3, 4, 5]
console.log(newarr) //[1, 2, 3, 4, 5]
arr.push(6)
console.log(arr)  //[1, 2, 3, 4, 5, 6]
console.log(newarr) //[1, 2, 3, 4, 5]
var arr = [1,2,3,4,5]
var newarr = arr.slice()
console.log(arr) //[1, 2, 3, 4, 5]
console.log(newarr) //[1, 2, 3, 4, 5]
arr.push(6)
console.log(arr)  //[1, 2, 3, 4, 5, 6]
console.log(newarr) //[1, 2, 3, 4, 5]

纳尼???看到这里你可能会疑惑这不是深拷贝嘛???往arr push一个元素,newarr并未发生变化,WTF?
别急,往下看

var arr = [1,2,{age:3},4,5]
var newarr = arr.slice()
console.log(arr) //[1, 2, {age:3}, 4, 5]
console.log(newarr) //[1, 2, {age:3}, 4, 5]
arr[2].age=5
console.log(arr)  //[1, 2, {age:5}, 4, 5]
console.log(newarr) //[1, 2, {age:5}, 4, 5]
var arr = [1,2,{age:3},4,5]
var newarr = arr.slice()
console.log(arr) //[1, 2, {age:3}, 4, 5]
console.log(newarr) //[1, 2, {age:3}, 4, 5]
arr[2].age=5
console.log(arr)  //[1, 2, {age:5}, 4, 5]
console.log(newarr) //[1, 2, {age:5}, 4, 5]

同样concatObject.assign也只是实现浅拷贝的效果

数组的深拷贝
function deepCopy(arr) {
    if (arr instanceof Array) {
        var result = [];
        for (var i = 0; i < arr.length; ++i) {
            result[i] = deepCopy(arr[i]);
        }
        return result;

    } else if (arr instanceof Object) {
        var result = {}
        for (var i in arr) {
            result[i] = deepCopy(arr[i]);
        }
        return result;
    } else {
        return arr;
    }
}
var arr = [1,2,{age:3},4,5]
var newarr=deepCopy(arr)
console.log(arr) //[1, 2, {age:3}, 4, 5]
console.log(newarr) //[1, 2, {age:3}, 4, 5]
arr[2].age=5
console.log(arr)  //[1, 2, {age:5}, 4, 5]
console.log(newarr) //[1, 2, {age:3}, 4, 5]
function deepCopy(arr) {
    if (arr instanceof Array) {
        var result = [];
        for (var i = 0; i < arr.length; ++i) {
            result[i] = deepCopy(arr[i]);
        }
        return result;

    } else if (arr instanceof Object) {
        var result = {}
        for (var i in arr) {
            result[i] = deepCopy(arr[i]);
        }
        return result;
    } else {
        return arr;
    }
}
var arr = [1,2,{age:3},4,5]
var newarr=deepCopy(arr)
console.log(arr) //[1, 2, {age:3}, 4, 5]
console.log(newarr) //[1, 2, {age:3}, 4, 5]
arr[2].age=5
console.log(arr)  //[1, 2, {age:5}, 4, 5]
console.log(newarr) //[1, 2, {age:3}, 4, 5]