JavaScript ES5-ES6详解

ES5

1.严格模式

1.全局严格模式

  • 严格模式修复了一些导致
    JavaScript引擎难以执行优化的缺陷:有时候,相同的代码,严格模式可以比非严格模式下运行得更快

  • 如果浏览器不支持, 只解析为一条简单的语句, 没有任何副作用

a.开启全局严格模式

<script>
        "use strict"
        //在全局开启严格模式

b.变量必须声明才能使用

<script>
        "use strict"
        a = 1;
       console.log(a)
       //Uncaught ReferenceError: a is not defined
       //未捕获的ReferenceError:未定义
</script>

c.函数自调用this是window

// 严格模式下,如果函数自己调用,this是undefined
        function fn(){
            console.log(this)
        }
        fn()//undefined
        window.fn()//window

d.创建了eval作用域

// 严格模式下,创建了eval作用域
 
        /* eval("alert(1)")
        eval可以把一串字符串代码运行 */
        
        eval("var a = 1; console.log(a)"); //1
        console.log(a)
        //ReferenceError: a is not defined

e.禁止调用栈

<script>
        "use strict"
        // 禁止调用栈
        function fn() {
            console.log(arguments)
            //Arguments [callee: (...), Symbol(Symbol.iterator): ƒ]
 
            console.log(arguments.callee)
            // Uncaught TypeError: 'caller', 'callee', and 'arguments' properties may not be accessed on strict mode functions or the arguments objects for calls to them
            // 如果不是严格模式,这里指向fn这个函数
        }
        fn()
    </script>

f.严格模式下禁止删除变量

  • 禁止删除变量
<script>
        "use strict" 
        a = 1;
        delete a;
        console.log(a)
        // Uncaught SyntaxError: Delete of an unqualified identifier in strict mode.
    </script>
 

<script>
        a = 1;
        delete a;
        console.log(a)
        // Uncaught ReferenceError: a is not defined
 </script>

 <script>
        "use strict"
        const a = 100; var let const都如此
        delete a
        // Uncaught SyntaxError: Delete of an unqualified identifier in strict mode.
未捕获的SyntaxError:删除严格模式下的非限定标识符。
    </script>

  • var/const/let 声明变量 经测试都无法删除

  • 并且const/let声明的变量不在window中

<script>
        var a = 100;
        console.log(window)
        console.log(a)
        // 100
        delete a
        console.log(window)
        console.log(a)
        // 100
 </script>

在这里插入图片描述

在这里插入图片描述

delete a

在这里插入图片描述

  • 直接声明变量
<script>
        a = 100;
        console.log(window)
        //见图
        console.log(a) 
        // 100
        delete a
        console.log(window)
        console.log(a)
        //Uncaught ReferenceError: a is not defined
</script>

065157c45ee86ac4a39013c258b4abdd.png

delete a

在这里插入图片描述

  • 注意区别
<script>
        var a = {
            b : 100
        }
        
        console.log(a)  
        // {b:100}
 
        delete a.b
        console.log(a)
        // {}
</script>
 <script>
        "use strict"
 
        var a = {
            b : 100
        }
        
        console.log(a)  
        // {b:100}
 
        delete a.b
        console.log(a)
        // {}
    </script>

2.局部严格模式

<script>
        a = 1;
 
        function fn(){
            "use strict"
            //在当前作用域中开启严格模式
 
            b = 2;
            console.log(b);
            //ReferenceError: b is not defined
        }
        console.log(a);//1会正常打印
        fn();
</script>

2.JSON

JSON的格式和JS对象基本一致,但是有两点需要注意:

  1. JSON的属性名必须使用双引号

  2. 最后一个属性后绝对不能有逗号

<script>
        var json = '{"name":"孙悟空", "age":18, "gender":"男", "haha":null, "abc":{}, "bcd":[]}';
        var jsonArr = '[1, 2, 3]';
 
        console.log(typeof json); //string
        console.log(typeof jsonArr); //string
    </script>

JSON类型

  • JSON对象

    • {}
  • JSON数组

    • []

JSON所支持的属性的类型

  1. 数字

  2. 字符串(使用双引号)

  3. 布尔值

  4. 空值(null)

  5. 对象

  6. 数组

JSON深复制

可以通过JSON来完成对象的深复制

slice() 方法返回一个新的数组对象,这一对象是一个由 begin 和 end
决定的原数组的浅拷贝(包括 begin,不包括end)。原始数组不会被改变。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-N3sXwJhi-1605369770483)(media/54c7bc2edceb839fe246c666c1f984f2.png)]

1.eval把json字符串转换为json对象(了解)

<script>
        var message = '{"name":"rolls","age":"99","color":"orange"}';
        console.log(typeof message)
        //string
 
        // eval把json字符串转换为json对象
        console.log(eval("("+message+")"))
        //{name: "rolls", age: "99", color: "orange"}
</script>

2.parse()把JSON字符串转换成JS对象

 //JSON.parse()把json字符串转换成json对象
        console.log(typeof JSON.parse(message))
        // object
        //{name: "rolls", age: "99", color: "orange"}

<script>
        json = '{"name":"孙悟空", "age":18, "gender":"男"}';
        console.log(JSON.parse(json)) //Object
        //{name: "孙悟空", age: 18, gender: "男"}
</script>

3.stringify()把JS对象转换为JSON字符串

// // JSON.stringify() 把JSON对象转换为JSON字符串
        let message  =  {
            "name" : "rolls",
            "age" : 90,
            "color" : "orange"
        };
        console.log(message)
        //{name: "rolls", age: 90, color: "orange"}
        // 这是对象
        console.log(JSON.stringify(message))
        //{"name":"rolls","age":90,"color":"orange"}
        // 这是JSON字符串

<script>
        var arr = [
        {name:"孙悟空", age:18, gender:"男"},
        {name:'猪八戒', age:28, gender:'男'},
        {name:'沙和尚', age:38, gender:'男'}
    ];
 
    console.log(JSON.stringify(arr))
    //[{"name":"孙悟空","age":18,"gender":"男"},{"name":"猪八戒","age":28,"gender":"男"},{"name":"沙和尚","age":38,"gender":"男"}]
 </script>

3.object扩展

1.Object.create()

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rlJKf7gR-1605369770487)(media/495cfbf6f3d9c7998435740bae9c03d5.png)]

properties:属性

1.继承

var obj1 = {
            name: "xiaowang",
            sex: "nan"
        }
 
        //1.创建一个新的对象,把新对象的隐式原型指向了obj1,这个也被称作为继承
        var obj2 = Object.create(obj1);
        console.log(obj2);
        //{}
        console.log(obj2.name); //xiaowang
 
 
 
        //只给obj2扩展,obj1是没有
        obj2.age = 12;
        console.log(obj1.age);
        //xiaowang,因为它的隐式原型指向obj1

2.创建干净对象

//2.可以使用create创建一个干净的对象 (直接隐式原型指向null)
        var obj3 = Object.create(null);
        console.log(obj3);
        //{ No properties }

3.创建正常对象

//3.使用create创建一个正常的对象(就像使用字面量创建一个)
        var obj4 = Object.create(Object.prototype);
        
        console.log(obj4)

2.create创建对象属性描述

1.create方法第二个参数

create方法的第二个参数是一个对象
            对象内格式是  key:{value:xxxx,xxx:xxx}
 
            value:当前key的值
            writable:当前属性是否可以被写入 默认是false
            enumerable:当前属性是否可以被枚举  默认是false
            configurable:当前属性的描述是否可以被修改 和 当前属性是否能够被删除  默认是false

2.演示

var obj1 = Object.create(null, {
            name: {
                value: "xiaowang",
                writable: false,
                enumerable: false,
                configurable: false
            }
            
        });
        console.log(obj1)
        //{name: "xiaowang"}
 
        //尝试修改属性的值
        obj1.name = "xiaoli";
        console.log(obj1);
        //{name: "xiaowang"}  
        //不能修改,因为writable: false
 
        //尝试枚举
        for (var key in obj1) {
            console.log(key);
        }
        // 不能遍历,因为enumerable false
 
        //尝试删除
        delete obj1.name;
        console.log(obj1);
        //{name: "xiaowang"}
        //不能删除,因为configurable:false
 
 
        //当打印出来的系统提供的对象属性颜色 为浅紫色的时候 代表这个属性不可以枚举
        for (var key2 in Object.prototype) {
            console.log(key2)
        }
 
 
 
//如果直接给这个create创建的对象 设置属性的时候,此时扩展的属性是不受描述影响的
        obj1.age = 18;
        console.log(obj1)
        //可以被枚举
        for (var key in obj1) {
            console.log(key);
        }
        //可以被删除
        delete obj1.age;
        console.log(obj1)

3.defineProperty设置对象属性

 //创建一个普通的对象
        var obj1 = {
            name: "小王",
            age: 12
        }
 
        //使用Object.defineProperty设置对象属性
        //Object.defineProperty(obj,key,{des})
        //如果修改的是普通属性,则只修改你要修改的秒速,其他默认都是true
        Object.defineProperty(obj1, "age", {
            value: 18,
            //没有添加的描述默认是true
        })
        //age依然可以被修改
        obj1.age = 20;
        console.log(obj1);
        // {name: "小王", age: 20}
 
 
 
 
        //当对象是使用create创建的时候,修改属性或描述的情况
        var obj2 = Object.create(null, {
            name: {
                value: "xiaowang",
                writable: true,
                enumerable: false,
                // configurable: false
            }
        });
        Object.defineProperty(obj2, "name", {
            value: "xiaohong",
            enumerable: true, //需要创建name属性的时候,设置的描述configurable 为true 才能修改name的描述属性
        })
        console.log(obj2)
        //{name: "xiaohong"}
        //writable: true
 
        for (var key in obj2) {
            console.log(key)
            //name enumerable: true
        }

4.defineProperties设置对象属性

//创建一个普通的对象
        var obj1 = {
            name: "小王",
            age: 12
        }
 
        //使用Object.defineProperties 设置对象属性
        //Object.defineProperties(obj,{des})
        //其他和defineProperty一样,除了一个书写多个 一个是书写一个
        Object.defineProperties(obj1, {
            name: {
                value: "laowang"
            },
            age: {
                value: 200
            },
            sex: {
                value: "nv" //如果添加新属性,则默认描述都是false
            }
        })
        console.log(obj1)
        //{name: "laowang", age: 20, sex: "nv"}
 
        for (var key in obj1) {
            console.log(key);
            // name age sex
        }

5.getter和setter

<script>
        //当对对象中多个属性进行读取和设置的时候,就可以使用getter和setter
        //getter只能读  setter只能写
        var obj1 = {
            firstName: "lao",
            lastName: "wang",
 
            get fullName() {
                return this.firstName + " " + this.lastName;
            },
            set setName(val) {
                // var arr = val.split(" ");
                // this.firstName = arr[0];
                // this.lastName = arr[1];
                [this.firstName, this.lastName] = val.split(" ");
            }
        }
        // console.log(obj1.firstName + obj1.lastName);
        console.log(obj1.fullName);
        //lao wang
        console.log(obj1);
        //{firstName: "lao", lastName: "wang"}
        
        //设置内容
        obj1.setName = "lao li"
</script>

ES6

1.关键字扩展

1.块作用域,可以作用域嵌套

<script>
        // 块作用域是代码块{}所构成的作用域
        {
            let a = 1;
            console.log(a);
            //1
            {
                let b = 2;
                console.log(a,b);
                //1 2
                {
                    let c = 3;
                    console.log(a,b,c)
                    //1 2 3
                }
            }
        }
    </script>

2.let声明的变量,只在代码块中生效,所以就拥有了块级作用域

 	  var a = 1;
        if (a > 0) {
            var b = 2;
        }
        console.log(b)
        //2
 
        var a = 1;
        if (a > 0) {
            let b = 2;
        }
        console.log(b)
        //ReferenceError: b is not defined

3.let特点(其次)

1.没有声明提升

<script>
        // 没有声明提升
        {
            console.log(a)
            let a = 1;
        }
//Uncaught ReferenceError: Cannot access 'a' before initialization
    </script>

2.不允许重复声明

// 不允许重复声明
        {
            let a = 1;
            let a = 2;
        }
        //ReferenceError: Cannot access 'a' before initialization


3.块级作用域使得IIFE没有必要存在

{
            let a = 1;
            console.log(a);
            //1
}

4.const常量(优先使用)

1.常量不允许被修改

{
            const PI = 3.1415926;
            console.log(PI)
            //常量不允许被修改(不允许修改栈中 常量保存的值)
            // PI = 3.14159265352344265253423; 
            // TypeError: Assignment to constant variable.
 }

2.改常量保存地址值内数据无碍

{
            const obj = {
                name: "lucy",
                sex: "nv"
            }
            //obj常量 保存的地址值没有被修改  所以可以正常执行
            obj.age = 14;
            console.log(obj)
            // {name: "lucy", sex: "nv", age: 14}
 }

3.const声明的时候必须赋值操作

{
            //常量在声明的时候 必须赋值操作 
            // const a; //Uncaught SyntaxError: Missing initializer in const declaration
            // a = 1;
}

4.不能提升,并且不能重复声明

{
            //常量是块作用域  并且不能提升 并且不能重复声明
            // console.log(a);
            //ReferenceError: Cannot access 'a' before initialization
 } 

{
            const a = 1;
            //const a = 1;
            //Uncaught SyntaxError: Identifier 'a' has already been declared
 }

5.let const 声明变量不再是window的属性了

//使用const let 声明的全局变量 不再是window的属性了
        // var a = 1;
        // let a = 1;
        const a = 1;
        console.log(window.a);
        //undefined

2.变量的解构赋值

1.数组的解构赋值

1.解构赋值的方法

//1.解构赋值方法
        {
            const arr = [3, 5, 7, 9];
            let [a, b, c, d] = arr; 
            //声明了 a b c d 4个变量  放在数组结构中,去接受数组的值
            console.log(a, b, c, d);
            // 3 5 7 9
        }

2.解构失败 返回undefined

//2.解构失败 返回undefined
        {
            let [a, b] = [1];
            console.log(a, b) 
            // 1 undefined
        }

3.不完全解构 也可以完成

//3.不完全解构 也可以完成
        {
            let [a] = [1, 2];
            console.log(a) 
            //1
        }

4.可以给解构赋值的变量设置默认值(可设可不设)

//4.可以给解构赋值的变量设置默认值(可设可不设)
        {
            const [a = 2, b = 1] = [9];
            console.log(a, b)
             //9 1
        }

5.可以使用rest参数(…) 必须写在最后一个 是一个数组,包含了剩余没有解构的元素

//5.可以使用rest参数(...)  必须书写在最后一个  是一个数组,包含了剩余没有解构的元素
        {
            const [a, b, ...c] = [1, 2, 3, 4, 45, 6, 7, 8, 99];
            console.log(a, b, c) //1 2 [3, 4, 45, 6, 7, 8, 99]
        }

6.多维数组也可以进行匹配

//6.多维数组也可以进行匹配
        {
            const arr = [1, [2, 3, [4, [5]], 6], 7];
            const [a, [b, c, [d, [e]], f], g] = arr;
            console.log(a, b, c, d, e, f, g);
            //1 2 3 4 5 6 7
        }

7.交换两个变量练习

{
            let a = 1;
            let b = 2;
            [a,b] = [b,a];
            console.log(a,b);
            // 2 1
 }

8.解构赋值练习2

  • 变量未声明之前不能使用
//解构赋值练习2:
        {
            let [foo = hoo, hoo = 2] = [];
            console.log(foo, hoo) 
            //ReferenceError: Cannot access 'hoo' before initialization
            //在初始化之前无法访问'hoo'
        }

9.解构赋值练习3

 
//练习1:如果想要获取数组的第一个和最后一个值怎么办(使用解构赋值)
let arr = [1, 2, 3];
// 由于数组本质是特殊的对象,因此可以对数组进行对象属性的解构
let { 0: first, [arr.length - 1]: last } = arr;
 
console.log(first)
console.log(last)

2.对象的解构赋值

1.对象解构赋值方法

const obj = {
            name: "laoli",
            age: 19,
            sex: "nan",
            fn1: function () {
 
            }
        }
 
        {
            //解构对象,对象的key和value(变量名) 相等的时候 可以简写
            //对象的解构主要也是掌握 key的一一对应关系
            const {
                name,
                age,
                sex,
            } = obj;
 
            console.log(name, sex, age);
            //laoli nan 19
        }

2.对象解构赋值也可以给默认值

<script>
        const obj = {
            name: "laoli",
            age: 19,
            sex: "nan",
            fn1: function () {
 
            }
        }
 
        {
            const{
                name = "rolls",
                age,
                score = 90
            } = obj;
            console.log(name,age,score)
            //laoli 19 90
        }
    </script>

3…可以嵌套解构

{
            //可以嵌套解构
            const obj = {
                name: "laoli",
                score: [100, 90, 80]
            }
            const {
                name,
                score: [ch, ma, en]
            } = obj;
            console.log(name, ch, ma, en) //laoli 100 90 80
 }

4.解构赋值应用1

{
            //解构赋值的应用1
            const {
                log,
                dir
            } = console;
 
            log(1);//1
            dir(1);//1
 
            const {
                create
            } = Object;
            log(create(null)) //{}
 
 }
 

5.解构赋值应用2-函数传参

{
            // 解构赋值的应用2
            const fn = function ([a, b, c, d]) {
                console.log(a, b, c, d)
            }
            fn([1, 2, 3, 4])
        }
 

6.函数的返回值接收

{
            //函数的返回值接受
            const fn = function () {
                return {
                    left: 10,
                    right: 20
                }
            }
 
            const {
                left,
                right
            } = fn();
        }

3.字符串的扩展

1.模板字符串

//模板字符串
        //模板字符串使用反引号,变量嵌套使用${} 里边可以书写基础运算
        const oBox = document.querySelector(".box");
        oBox.innerHTML = `
    <p>我的姓名是 <span>${obj.name==="lily"?obj.name:"你不配"}</span></p>
    <p>我的性别是 <span>${setSex(obj.sex)}</span></p>
    <p>我的年龄是 <span>${obj.age + 4}</span></p>
        `;

2.方法–去空格

{
            const str = "   rolls   royce   ";
 
            let newStr = "";
            for (let i = 0; i < str.length ; i++){
                if (str[i] === " ") {
                    continue;
                }
                newStr += str[i];
                
            }
            console.log(newStr)
 
 
            let newStr = str.replace(/\s+/g,"");
            console.log(newStr)
 
            let say = "你TMD就是个hp";
            console.log(say.replace(/TMD|hp/g,"***"))
        }

4.数组扩展

4-1.扩展运算符

1.展开数组

<script>
        const arr = [1, 2, 3, 4];
        console.log(arr); 
        //[1, 2, 3, 4] 原来
        console.log(...arr);
         //1 2 3 4  展开
 
        const arr2 = [1, 2, 2, ...arr, 5, 6];
        console.log(arr2);
        //(9) [1, 2, 2, 1, 2, 3, 4, 5, 6]
</script>

2.使用在传参上

const arr3 = [1, 2, 3, 4]
 
        function fn(a, b, c, d) {
            console.log(a + b + c + d);
        }
        fn(...arr3);
        //10

3.复制数组

const arr4 = [1, 2, 3, 4, 5];
        // const arr5 = arr4;
        // 上面这个只是地址的复制 arr5和arr4都指向一个数组
        // 复制数组
        const arr5 = [...arr4];
        console.log(arr5);
        //[1, 2, 3, 4, 5]
        console.log(arr5 === arr4)
        //false

4.合并数组

const arr4 = [1, 2, 3, 4, 5];
        const arr6 = [1, 2, 3, 4, 5];
        //合并数组
        const arr5 = [...arr4, ...arr6];
        console.log(arr5)
        //[1, 2, 3, 4, 5, 1, 2, 3, 4, 5]

5.展开字符串

const str = "hello";
        const arr7 = [...str];
        console.log(...str) 
        //h e l l o
        console.log(arr7)
        // ["h", "e", "l", "l", "o"]

6.解构赋值

//生成一个数组 (此时扩展运算符必须在最后一个)
        let [a, b, ...newarr] = [1, 2, 3, 4, 5, 5, 6, 8, 9];
        console.log(newarr);
        //(7) [3, 4, 5, 5, 6, 8, 9]

4-2.数组的新方法

1.from()

  • 从一个类似数组或可迭代对象创建一个新的,浅拷贝的数组实例
{
            const obj1 = {
                0: "a",
                1: "b",
                2: "c",
                length: 3
            }
            const obj2 = {
                0: "a",
                1: "b",
                2: "c"
            }
            //类数组的条件:1.key值从0开始依次自然递增,2.拥有length属性
            console.log(Array.from(obj1))
            //["a", "b", "c"]
            console.log(Array.from(obj2))
            //[]
}

2.of()

  • 创建一个具有可变数量参数的新数组实例,而不考虑参数的数量或类型

  • 如果传递一个参数并且是数字的时候,那么就会创建一个新数组,长度为这个数字
    弥补new Array的不足

{
            const arr1 = new Array(4, 5);
            console.log(arr1); //[4,5]
 
            const arr2 = new Array(4);
            console.log(arr2); //[,,,,]
            console.log([, , , , ].length) 
            //4  如果最后一个逗号后为空,则这个逗号是结尾
 
            const arr3 = Array.of(4);
            console.log(arr3);
            //[4]
 
            const arr4 = Array.of(4, 5);
            console.log(arr4);
            //[4, 5]
}

3.copyWithIn()

{
            /* copyWithIn();
            复制当前数组中的某些值, 覆盖当前数组中的某些值
                -
                参数1: 开始替换的位置 -
                参数2: 开始读取复制的位置 -
                参数3: 读取复制的结束位置(不包含), 如果不写 则默认到末尾 */
            const arr1 = [1, 2, 3, 4, 5, 6, 7, 8, 9]
            const reArr1 = arr1.copyWithin(1, 6, 8);
            console.log(arr1, reArr1)
  //(9) [1, 7, 8, 4, 5, 6, 7, 8, 9] (9) [1, 7, 8, 4, 5, 6, 7, 8, 9]
        }

4.fill()

  • 填充数组
{
            /* fill():填充数组
                    - 第一个参数就是填充的内容
                    - 第二个和第三个参数:填充的起始和结束位置 */
            const arr1 = [1, 2, 3, 4, 5, 6];
            const reArr1 = arr1.fill("a"); //全部填充
            console.log(arr1, reArr1) //改变原数组 返回改变后的数组
 
            const arr2 = [1, 2, 3, 4, 5, 6];
            const reArr2 = arr2.fill("a", 3, 6); //全部填充
            console.log(arr2, reArr2) //改变原数组 返回改变后的数组
//(6) ["a", "a", "a", "a", "a", "a"] (6) ["a", "a", "a", "a", "a", "a"]
  }

5.find()

  • 返回第一个匹配的元素(返回的是回调函数第一次返回true的item)
const arr = ["lao wang", "xiao wang", "li ly", "zhong wang", "da wang", "ni"];
            //返回第一个姓li的名字
            const re = arr.find(function (item, index) {
                /* if (item.startsWith("li ")) {
                    return true;
                } */
 
                return item.startsWith("li ");
            })
            console.log(re);
            //li ly

6.findIndex()

  • 返回第一个匹配的下标(返回的是回调函数第一次返回true的index)
const arr = ["lao wang", "xiao wang", "li ly", "zhong wang", "da wang", "ni"];
            //返回第一个姓li的名字
            const re = arr.findIndex(function (item, index) {
                return item.startsWith("li ");
            })
            console.log(re);
            //2

7.flat()

  • 拉平数组(数组扁平化)
{
            const arr1 = [1, 2, [3, 4]];
            console.log(arr1.flat(1))
            //(4) [1, 2, 3, 4]
 
            const arr2 = [1, 2, [3, [4, 5]]];
            console.log(arr2.flat(Infinity))
            //(5) [1, 2, 3, 4, 5]
}

8.entries()

  • 拿到了数组的键值对的遍历器对象

  • - 遍历器对象有一个next方法,可以依次遍历iterator中的内容

{
            const arr1 = ["a", "b", "c", "d", "e"];
            const iter = arr1.entries(); //返回的是一个iterator(遍历器对象)对象
            //遍历器对象有一个next方法,可以依次遍历iterator中的内容
            console.log(iter);
            /* Array Iterator {}
            __proto__: Array Iterator
            next: ƒ next()
            Symbol(Symbol.toStringTag): "Array Iterator"
            __proto__: Object */
            console.log(iter.next());
            //{value: Array(2), done: false}
            // Array(2) value: (2) [0, "a"]
            console.log(iter.next());
            //{value: Array(2), done: false}
            console.log(iter.next());
            //{value: Array(2), done: false}
            console.log(iter.next());
            //{value: Array(2), done: false}
            console.log(iter.next());
            //{value: Array(2), done: false}
            console.log(iter.next());
            //{value: undefined, done: true}
            console.log(iter.next());
            // {value: undefined, done: true}
 
            for (let i of arr1.entries()) {
                console.log(i) //拿到了 每一次的[key,value]的值
                /*  (2)[0, "a"]
                 (2)[1, "b"]
                 (2)[2, "c"]
                 (2)[3, "d"]
                 (2)[4, "e"] */
            }
            console.log(iter)
            //Array Iterator {}
        }

9.keys()

{
            const arr1 = ["a", "b", "c", "d", "e"];
            const iter = arr1.keys();
            console.log(iter)
            //Array Iterator {}
            console.log(iter.next())
            // {value: 0, done: false}
            console.log(iter.next())
            // {value: 1, done: false}
            console.log(iter.next())
            // {value: 2, done: false}
            console.log(iter.next())
            // {value: 3, done: false}
            console.log(iter.next())
            // {value: 4, done: false}
            console.log(iter.next())
            // {value: undefined, done: true}
            console.log(iter.next())
            // {value: undefined, done: true}
            for (let i of arr1.keys()) {
                console.log(i)
                //拿到了 每一次的[key,value]的值
                // 0 1 2 3 4
            }
            console.log(iter)
            //Array Iterator {}
 }

10.values()

{
            const arr1 = ["a", "b", "c", "d", "e"];
            const iter = arr1.values(); //返回的是一个iterator(遍历器对象)对象
            //遍历器对象有一个next方法,可以依次遍历iterator中的内容
            console.log(iter);
            console.log(iter.next());
            console.log(iter.next());
            console.log(iter.next());
            console.log(iter.next());
            console.log(iter.next());
            console.log(iter.next());
            console.log(iter.next());
            console.log(iter.next());
 
            for (let i of arr1.values()) {
                console.log(i) //拿到了 每一次的[key,value]的值
            }
            console.log(iter)
            //Array Iterator {}
        }

5.函数的扩展

5-1.函数的默认值

ES5

function fn(a, b) {
            //b是可选的,如果b没有被传递,则默认是0;
            b = b === undefined ? 0 : b;
            return a + b;
        }
        console.log(fn(1)) //1
        console.log(fn(1, 5)) //6
        console.log(fn(1, "h")) //1h

ES6

直接给参数一个默认值即可

function fn1(a, b = 0) {
            return a + b;
        }
        console.log(fn1(1)) //1
        console.log(fn1(1, 5)) //6
        console.log(fn1(1, "h")) //1h

5-2.rest参数

  • 使用rese参数,获取的是数组类型
{
            //...相当于整合了后边没有接受的值,只能放在最后一个
            const [a, ...b] = [1, 2, 3, 4, 5, 6];
            console.log(b); 
            //[2,3,4,5,6];
        }

{
            function fn1(...rest) {
                //arguments获取所有实参 是类数组类型
                // console.log(arguments)
                //Arguments(5) [1, 2, 3, 4, 5, callee: (...), Symbol(Symbol.iterator): ƒ]
 
                //使用rest参数 是数组类型
                console.log(rest);
                //(5) [1, 2, 3, 4, 5]
            }
            fn1(1, 2, 3, 4, 5)
        }

{
            function fn1(a, b, ...rest) {
                //arguments获取所有实参 是类数组类型
                // console.log(arguments)
 
                //使用rest参数 是数组类型
                console.log(rest); 
                //[3,4,5]
            }
            fn1(1, 2, 3, 4, 5)
        }

{
            // 封装一个函数,让函数计算所有实参的和
            function sum(...rest) {
                /* const re = rest.reduce(function (p, c) {
                    return p + c;
                },0)
                return re; */
 
                return rest.reduce(function (p, c) {
                    return p + c;
                }, 0)
            }
            console.log(sum(1, 2, 3, 4, 5, 6)) //21
        }
        {
            var fn = (...rest) => {
                return rest.reduce((p, c) => p + c)
            }
            console.log(fn(1, 2, 3, 4, 5, 6))
        }

5-3.箭头函数

1.箭头函数格式

const {
            log
        } = console;
        //1. 只有一个参数,并且函数体只有一个return
        //参数写在 =>前   函数体写在=>后  如果函数体只有一个return  则直接书写return后的语句 并且省略大括号
        /* function (a) {
            return a + 1;
        } */
 
        const fn1 = a => a + 1;
        console.log(fn1(1));
        //2
 
 
        //2.函数多个形参 或者没有形参
        const fn2 = (a, b) => a + b;
        log(fn2(1, 2)); 
        //3
 
        //3.当函数体有多句话 需要书写完整的函数体
        const fn3 = () => console.log(1);
        fn3();
        const fn4 = () => {
            let a = 1;
            let b = 2;
            console.log(a + b);
        }
        fn4();
 
 
        //练习
        /* function sum1(...rest) {
            return rest.reduce(function (p, c) {
                return p + c;
            }, 0)
        } */
 
        const sum1 = (...rest) => rest.reduce((p, c) => p + c, 0);
        console.log(sum1(1, 2, 3, 4, 5, 6)) //21

2.箭头函数this

/* 
            箭头函数:
                this:箭头函数没有自己的this(他的this不能在不同的环境中发生改变),
                    箭头函数的this在定义的时候就已经确定了,在箭头函数中使用this,其实是定义的时候他所在父级函数的this
        
        */
        const fn1 = () => console.log(this);
 
        fn1(); //w
 
        document.onclick = fn1; //w
 
        const obj = {
            name: "lily",
            do: fn1
        }
        obj.do(); //w
 
        const obj1 = {
            name: "lily",
            do: function () {
                fn1();
            }
        }
        obj1.do(); //w
 
        const obj2 = {
            name: "lily",
            do: () => {
                fn1();
            }
        }
        obj2.do(); //w
 
 
 
        const obj1 = {
            name: "lily",
            do: () => {
                // this-->window
                const fn1 = () => {
                    console.log(this); //window
                }
                fn1();
            }
        }
        obj1.do()
 
        const obj2 = {
            name: "lily",
            do: function () {
                // this--obj2
                const fn1 = () => {
                    console.log(this); //
                }
                fn1()
            }
        }
        // obj2.do()
        const fn3 = obj2.do;
        fn3();

3.箭头函数其他注意

  • 箭头函数不能当做构造函数

  • 箭头函数没有arguments对象

//1.箭头函数不能当作构造函数
        const fn1 = (name) => {
            this.name = name
        }
        // new fn1(); //fn1 is not a constructor
 
        //2.箭头函数没有arguments对象
        const fn2 = (...rest) => {
            console.log(rest)
            // console.log(arguments); //arguments is not defined
        }
        fn2(1, 2, 3, 4, 5)

6.Math的扩展

** 次方

   /* 
            Math的扩展
                1.n次方 旧方法:Math.pow();   新方法 : **运算符
        
        */
 
        console.log(Math.pow(3, 3))
        //27
        console.log(3 ** 3)
        //27
        console.log(2 ** 10)
        //1024
        console.log(2 ** 1000)
        //1.0715086071862673e+301
 
        console.log(2 ** 2 ** 3) //2的8次方  从右向左计算
        //256

进制

        /* 
            进制表示:  
                二进制: 以 0b为开头
                八进制:以0o开头
        
        */
        let num1 = 0b110; //二进制
        console.log(num1); //打印的时候是转换成了10进制 
        //6
        let num2 = 010; //旧版本提供了定义八进制的写法 前边加一个0
        console.log(num2);
        //8
        let num3 = 0o10; //新版本提供了定义八进制的写法 前边加一个0o
        console.log(num3);
        //8

Math.trunc()

  • 将数字的小数部分去掉,只保留整数部分
 
        /* 
            Math.trunc()方法会将数字的小数部分去掉,只保留整数部分
         */
 
        console.log(Math.trunc(1.21)) //1
        console.log(Math.trunc(-1.21)) //-1
        console.log(Math.trunc("-1.21a")) //NaN
 

Math.sign()

  • 判断一个数字是正数 负数 还是NaN
        Math.sign() 判断一个数字的正数还是负数 还是0 或者是NaN
                -返回值是-1 则代表负数
                - 返回值是0 代表0
                - 返回值是1 代表正数
 
        console.log(Math.sign(-3))//-1
        console.log(Math.sign(0))//0
        console.log(Math.sign(4))//1

Math.sqwt()

  • 平方根
      Math.sqrt()平方根
 
 
console.log(Math.sqrt(2))//1.4142135623730951

Math.cbrt()

  • 立方根
 
    	  Math.cbrt()立方根
       console.log(Math.cbrt(27))//3

Math.hypot()

  • 求所有参数平方根的和
  Math.hypot() 求所有参数平方和的平方根
        console.log(Math.hypot(3, 4)) //5

7.Number扩展

Number.isFinite(i)

  • 判断是否有最大的数
  
        console.log(Number.isFinite(3)) //true
        console.log(Number.isFinite(Infinity)) //false

Number.isNaN(i)

  • 判断是否是NaN
        console.log(isNaN("a")); //true  会转换成number 然后判断
        console.log(Number.isNaN("a")); //false  如果是NaN就返回true
        console.log(Number.isNaN(NaN)); //true  如果是NaN就返回true
 

Number.isInteger(i)

  • 判断是否是整数
<script>
        console.log(Number.isInteger(3));//true
        console.log(Number.isInteger(3.1));//false
</script>

Number.parseInt(str)

  • 将字符串转换为对应的数值

8.对象的扩展

8-1.对象的简写

1.属性的简写

let [name, age, sex] = ["xiaowang", 20, "女"];
        let p1 = {
            name: name,
            age: age,
            sex: sex
        }
        console.log(p1);

//在es6中,对象的key和value如果相同,则可以简写
        let p2 = {
            name,
            age,
            sex
        }
        console.log(p2);

2.方法的简写

//如果对象的key 和 value(必须是变量) 相同,则可以简写一个key即可
        //函数不建议简写为箭头函数,而是省略function的简写
        let [name, age, sex] = ["xiaowang", 20, "女"];
        let p1 = {
            name: name,
            age: age,
            sex: sex
        }
        console.log(p1);
 
        let p3 = {
            name,
            age,
            sex,
            do: function () {
                console.log("eat")
            }
        }
        p3.do();
 
        let p4 = {
            name,
            age,
            sex,
            do() {
                console.log("eat")
            }
        }
        p4.do();

8-2属性表达式

//假设变量a 保存的是obj的key值,
        const a = "age";
        //要把a保存的key值放入对象中
        const obj = {
            //对象不会把key解析为一个变量,因为key都是字符串
            a: 18,
            //当对象的key用变量保存的时候,使用时添加中括号,可以把变量解析
            [a]: 19
        }
        console.log(obj)
        //{a: 18, age: 19}

// 在ES6中,支持key发生变化
        let a = "name";
        let b = "sex";
        let p6 = {
            [a]: "laowang",
            [b + "1"]: "nv"
        }
        console.log(p6)

1.特殊例子

//表达式还可以用于定义方法名
        //属性名可以写变量了,但是对象的key值解析后永远是一个字符串
        const o1 = {};
        const o2 = {};
        const obj1 = {
            [o1]: 12,
            [o2]: 13
        }
        console.log(obj1[o1]) //13

8-3.对象的扩展运算符

let { a, b, ...c } = {
            a: 1,
            b: 2,
            c: 3,
            d: 4,
            e: 5
        }
        console.log(c)

8-4.对象新增的方法

1.Object.is()

 //Object.is 相当于 ===   只不过修复了NaN不等NaN
        console.log(Object.is(1, 1)) //true
        console.log(Object.is(1, 2)) //false
        console.log(Object.is(1, "1")) //false
        console.log(Object.is({}, {})) //false
        console.log(Object.is({}, [])) //false
        console.log(Object.is(true, true)) //true
        console.log(Object.is(undefined, null)) //false
        console.log(Object.is(NaN, NaN)) //true

2.Object.assign()

const obj1 = {
            a: 1,
            b: 2,
        }
        const obj2 = {
            c: 3,
            d: 4
        }
        const obj3 = {
            a: 5,
            e: 6
        }
 
        //Object.assign是把后边的所有对象合并到第一个参数中去了,并没有创建一个新的对象
        const re1 = Object.assign(obj1, obj2);
        //{a: 1, b: 2, c: 3, d: 4}
        console.log(re1 === obj1) //true
        console.log(re1 === obj2) //false
 
 
        //合并对象的时候,如果有重名的则会覆盖
        const re2 = Object.assign(obj1, obj2, obj3);
        //{a: 5, b: 2, c: 3, d: 4, e: 6}
        console.log(re2);

3.赋值一个对象(浅拷贝)

 //原始深拷贝和浅拷贝(让你复制一个对象)
        const obj4 = {
            a: 1,
            b: 2,
            c: {
                d: 1
            }
        }
        //浅拷贝一份obj4
        const obj5 = {};
        for (let key in obj4) {
            obj5[key] = obj4[key]; //如果是基本类型值,则直接赋值,如果是引用类型值,则把地址赋值过去了
        }
        console.log(obj5 === obj4) //false 
        console.log(obj5.c === obj4.c) //true

4.assign()的拷贝作用

//Object.assign()的拷贝作用
        const obj6 = {
            a: 1,
            b: 2,
            c: {
                d: 1
            }
        }
        const obj7 = Object.assign({}, obj6); //把Obj6合并到空对象中,就得到一次拷贝(浅拷贝)
        console.log(obj7 === obj6); //false
        console.log(obj7.c === obj6.c); //true

9.新增数据类型

        /* 
            js数据类型:
                基本:String Boolean Number Null Undefined Symbol BigInt
                引用:Object
    
         */
 
        const obj1 = {
            name: "laowang",
            age: 18,
            sex: "nv",
            do: "eat",
            think: "PhP是不是世界上最好的语言",
        }
 
        //obj1对象可能你不知道里边会有哪些属性
        //当你需求给对象设置一些属性和方法的时候,可能重名覆盖其他的属性,或者可能被其他人覆盖你的属性
        obj1.do = "drink"; 
        //你可以能覆盖原有属性,也可能被人覆盖
        {name: "laowang", age: 18, sex: "nv", do: "drink", think: "PhP是不是世界上最好的语言"}
 
        //为了避免上边的情况,我们希望设置一个独一无二的值,永远不可能覆盖别人,也永远不可能被人覆盖
 
        //所以symbol类型诞生,symbol类型每次创建的值都是独一无二的

9-1.Symbol

创建Symbol()

 
 
        //1.使用symbol创建一个值(不需要new)
        //Symbol的参数,没有任何作用,只是为了方便我们识别是哪一个值
        const sy1 = Symbol("sy1");
        const sy2 = Symbol("sy2");
        console.log(sy1);
        // Symbol(sy1)
        console.log(sy2);
        // Symbol(sy2)
        console.log(sy1 == sy2); //false
        console.log(typeof sy1) //'symbol'

使用Symbol()

//给obj1扩展一个属性(不能覆盖别人 也不能被人覆盖)
        /* obj1[Symbol("think")] = "hello"; //如果这样设置的话,你永远都获取不到设置的这个值了
        obj1[Symbol("say")] = "world"; 
        console.log(obj1) */
 
        const sy3 = Symbol("think");
        const sy4 = Symbol("say");
        obj1[sy3] = "hello";
        obj1[sy4] = "world";
        obj1[Symbol()] = "baibai";
        console.log(obj1)
        //使用
        console.log(obj1[sy3]);
        //hello
        console.log(obj1[sy4]);
        //world
 
 
        // 1.Symbol传入的参数 没有意义  方便识别
        //2.Symbol不能使用new调用,而是直接使用
        //3.Symbol不能转数字
        //4.要用变量保存这个Symbol 否则以后就拿不到了
        //5.Symbol默认不能被遍历出来
 
        for (let key in obj1) {
            console.log(key);
        }

Object.getOwnPropertySymbol()

  const SymbolArr = Object.getOwnPropertySymbols(obj1); //拿到Symbol的值 组成一个数组
        console.log(SymbolArr)
        //[Symbol(think), Symbol(say), Symbol()]
        console.log(SymbolArr[0])
        //Symbol(think)
        console.log(obj1[SymbolArr[0]])
        //hello
         //获取symbol 的值
        console.log(obj1[SymbolArr[1]])
        //world
        console.log(obj1[SymbolArr[2]])
        //baibai
         //只有这样的遍历才能拿到 没有设置变量保存的Symbol的值
    </script>

9-2.BigInt

  • 大整形.定义方法:在数字后面添加一个n即可
//BigInt 大整型  一定是整数
 
        console.log((2 ** 53)) //计算不精确
        console.log((2 ** 53) + 1) //计算不精确
        console.log((2 ** 53) + 3) //计算不精确
        console.log(2 ** 1023) //计算不了
 
        //大整型 定义方法 在数字后添加一个n即可
        const bi1 = 1n;
        console.log(bi1) //1n
        console.log(typeof bi1); //"bigint"
        console.log((2n ** 53n) + 1n) //计算精确
 
        console.log(1n == 1) //true
        console.log(1n === 1) //false
 
        //类型转换和number区别不大
        console.log(Number(1n)) //number 1
        console.log(String(1n)) //string 1
        console.log(Boolean(1n)) //true
        console.log(Boolean(0n)) //false

10.新增数据结构

Set

new Set(arr)

 
        /* 
            Set类型,类似于数组,里边的值没有重复的
            需要使用new 实例化,实例化参数必须是一个拥有iterator接口的数据
        
         */
 
        // 数组
        const set1 = new Set([1, 2, 1, 2, 1, 2, 4, 3, 4, 5, 6, 2, 3, 4]);
        console.log(set1);
        //Set(6) {1, 2, 4, 3, 5, …}

new Set(string)

       //字符串
        const set2 = new Set('1212123566');
        console.log(set2);
        //Set(5) {"1", "2", "3", "5", "6"}
 

new Set(object)

          //对象
        /* const set3 = new Set({
            //TypeError: object is not iterable (cannot read property Symbol(Symbol.iterator))
            name: 1,
            age: 2
        }) */
 
        //

new Set(伪数组)

 
        const oLis = document.querySelectorAll("ul li");
        const set3 = new Set(oLis);
        //NodeList(4) [li, li, li, li]
        console.log(set3);
        //Set(4) {li, li, li, li}
 

使用-数组去重

 
        //使用:数组去重
        const arr = [1, 2, 1, 2, 1, 2, 4, 3, 4, 5, 6, 2, 3, 4];
        const set4 = new Set(arr);
        console.log(set4) //set的格式 
        //Set(6) {1, 2, 4, 3, 5, …}
 
        //set也是一个拥有iterator属性的类型,可以使用三点运算符展开
        console.log(...set4)
        //1 2 4 3 5 6
        const newArr = [...set4];
        console.log(newArr)
        //(6) [1, 2, 4, 3, 5, 6]
 

使用-字符串去重

 
        //字符串去重 set不能转字符串的话 可以借助于数组来进行转换
        const str = "ababcdeehfhgd";
        const set5 = new Set(str);
        console.log(set5);
        Set(8) {"a", "b", "c", "d", "e", …}
 
        const strArr = [...set5];
        console.log(strArr);
        // ["a", "b", "c", "d", "e", "h", "f", "g"]
        console.log(strArr.join(""));
        //abcdehfg
        console.log(String(set5)) 
        //[object Set]

Set的方法

size

  const {
            log
        } = console;
 
        const arr = [1, 2, 1, 2, 1, 2, 4, 3, 4, 5, 6, 2, 3, 4];
        const set4 = new Set(arr);
        console.log(set4);
        //Set(6) {1, 2, 4, 3, 5, …}
 
        //size:长度
        log(set4.size); 
        //6

add()

        //add添加  返回添加后的set类型
        set4.add(11);
        const re1 = set4.add(2);
        log(set4)
        //Set(7) {1, 2, 4, 3, 5, …}
        log(re1)
        //Set(7) {1, 2, 4, 3, 5, …}
 

delete()

      //delete 删除
        const re2 = set4.delete(2);
        console.log(re2)
        //true 
        //返回值是 布尔值 代表是否删除成功
        console.log(set4)
        //Set(6) {1, 4, 3, 5, 6, …}

has()

        //has()判断是否存在
        console.log(set4.has(9)) //false
 

clear()

 
         //clear清空
        log(set4.clear()) 
        //undefined  clear没有返回值
        log(set4) //被清空了
        //Set(0) {}

entries()/key()/value()

 
        //entries  //set类型的key和value都是相等的
        const re3 = set4.entries();
        log(re3)
        //SetIterator {1 => 1, 4 => 4, 3 => 3, 5 => 5, 6 => 6, …}
 
        log(re3.next())
        // {value: Array(2), done: false}
        log(re3.next())
        // {value: Array(2), done: false}
        log(re3.next())
        // {value: Array(2), done: false}
        log(re3.next())
        // {value: Array(2), done: false}
        log(re3.next())
        // {value: Array(2), done: false}
        log(re3.next())
        // {value: Array(2), done: false}
        log(re3.next())
        //{value: undefined, done: true} 
        for (let keys1 of re3) {
            console.log(keys1)
            /* 
                (2) [1, 1]
                (2) [4, 4]
                (2) [3, 3]
                (2) [5, 5]
                (2) [6, 6]
                (2) [11, 11]
             */
        } 
 
 
        //keys
        const re4 = set4.keys();
        log(re4)
        //SetIterator {1, 4, 3, 5, 6, …}
 
        //values
        const re5 = set4.values();
        log(re5)
        //SetIterator {1, 4, 3, 5, 6, …}

for…of…

 //set除了自身的entries keys values可以被forof遍历,自身也可以被遍历 得到一个value值
        for (let values1 of set4) {
            console.log(values1)
            // 1 4 3 5 6 11
        }
        console.log(set4)

forEach()

//set也可以被forEach遍历
        set4.forEach((item, index) => {
            console.log(item, index);
            /* 
                1 1
                4 4
                3 3
                5 5
                6 6
                11 11
             */
        })

小练习

//遍历100次 每次随机生成0-9的数字,看能不能把所有的1-10数字全部输出
        const set5 = new Set();
        for (let i = 0; i < 100; i++) {
            set5.add(Math.floor(Math.random() * 10))
        }
        if (set5.size === 10) {
            console.log("ok~")
        } else {
            console.log("no~")
        }
        console.log(set5)

Map

  • 解决了对象中key必须被解析成字符串的问题

  • Map是一种类似于Object的数据结构,但是key可以使任意类型的值

new Map()

 
        /* 
            Map类型:解决了对象中 key必须被解析成字符串的问题
            Map是一种类似于Object的数据结构,但是key可以是任意类型的值
        
         */
        const obj1 = {};
        const obj2 = {
            a: 1
        };
 
        const map1 = new Map([
            ["name", "lily"],
            ["age", 18],
            [obj1, "haha"],
            [obj2, "hehe"],
            [true, "heihei"],
            [2, "gege"]
        ])
        console.log(map1);
        /* 
            Map(6) {"name" => "lily", "age" => 18, {…} => "haha", {…} => "hehe", true => "heihei", …}
                [[Entries]]
                0: {"name" => "lily"}
                1: {"age" => 18}
                2: {Object => "haha"}
                3: {Object => "hehe"}
                4: {true => "heihei"}
                5: {2 => "gege"}
                size: (...)
                __proto__: Map
         */

size

 
        //size:长度
        console.log(map1.size);
        //6

set()

   	   //set设置
        const arr = [1, 2, 3]
        map1.set(arr, "shuzu")
        console.log(map1)
        /* Map(7) {"name" => "lily", "age" => 18, {…} => "haha", {…} => "hehe", true => "heihei", …}
           [[Entries]]
           0: {"name" => "lily"}
           1: {"age" => 18}
           2: {Object => "haha"}
           3: {Object => "hehe"}
           4: {true => "heihei"}
           5: {2 => "gege"}
           6: {Array(3) => "shuzu"}
           size: (...)
           __proto__: Map */

get()

 
        //get 获取
        const re1 = map1.get(obj1);
        const re2 = map1.get(true);
        console.log(re1);
        //haha
        console.log(re2);
        //heihei

has()

 
        //has 判断key是否存在
        const re3 = map1.has([1, 2, 3]);
        console.log(re3) 
        //false   地址值的比较
 
        const re4 = map1.has(obj1);
        console.log(re4) 
        //true  变量,保存的是地址

delete

       //delete删除
        map1.delete(obj2);
        console.log(map1)
        /* 
            Map(6) {"name" => "lily", "age" => 18, {…} => "haha", true => "heihei", 2 => "gege", …}
                [[Entries]]
                0: {"name" => "lily"}
                1: {"age" => 18}
                2: {Object => "haha"}
                3: {true => "heihei"}
                4: {2 => "gege"}
                5: {Array(3) => "shuzu"}
                size: (...)
                __proto__: Map
         */

clear()

 	//clear清空
        /* map1.clear();
        console.log(map1)
        //Map(0) {}
         */

entries()/key()/value()

      
      
        //entries
        const re5 = map1.entries();
        console.log(re5);
        //MapIterator {"name" => "lily", "age" => 18, {…} => "haha", true => "heihei", 2 => "gege", …}
        for (let values1 of re5) {
            console.log(values1)
        }
 
 
        //keys
        const re6 = map1.keys();
        //MapIterator {"name", "age", {…}, true, 2, …}
        for (let values1 of re6) {
            console.log(values1)
            /* 
             name
             age
             {}
             true
             2
             (3) [1, 2, 3]
            
            */
        }
 
        //values
        const re7 = map1.values();
        for (let values1 of re7) {
            console.log(values1)
            /* 
                lily
                 18
                 haha
                 heihei
                 gege
            */
        }
 

for…of…

//map也可以自己使用forof
        for (let values1 of map1) {
            console.log(values1);
        }

forEach

 
        //forEach
        map1.forEach((item, index) => {
            console.log(item, index)
            /* 
                (2) ["name", "lily"]
                (2) ["age", 18]
                (2) [{…}, "haha"]
                (2) [true, "heihei"]
                (2) [2, "gege"]
                (2) [Array(3), "shuzu"]
            */
        })
 
       

11.iterator

1.手写iterator

<script>
        const arr = ["a", "b", "c", "d"];
 
        Array.prototype.myIterator = function () {
            //声明一个累加器,用来判断遍历是否完成
            let index = 0;
            //原型对象的方法this指向实例化对象
            //返回一个对象,对象中有next方法,可以依次拿到值
            // console.log(this)
            const _this = this; //保存当前的this指向,用来在其他地方使用
            return {
                // 调用next方法后返回一个对象:{value:XXX,done:false}
                next: function () {
                    // console.log(this) //指向的是当前next所在的对象,不是当前的数组
                    if (index < _this.length) {
                        return {
                            value: _this[index++],
                            done: false
                        }
                    } else {
                        return {
                            value: undefined,
                            done: true
                        }
                    }
                }
            }
        }
 
        const re = arr.myIterator();
        console.log(re)
        console.log(re.next())
        console.log(re.next())
        console.log(re.next())
        console.log(re.next())
        console.log(re.next())
        console.log(re.next())
        console.log(re.next())
    </script>

2.数据类型的iterator

<ul>
        <li></li>
        <li></li>
        <li></li>
        <li></li>
    </ul>
    <script>
        const oLis = document.querySelectorAll("ul li");
        console.log(oLis)
        // NodeList(4) [li, li, li, li]
         //nodeList对象拥有Iterator接口
 
        function fn1() {
            console.log(arguments);
        }
        fn1(1, 2, 3, 4) 
        //Arguments(4) [1, 2, 3, 4, callee: ƒ, Symbol(Symbol.iterator): ƒ]
        //arguments 对象拥有Iterator接口
 
 
        console.log([]); //Array 对象拥有Iterator接口
 
        console.log(new Set()); //set 对象拥有Iterator接口
 
        console.log(new Map([])); //Map 对象拥有Iterator接口
 
        console.log(new String("123")) //String 对象拥有Iterator接口
 
        console.log(new Number(1)); //number 没有Iterator接口
 
        console.log({}); //Object 没有Iterator接口
 
 
 
        //其实for of 就是对Iterator接口的消费
        //手动获取它们的Iterator接口  模拟for of运行过程
        const arr = ["a", "b", "c", "d"];
        //凡是拥有iterator接口的对象,都有一个Symbol(Symbol.iterator)方法,调用这个方法即可得到遍历当前对象的迭代器对象
        //直接通过arr的Symbol.iterator属性,获取获取到这个方法
        const re = arr[Symbol.iterator](); //获取到了数组的迭代器对象
        console.log(re);
        //Array Iterator {}
        console.log(re.next());
        // {value: "a", done: false}
        console.log(re.next());
        // {value: "b", done: false}
        console.log(re.next());
        // {value: "c", done: false}
        console.log(re.next());
        // {value: "d", done: false}
        console.log(re.next());
        // {value: undefined, done: true}
        console.log(re.next());
        //{value: undefined, done: true}
    </script>

3.for…of…

遍历NodeList
   <ul>
        <li></li>
        <li></li>
        <li></li>
        <li></li>
    </ul>
    <script>
        /* 
            for of 是ES6提供的对数据结构统一的遍历方式
            只要是部署了Iterator接口了类型,全部都可以使用for of 进行遍历迭代
            
            for of遍历拿到的是 value 而不是key
         */
 
        const oLis = document.querySelectorAll("ul li");
        console.log(oLis) //nodeList对象拥有Iterator接口
        //NodeList(4)
 
        for (let value of oLis) {
            console.log(value);
        }
        /* for (let i in oLis) {
            console.log(i);
            0
             1
             2
             3
             length
             item
             entries
             forEach
             keys
             values
        } */

遍历arguments
 
        function fn1() {
            console.log(arguments);
            //  Arguments(4) [1, 2, 3, 4, callee: ƒ, Symbol(Symbol.iterator): ƒ]
            for (let value of arguments) {
                console.log(value); // 1 2 3 4
            } 
        }
        fn1(1, 2, 3, 4) //arguments 对象拥有Iterator接口

遍历Array
 
        const arr = ["a", "b", "c", "d"]
        console.log(arr); //Array 对象拥有Iterator接口
        //(4) ["a", "b", "c", "d"]
        for (let value of arr) {
            console.log(value);
            /* 
                a
                 b
                 c
                 d
            */
        }
        for (let value of arr.entries()) {
            console.log(value);
            /* 
             (2) [0, "a"]
                [1, "b"]
                [2, "c"]
                [3, "d"]
 
            */
        }

遍历Set
 
        const set = new Set(["a", "b", "c", "e"])
        console.log(set); //set 对象拥有Iterator接口
        //Set(4) {"a", "b", "c", "e"}
        for (let value of set) {
            console.log(value);
            // a b c e
        }

遍历Map
 const map1 = new Map([
            [{}, "haha"],
            [true, "hehe"]
        ])
        console.log(map1);
        //Map(2) {{…} => "haha", true => "hehe"}
        //Map 对象拥有Iterator接口
        for (let value of map1) {
            console.log(value);
            /* 
                (2) [{…}, "haha"]
                (2) [true, "hehe"]
            */
        }

遍历String
       
        const str = "123";
        console.dir(new String("123")) //String 对象拥有Iterator接口
        for (let value of str) {
            console.log(value);
            // 1 2 3
        }
 

number和object没有
 
        // console.log(new Number(1)); //number 没有Iterator接口
 
        const obj = {
            name: "laoli",
            age: 18
        }
        console.log(obj); //Object 没有Iterator接口
        for (let value of obj) {
            console.log(value); //obj is not iterable
        }
 
 
 
        //

12.class

<script>
        /* 
            ES5定义类
         */
 
        /* function Person(name, age) {
            this.name = name;
            this.age = age;
        }
        Person.prototype.eat = function () {
            console.log("吃饭");
        } */
 
        /* 
            ES6语法糖 
            使用class 定义类
        
         */
 
        class Person {
            //constructor:当new的时候,会自动调用这个方法,必须存在(书写公有属性)
            constructor(name, age) {
                //其实写在构造函数中的属性 都放在了constructor中
                this.name = name;
                this.age = age;
            }
            //直接书写在class中的方法 其实就是原型对象上的公有方法
            eat() {
                console.log("吃饭");
            }
 
            //如果直接在class中书写属性,则还是实例化对象所有的(这样写无法传参)
            sex = "男";
 
            // static定义的属性和方法 其实都是静态属性和方法  是构造函数对象上的
            static hi = "hello";
        }
 
        //也可以通过原型对象扩展原型方法
        Person.prototype.drink = function () {
            console.log("大乌苏");
        }
 
        const p1 = new Person("laowang", 20)
        const p2 = new Person("xiaowang", 10)
        console.log(p1, p2)
        //Person {sex: "男", name: "laowang", age: 20}age: 20name: "laowang"sex: "男"__proto__: Object Person {sex: "男", name: "xiaowang", age: 10}
        console.log(p1.eat === p2.eat)
        //true
        console.dir(Person)
        // class Person
    </script>

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值