目录
数组的扩展
forEach遍历
//第一个参数为函数
//函数的第一个参数 是遍历的当前元素
//函数的第二个参数 当前元素的下标
//函数的第三个元素 数组本身。
//第二个参数为:函数中this指向。
arr.forEach(function(item,index,arr){
},obj);
小练习:将数组中的参数写入页面中(重点是看forEach中第二个参数(函数中this指向。)
<body>
<ul>
<li></li>
<li></li>
<li></li>
<li></li>
</ul>
</body>
<script>
var arr = [
"千与千寻",
"肖申克的救赎",
"谁先爱上他的",
"哈尔的移动城堡",
"海上钢琴师"
]
var lis = document.querySelectorAll("li")
arr.forEach(function (item, index, self) {
// console.log("电影名:"+item+",下标为:"+index);
this[index].innerHTML = item;
},lis);
</script>
map方法
map 映射含义,用法与forEach基本类似。
可以在函数中定义返回值。返回是一个数组。
var arr = [
{
name:"千与千寻",score:"8.6"},
{
name:"肖申克的救赎",score:"9.6"},
{
name:"谁先爱上他的",score:"8.3"},
{
name:"哈尔的移动城堡",score:"8.9"},
{
name:"海上钢琴师",score:"9.0"}
]
var arr2 = arr.map(function(item){
return item.score;
//等价于 return item["score"];
});
console.log(arr2);// 能够得到这里面的每一个值 "8.6", "9.6", "8.3", "8.9", "9.0"
数组 中 map方法与forEach遍历的比较,
<script>
var array = ["wo", "shi", "zhao"];
array.forEach(function (item, index, arr) {
console.log(item + " " + index);
//console.log(arr);
});
array.map(function (item, index, arr) {
console.log(item + " " + index);
//console.log(arr);
});
</script>
Array.form()
Array.form
方法可以将类似数组的对象转为真正的数组。比如:DOM获取的伪数组,arguments对象。
<body>
<ul>
<li></li>
<li></li>
<li></li>
<li></li>
</ul>
</body>
<script>
let lis = document.querySelectorAll("li");
console.log( lis);//输出的是li 的一个伪数组
var arr = Array.from(lis);//转换为真正数组
console.log( arr);//这时获取到的li是一个真正的数组
//用typeof检测时发现都为对象 是因为数组也是对象
</script>
小练习:将arguments的参数(是一个伪数组)排序
<!-- <script>
//获取arguments的参数是一个伪数组
function sort() {
var args = Array.from(arguments);//转换成了一个真正的数组,
return args.sort();//这样就能使用数组的排序方法sort()
}
console.log(sort(6, 3, 5));
</script> -->
这里在对比一下
<!-- <script>
let likeArr = {
length: 3,//这个设置要有,否则输出一个空数组
"0": "hello",
"1": "word",
"2": "你好"
}
console.log(likeArr);//{
0: "hello", 1: "word", 2: "你好", length: 3}
let arry = Array.from(likeArr);
console.log(arry);
//上下这两种输出都是一个真正的数组,结构样式一样
var arr = ["hello", "word", "你好"];
console.log(arr);
</script> -->
Array.of()
Array.of
方法将一组值,转换为数组。
<script>
let arr = Array.of( 3);
console.log(arr);//这时只有一个参数,就输出数组,数组里只有一个参数
let arr2 = new Array(3);//传统数组方法当数组里面只有一个参数时,输出的不是这个数组的内容,而是设置这个数组的长度
console.log(arr2);//输出 length: 3
//========================================================
let arr3 = new Array(1,2,3);
console.log(arr3);//输出数组 [1, 2, 3]
//Array.of方法
let arr4 = Array.of(1,2,3);
console.log(arr4);//输出数组 [1, 2, 3]
</script>
copyWithin()
将指定位置的内容复制到其他位置(复制会覆盖原有的内容)然后返回当前数组。
<script>
//target:必需,从该位置进行覆盖
//start:可选,从该位置开始读取数据,默认为0。如果为负数,表示倒数。
//end:可选 到该位置结束读取数据,默认为数组的长度。如果为负数,表示倒数、
var arr=[0,1,2,3,4]
// var arr1= arr.copyWithin(1);
// console.log(arr1);//[0, 0, 1, 2, 3]
// var arr2= arr.copyWithin(1,3);
// console.log(arr2);//[0, 3, 4, 3, 4]
// var arr3= arr.copyWithin(1,2,3);
// console.log(arr3);//[0, 2, 2, 3, 4]
// var arr4= arr.copyWithin(1,-2,4);
// console.log(arr4);[0, 3, 2, 3, 4]
这几种情况不能同时释放观察,因为同时释放原来的数组值就被改变,复制会覆盖原有的内容
</script>
find()和findIndex()
find方法,找到第一个符合条件的数组元素。
arr.find(function(item,indedx,arr){
//条件判断
})
小练习:(下面没有输出-9,因为它不是第一次出现)
<script>
var arr = [1, 6, -10, -9].find(function (item) {
return item < 0;
})
// ES6箭头函数写法
// var arr = [1, 6, -10, -9].find(item => item < 0)
console.log(arr);//-10
</script>
findIndex,找到第一个符合条件的数组元素的下标。
var arr = [1, 6, -10, -9].findIndex(item => item < 0)
console.log(arr);//2
keys(),values(),entries()配合for…of循环
这三个方法主要用于数组的遍历。配合for…of循环。
keys():对键名的遍历
values():对键值的遍历
entries():对键值对的遍历。
格式:
//item 指遍历的当前元素
//arr 指遍历的数组
for (const item of arr) {
console.log(item);
}
var arr = ["a","b"]
for (const item of arr.keys()) {
console.log(item);
}
// 0 1
for (const item of arr.values()) {
console.log(item);
}
// a b
for (const item of arr.entries()) {
console.log(item);
}
//[0,"a"] [1,"b"]
includes()
该方法可以判断数组是否包含指定的值。
格式
//arr:数组
//value:判断该数组中是否包含该值
//target:从数组的指定位置开始查找。
arr.includes(value,target)
返回值:布尔值 true为包含,false 不包含
console.log( [1,2,3].includes(2)); //true
console.log( [1,2,3].includes("2")); //false
console.log([1,2,3].includes(2,1));//true
console.log([1,2,3].includes(2,2));//false
小练习:
var arr = [1,2,3]
var index = arr.indexOf(2);//利用的是indexOf()方法找不到值返回-1
if(index !== -1){
console.log("该值已包含");
}else{
console.log("该值不包含");
}
显示该值已包含
var arr = [1,2,3]
var index = arr.indexOf(2);
includes方法与indexOf()方法的区别
- indexOf返回的是下标。 includes返回的是布尔值
- indexOf用来判断是否包含不够语义化,不够直观。
- indexOf 对于
NaN
是有误判的。
<script>这样写就没有了误判
var arr = [1, 2, 3,NaN]
// var index = arr.indexOf(NaN);//该值不包含(可是明明有)
var index = arr.includes(NaN);
if (index) {
console.log("该值已包含");
} else {
console.log("该值不包含");
}
</script>
对象扩展方法
Object.assign()
assign()用于对对象的合并。
格式
//第一个参数后面的所有参数,合并到第一个参数中。
Object.assign(target,obj1,obj2)
<script>
第一个参数后面的所有参数,合并到第一个参数中。
const target = {
name: '奥黛丽·赫本' }
const obj1 = {
age: '20' }
Object.assign(target, obj1);
console.log(target);//输出一个改变后的对象 {
age: "20" name: "奥黛丽·赫本"}
</script>
同名属性
<script>
let target = {
name: '奥黛丽·赫本' }
let obj1 = {
name: '张三' }
Object.assign(target, obj1);
console.log(target);//{
name: '张三'}
//遇到同名属性,则后面的参数对象中的属性会将前面的属性覆盖。
</script>
用在数组上
用在数组上时,会将数组视为对象。
<script>
//Object.assign() 用在数组上时,会将数组视为对象。
var arr1 = [10, 20, 30];
/*等价于 var arr1 = {
"0":"a",
"1":"b",
"2":30
}*/
var arr2 = ["a", "b"];
/*等价于 var arr2 = {
0: "a",
1: "b"
}*/
Object.assign(arr1, arr2);
console.log(arr1);//a,b,30
</script>
浅拷贝
对基本类型变量,浅拷贝是对值的拷贝,(会影响被拷贝的值)没有深拷贝的概念。
对引用类型来说,浅拷贝是对对象地址的拷贝,并没有开辟新的栈,复制的结果是两个对象指向同一个栈的地址,彼此之间的操作会互相影响,
<script>
//#### 浅拷贝只拷贝复合数据的内存地址。拷贝后的变量仍然指向原本的对象。
const target = {
name: "奥黛丽·赫本",
sex: "女",
son: {
name: "卢卡·多蒂",
age: "40"
}
};
let obj1 = {
name: "奥黛丽",
age: "20",
son: {
name: "卢卡·多蒂",
age: "40"
}
}
Object.assign(target, obj1);
console.log(target);
/*合并后的对象输出的为 {age: "20"
name: "奥黛丽"
sex: "女"
son: {name: "卢卡·多蒂", age: 39}}
我们看到加上来的对象替换了原来名字相同的对象 这里age: 就该为40,只不过 这样的演示不了(下面的40是对的)
*/
console.log(target.son.age);//40
/* 因为这个我们明白,原来的值没有被改变,他们得到的这个对象是这个对象的内存地址,
改变的也是也是这个对象的内存地址的内容,没有真正的改变这个对象的内容
*/
obj1.son.age = 39;//作用 改变里面的值
console.log(target.son.age);//39 值改变了,是对内存地址的改变,不是对堆中数据的改变
</script>
深拷贝
深拷贝则是开辟新的栈,拷贝后的对象与原来的对象是完全隔离,互不影响
assign对象(合并对象)扩展方法就是浅拷贝
。也就是说,如果被合并的对象中有一个属性为对象,那么target对象拷贝得到的是这个对象的内存地址。
<script>
let obj1 = {
name: 'tom',
age: 18,
sex: '男',
children: {
name: '张三',
age: 200
}
}
let obj2 = {
sleep: '睡觉'
}
// 合并对象
// let res = Object.assign(target, [obj1, obj2, ....]);
let res = Object.assign({
}, obj1)
// console.log(res);
console.log(obj1, obj2);
obj1.name = 'zhangsan';
console.log(obj1, obj2);
</script>
合并对象 也能够实现对象的拷贝 深拷贝是狭义(只能拷贝一层); 不能实现真正的深拷贝(对象嵌套的形式)
js 的深拷贝 经典的算法 递归算法实现
总要有一个出口
function deepObj(obj) {
let newObj = {
}
for (let key in obj) {
if (obj[key] instanceof Object) {
newObj[key] = deepObj(obj[key])
} else {
newObj[key] = obj[key]
}
}
return newObj
}
let res = deepObj(obj1)
console.log(res); //age变为3400
obj1.children.name = '2348758475';
res.children.age = 3400;
console.log(res); //age变为3400
console.log(obj1); age仍为200
这样就完成了深拷贝,拷贝后的对象与原来的对象是完全隔离
1.对象属性的简洁表示法
ES6可以在对象的大括号中,直接写入变量 和函数,作为对象的属性和方法。如果属性名与变量名相同,则可以简写,只写属性名即可。
var name = "赫本"
var obj = {
name}
//相当于
var obj = {
name:name}
console.log(obj.name); //赫本
<script>
function fn(a, b) {
return {
a,
b
};
/*等价于 return {
a: a,
b: b
};*/
}
var obj = fn("hello", "word");
console.log(obj); //{
a: "hello", b: "word"}
</script>
方法的简写
在对象中,可以对方法进行简写
<script>
let obj = {
fn() {
console.log("今晚九点,海岛集合。");
}
}
//相等于
/* let obj = {
fn: function() {
console.log("今晚九点,海岛集合。");
}
}*/
obj.fn();
</script>
简写只适用于普通函数方法,构造函数不能简写。
2.属性名表达式
拆分的功能,如果是对象,则将对象中的所有属性遍历出来,如果是数组,则将所有的元素遍历出来
<!-- <script>
let a = {
x: 1,
y: 2
}
let b = {
...a
}
console.log(b);// {
x: 1, y: 2}
</script> -->
<script>
let arr = [10, 20, 30];
let c = {
...arr
}
console.log(c["0"]);//10
</script>