克隆:
(1)赋值
索引也指向原地址
(2)浅克隆——js中基本上都是浅克隆,克隆原始值、克隆引用值的索引,使其指向同一个地址。
开辟内容和原地址内容一样的新空间,索引指向新的空间
(3)深克隆
开辟内容和原地址内容一样的新空间,新空间内的引用值,也开辟新空间。实现完全的互不影响。
(4)引用值的引用值是引用的地址:(浅克隆,因为对象的引用值还指向原来的地址,并没有完全克隆一份)
例如:obj对象的arr属性指向arr的引用地址;当arr指向别的地址时,不想要obj.arr指向原本的地址[1,2,3]
let arr = [1,2,3];
let obj = {};
obj.arr = arr;
arr = ["a"];
console.log(obj.arr);//[1, 2, 3]
例如:通过arr索引修改该地址中的值时,会影响到obj.arr的值。因为他们指的是同一个地址。
let arr = [1,2,3];
let obj = {};
obj.arr = arr;
arr[0] = "a";
console.log(obj.arr);// ["a", 2, 3]
数组方法
改变原数组的方法有:push、pop、unshift、shift、sort、reverse、splice
操作数组得到的结果数组,只是得到副本,得到原数组引用数据的地址所指的空间,得到原始值的复制值。
数组的方法的原理:
都是开辟一个新的内存空间,进行新的地址赋值操作。
(1)修改地址所指的空间值,副本受到影响
var arr = [["a"],2,3]
var arr1 = arr.slice(0,1);
arr[0][0] = "b";
console.log(arr, arr1);
(2)改变原数组第一项的地址,副本不受影响。因为副本的地址还指向之前的位置。就好像构造函数创建的两个实例对象,当其中一个对象修改地址和修改地址的内容,结果是不同。
var arr = [["a"],2,3]
var arr1 = arr.slice(0,1);
arr[0] = ["b"];
console.log(arr, arr1);
1、join方法
遍历每一项及其子项调用toString方法,使得每项及其子项成为字符串。
用一个字符串来拼接数组的每一项,如果不给join传值,或者传入undefined值,默认按逗号拼接
特点:首先将数组的每一项连接,数组的每一项调用toString方法
var arr = [1,2,"str",[false,undefined,[4],3],{name:"zhu"}];
console.log(arr.join("~"));
结果
1~2~str~false,,4,3~[object Object]
(1)不改变原数组;(2)返回字符串结果
如果数组的项中有undefined或null:得到空字符;而字符串中处理undefined和null时,得到字符串“undefined”和“null”。
var arr = [undefined, null, "", 1, false, [2,[8,9],3],{}, "abc"]
console.log(arr.join(''));
"1false2,8,9,3[object Object]abc"
join方法与字符串的split方法对应!
2、push方法
在数组末尾添加一项或者多项,并修改length值
push
方法具有通用性。该方法和 call()
或 apply()
一起使用时,可应用在类似数组的对象上。push
方法根据 length
属性来决定从哪里开始插入给定的值。如果 length
不能被转成一个数值,则插入的元素索引为 0,包括 length
不存在时。当 length
不存在时,将会创建它。
var arr = [1,2,"str",[false,[4],3],{name:"zhu"}];
console.log(arr.push(true)); //6
console.log(arr); //[1, 2, "str", Array(3), {…}, true]
可以添加多项:
var arr = ["a", "b", "c"];
console.log(arr.push("d","e")); //返回长度值5
console.log(arr); //["a", "b", "c", "d", "e"]
(1)修改原数组;(2)返回length值
问:为什么push方法返回length值?
因为数组的方法操作无非是这些值,操作后的数组、操作的片段组成的数据、或者length值。因为push方法是修改数组的,所以不会返回修改后的数组,而且push方法可以push多个值进去,push进去的值我们也是知道的,所以返回length值最合理。
3、pop方法
在数组末尾移除一项,并修改length值
var arr = [1,2,"str",[false,[4],3],{name:"zhu"}];
console.log(arr.pop());//{name: "zhu"}
console.log(arr);//[1, 2, "str", Array(3)]
(1)修改原数组;(2)返回移除项
pop
方法从一个数组中删除并返回最后一个元素。
pop
方法有意具有通用性。该方法和 call()
或 apply()
一起使用时,可应用在类似数组的对象上。pop
方法根据 length
属性来确定最后一个元素的位置。如果不包含length
属性或length
属性不能被转成一个数值,会将length
置为0,并返回undefined
。
function a(){
console.log(Array.prototype.pop.apply(arguments)); //c
}
a("a","b","c");
如果你在一个空数组上调用 pop(),它返回 undefined
。
4、unshift方法
unshift
方法会在调用它的类数组对象的开始位置插入给定的一个或多个参数。
unshift
特意被设计成具有通用性;这个方法能够通过 call
或 apply
方法作用于类数组对象上。不过对于没有 length 属性(代表从0开始的一系列连续的数字属性的最后一个)的对象,调用该方法可能没有任何意义。
注意, 如果传入多个参数,它们会被以块的形式插入到对象的开始位置,它们的顺序和被作为参数传入时的顺序一致。 于是,传入多个参数调用一次 unshift
,和传入一个参数调用多次 unshift
(例如,循环调用),它们将得到不同的结果
var arr = [1,2,"str",[false,[4],3],{name:"zhu"}];
console.log(arr.unshift(true));//6
console.log(arr);//[true, 1, 2, "str", Array(3), {…}]
(1)修改原数组;(2)返回length值
5、shift方法
在数组前面移除一项,并修改length值
shift
方法移除索引为 0 的元素(即第一个元素),并返回被移除的元素,其他元素的索引值随之减 1。如果 length
属性的值为 0 (长度为 0),则返回 undefined
。
shift
方法有意具有通用性。shift
方法并不局限于数组:这个方法能够通过 call
或 apply
方法作用于类似数组的对象上。但是对于没有 length 属性(从0开始的一系列连续的数字属性的最后一个)的对象,调用该方法可能没有任何意义。
var arr = [1,2,"str",[false,[4],3],{name:"zhu"}];
console.log(arr.shift());//1
console.log(arr);//[2, "str", Array(3), {…}]
(1)修改原数组;(2)返回移除项
6、reverse方法
reverse()
方法将数组中元素的位置颠倒,并返回该数组。数组的第一个元素会变成最后一个,数组的最后一个元素变成第一个。该方法会改变原数组。
var arr = [1,2,"str",[false,[4],3],{name:"zhu"}];
console.log(arr.reverse());//[{…}, Array(3), "str", 2, 1]
console.log(arr);//[{…}, Array(3), "str", 2, 1]
颠倒类数组:
const a = {0: 1, 1: 2, 2: 3, length: 3};
console.log(a); // {0: 1, 1: 2, 2: 3, length: 3}
Array.prototype.reverse.call(a); //same syntax for using apply()
console.log(a); // {0: 3, 1: 2, 2: 1, length: 3}
(1)修改原数组;(2)返回修改后的原数组
7、sort方法
排序且修改原数组
arr.sort([compareFunction])
compareFunction
可选,用来指定按某种顺序进行排列的函数。如果省略,元素按照转换为的字符串的各个字符的Unicode位点进行排序。
var arr = ["a","c","b","ac","bc"];
arr.sort()
console.log(arr);//["a", "ac", "b", "bc", "c"]
升序或降序
var arr = [1,3,5,2,4];
arr.sort(function(a,b){
return a - b;//升序
return b - a;//降序
})
console.log(arr);//[1, 2, 3, 4, 5]
(2)对非 ASCII 字符排序:
当排序非 ASCII 字符的字符串(如包含类似 e, é, è, a, ä 等字符的字符串)。一些非英语语言的字符串需要使用 String.localeCompare
。这个函数可以将函数排序到正确的顺序
(3)使用映射改善排序
compareFunction
可能需要对元素做多次映射以实现排序,尤其当 compareFunction
较为复杂,且元素较多的时候,某些 compareFunction
可能会导致很高的负载。使用 map 辅助排序将会是一个好主意。基本思想是首先将数组中的每个元素比较的实际值取出来,排序后再将数组恢复。
实例:
var arr = ['a','c','b']
arr.sort((a,b) => {
return a.localeCompare(b) //比较一切字符数字
return a - b; //比较数字
})
8、concat方法
拼接数组, concat()
方法用于合并两个或多个数组。此方法不会更改现有数组,而是返回一个新数组。
concat
方法创建一个新的数组,每个参数的顺序依次是:如果是数组,就是数组的每个元素,如果不是数组,就是该参数本身。
注意:数组/值在连接时保持不变。此外,对于新数组的任何操作(仅当数组元素不是对象引用时)都不会对原始数组产生影响,反之亦然。
下例中,数组arr中的元素不是引用值,修改不会影响newArr
var arr = ["a", "b", "c"];
var newArr = [].concat(arr);
console.log(newArr); //["a", "b", "c"]
arr[0] = "d";
console.log(newArr); //["a", "b", "c"]
如果没有给该方法传参,只是赋值该数组并返回副本。
var arr = ["a","c","b","ac","bc"];
var arr1 = arr.concat();
arr.push(1)
console.log(arr);//["a", "c", "b", "ac", "bc", 1]
console.log(arr1);//["a", "c", "b", "ac", "bc"]
传参
可以传递多个参数,每个参数按顺序拼接到副本中,如果参数是一个数组,将该数组的每一项拼接到副本中。
var arr = ["a","c","b","ac","bc"];
var arr1 = arr.concat([1,[true],2,3],4,{name:"zhu"});
console.log(arr);//["a", "c", "b", "ac", "bc"]
console.log(arr1);//["a", "c", "b", "ac", "bc", 1, Array(1), 2, 3, 4, {…}]
(1)不修改原数组;(2)返回拼接后的数组
9、slice方法
slice()
方法返回一个新的数组对象,这一对象是一个由 begin
和 end
决定的原数组的浅拷贝(包括 begin
,不包括end
)。原始数组不会被改变。
传参为数组索引,如果传的参数有负值,则用数组长度length 加上该值来确定位置。如果结束位置小于起始位置,返回空数组。
不传参,截取整段数组,即浅copy数组
var arr = ["a","c","b","ac","bc"];
var arr1 = arr.slice();
console.log(arr);//["a", "c", "b", "ac", "bc"]
console.log(arr1);//["a", "c", "b", "ac", "bc"]
传 一个参数,截取时,起始索引值到数组末尾
var arr = ["a","c","b","ac","bc"];
var arr1 = arr.slice(1);
console.log(arr);//["a", "c", "b", "ac", "bc"]
console.log(arr1);//["c", "b", "ac", "bc"]
传两个参数,截取的起始索引值到终止索引值
var arr = ["a","c","b","ac","bc"];
var arr1 = arr.slice(1,3);
console.log(arr);//["a", "c", "b", "ac", "bc"]
console.log(arr1);//["c", "b"]
begin
可选提取起始处的索引(从
0
开始),从该索引开始提取原数组元素。如果该参数为负数,则表示从原数组中的倒数第几个元素开始提取,
slice(-2)
表示提取原数组中的倒数第二个元素到最后一个元素(包含最后一个元素)。如果省略
begin
,则slice
从索引0
开始。如果
begin
大于原数组的长度,则会返回空数组。
end
可选提取终止处的索引(从
0
开始),在该索引处结束提取原数组元素。slice
会提取原数组中索引从begin
到end
的所有元素(包含begin
,但不包含end
)。
slice(1,4)
会提取原数组中从第二个元素开始一直到第四个元素的所有元素 (索引为 1, 2, 3的元素)。如果该参数为负数, 则它表示在原数组中的倒数第几个元素结束抽取。
slice(-2,-1)
表示抽取了原数组中的倒数第二个元素到最后一个元素(不包含最后一个元素,也就是只有倒数第二个元素)。如果
end
被省略,则slice
会一直提取到原数组末尾。如果
end
大于数组的长度,slice
也会一直提取到原数组末尾。
10、splice方法
splice()
方法通过删除或替换现有元素或者原地添加新的元素来修改数组,并以数组形式返回被修改的内容。此方法会改变原数组。
传递参数:从第几位,截取几个,插入的值
start
指定修改的开始位置(从0计数)。如果超出了数组的长度,则从数组末尾开始添加内容;如果是负值,则表示从数组末位开始的第几位(从-1计数,这意味着-n是倒数第n个元素并且等价于
array.length-n
);如果负数的绝对值大于数组的长度,则表示开始位置为第0位。
deleteCount
可选整数,表示要移除的数组元素的个数。
如果
deleteCount
大于start
之后的元素的总数,则从start
后面的元素都将被删除(含第start
位)。如果
deleteCount
被省略了,或者它的值大于等于array.length - start
(也就是说,如果它大于或者等于start
之后的所有元素的数量),那么start
之后数组的所有元素都会被删除。如果
deleteCount
是 0 或者负数,则不移除元素。这种情况下,至少应添加一个新元素。
item1, item2, ...
可选要添加进数组的元素,从
start
位置开始。如果不指定,则splice()
将只删除数组元素
会 将后面要插入的值,插入到原数组中。
var arr = ["a","c","b","ac","bc"];
var arr1 = arr.splice(2,0,true,1,2,3);
console.log(arr);//["a", "c", true, 1, 2, 3, "b", "ac", "bc"]
console.log(arr1);//[]
如果是数组或对象也是直接插入
var arr = ["a","c","b","ac","bc"];
var arr1 = arr.splice(2,0,[true,1,2,3],{name:"zhu"});
console.log(arr);//["a", "c", Array(4), {…}, "b", "ac", "bc"]
console.log(arr1);//[]
返回值:由被删除的元素组成的一个数组。如果只删除了一个元素,则返回只包含一个元素的数组。如果没有删除元素,则返回空数组。
实际上可以同时删除和插入的,如果添加进数组的元素个数不等于被删除的元素个数,数组的长度会发生相应的改变。
(1)修改原数组;(2)返回截取的数组。
11、indexOf方法和lastIndexOf方法 -- ES5方法
正向查找和反向查找数组中的值,返回找到的第一个值的索引,如果没有返回-1
var arr = ["a","c","b","ac","bc","b"];
console.log(arr.indexOf("b"));//2
console.log(arr.lastIndexOf("b"));//5
问:如果是查找引用值呢?
答:indexOf方法查找,是根据===来判断的,如果是引用值,要判断地址是否相同!
var obj = {b:2}
var arr = [1, true, {a:0}, ["m"], undefined, null, NaN, obj];
console.log(arr.indexOf(NaN)) // -1
console.log(arr.indexOf(null)) //5
console.log(arr.indexOf(undefined)) //4
console.log(arr.indexOf(["m"])) //-1
console.log(arr.indexOf(obj)) //7
12、迭代方法 -- ES5方法
对数组的每一项指定一个运行函数
参数:item,index(value,key)
arr.map((item,index) => {
console.log(item,index)
})
对这个五个迭代方法的思考:
callback:
用来测试数组的每个元素的函数。返回true
表示该元素通过测试,保留该元素,false
则不保留。它接受以下三个参数:
element
:数组中当前正在处理的元素。
index
可选:正在处理的元素在数组中的索引。
array
可选:调用了filter
的数组本身。
thisArg
可选:执行callback
时,用于this
的值。
forEach循环处理数组,无返回结果;
map循环处理,返回处理函数的返回值组成数组。
filter循环处理,返回处理结果为true的项组成的数组。
every循环处理,每项为true,返回true
some循环处理,某项为true,返回true。所以some可能不会执行每项,因为找到true项就停止循环。
var arr = [1,2,3];
arr.forEach(function(item,index){//undefined
})
arr.map(function(item, index){//处理函数的结果
})
arr.filter(function(item, index){// 处理函数为true的项
})
arr.every(function(item, index){//true or false
})
arr.some(function(item, index){//true or false
})
(1)map 方法
返回每次函数调用执行结果组成的数组,即处理函数的返回值组成的数组
注意: map() 不会对空数组进行检测。arr是长度为5的空数组,map方法不执行。arr为【】空数组也不执行。
var arr = new Array(5)
arr.map(function(){
console.log(1);
})
注意:
map
生成一个新数组,当你不打算使用返回的新数组却使用map
是违背设计初衷的,请用forEach
或者for-of
替代。你不该使用map
: A)你不打算使用返回的新数组,或/且 B) 你没有从回调函数中返回值。
callback
函数会被自动传入三个参数:数组元素,元素索引,原数组本身。map
不修改调用它的原数组本身(当然可以在callback
执行时改变原数组)
对于只接受一个参数的方法,可以直接调用。因为该方法对应callback的第一个参数:
var numbers = [1, 4, 9];
var roots = numbers.map(Math.sqrt); //[1, 2, 3]
(2)filter方法
返回执行结果true的项组成的数组
filter
遍历的元素范围在第一次调用callback
之前就已经确定了。在调用filter
之后被添加到数组中的元素不会被filter
遍历到。如果已经存在的元素被改变了,则他们传入callback
的值是filter
遍历到它们那一刻的值。被删除或从来未被赋值的元素不会被遍历到。遍历过程中:
(1)给原数组新增的元素不会被遍历;
(2)删除的元素或未被赋值的元素不会被遍历;
(3)修改的元素,会被遍历到
(3)forEach方法
遍历规则与filter一样!除此之外:
如果数组在迭代时被修改了,则会跳过一些元素。当到达包含值 "two" 的项时,整个数组的第一个项被移除了,这导致所有剩下的项上移一个位置。因为元素 "four" 正位于在数组更前的位置,所以 "three" 会被跳过。会输出 "one", "two", "four"。
注意: 除了抛出异常以外,没有办法中止或跳出
forEach()
循环。如果你需要中止或跳出循环,forEach()
方法不是应当使用的工具。若你需要提前终止循环,你可以使用:
- 一个简单的 for 循环
- for...of / for...in 循环
Array.prototype.every()
Array.prototype.some()
Array.prototype.find()
Array.prototype.findIndex()
这些数组方法则可以对数组元素判断,以便确定是否需要继续遍历:
译者注:只要条件允许,也可以使用
filter()
提前过滤出需要遍历的部分,再用forEach()
处理
(4)every方法
如果回调函数的每一次返回都为 truthy 值,返回 true
,否则返回 false
。
every()
方法测试一个数组内的所有元素是否都能通过某个指定函数的测试。它返回一个布尔值。
注意:若收到一个空数组,此方法在一切情况下都会返回
true
。
(5)some方法
some()
方法测试数组中是不是至少有1个元素通过了被提供的函数测试。它返回的是一个Boolean类型的值。
注意:如果用一个空数组进行测试,在任何情况下它返回的都是
false
。
注意:
1、数组中除了indexOf和lastIndexOf接收的是元素项,其他的都是数组方法都接收处理函数。