ES6深浅拷贝数组的扩展(forEach遍历与map方法的比较,Array.form()转数组)对象的拓展(Object.assign()对对象的合并)

数组的扩展

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()方法的区别

  1. indexOf返回的是下标。 includes返回的是布尔值
  2. indexOf用来判断是否包含不够语义化,不够直观。
  3. 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>

猜你喜欢

转载自blog.csdn.net/z18237613052/article/details/114098999