Skip to content
On this page

25个ES语法

01. 严格模式【ES5】

  1. 文件开头使用: ‘use strict’ 进行声明使用严格模式
  2. 严格模式下语法和行为改变
* 必须用var声明变量。非严格模式情况下,不适用var声明的变量是属于window的一个属性
 * 禁止自定义的函数中的this指向window。比如:function Person(name){this.name=name}=》Person('jiliang')=》错误;new Person(‘jiliang’)=》正确
 * 创建eval作用域。eval函数可以解析函数的字符串,如果是非严格模式,变量易受污染
 * 对象不能有重名属性

02. json对象的扩展【ES5】

JSON.stringfy(obj/arr) ==》将  js对象(数组)转换为json对象(数组);将对象(数组)转换为字符串
JSON.parse(str)==》json对象(数组)转换为js对象(数组);将字符串转换为对象(数组)

03. Object对象方法扩展【ES5】

  • Object.create(prototype, [descriptors])
  • Object.defineProperties(object, descriptors)
html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>03_Object扩展</title>
</head>
<body>
<!--
ES5给Object扩展了一些静态方法, 常用的2个:
1. Object.create(prototype, [descriptors])
  * 作用: 以指定对象为原型创建新的对象
  * 为新的对象指定新的属性, 并对属性进行描述
    - value : 指定值
    - writable : 标识当前属性值是否是可修改的, 默认为false
    - configurable: 标识当前属性是否可以被删除 默认为false
    - enumerable: 标识当前属性是否能用for in 枚举 默认为false
2. Object.defineProperties(object, descriptors)
  * 作用: 为指定对象定义扩展多个属性
    * get :用来获取当前属性值得回调函数
    * set :修改当前属性值得触发的回调函数,并且实参即为修改后的值
   * 存取器属性:setter,getter一个用来存值,一个用来取值
-->
<script type="text/javascript">
        var obj1 = {userName: 'jiliang', sex: ''}
        var obj2 = Object.create(obj1, {
            age: {
                value: 28,
                writable: true, // 标识当前属性值可以修改
                configurable: true, // 标识当前属性可以被删除
                enumerable: true // 标识当前属性可以for in枚举
            }
        })
        console.info(obj2)

        var obj = {"firstName": 'huang', "lastName": 'jiliang'};
        // 为obj对象定义扩展fullName属性
        Object.defineProperties(obj, {
            fullName: {
                // get为获取属性的值,获取扩展属性值的时候,get方法自动调用.惰性求值,只有获取的时候才会调用
                get: function() {
                    return this.firstName + " " + this.lastName 
                },
                // 监听扩展属性,当扩展属性发生变化的时候自动调用,自动调用后会将变化的值作为实参注入到set函数
                set: function(data) {
                    console.info("set() ==>"+data)
                    var arrData = data.split(' ');
                    console.info("更改后,firstName:"+arrData[0])
                    console.info("更改后,lastName:"+arrData[1])
                }
            }
        })
        console.info(obj.fullName)
        obj.fullName = 'shuai ge'

        //////////////扩展////////////////
        /* 
            对象本身的两个方法
            get propertyName(){}  用来得到当前属性值的回调函数

            set propertyName(){}  用来监视当前属性值变化的回调函数

         */
            var tempObj = {
                name: 'jiliang',
                age: 29,
                get allMessage() {
                    return this.name + "  " + this.age
                },
                set allMessage(data) {
                    cosnole.info("allMessage property:"+ data)
                }
            }
            console.info(tempObj.allMessage)

</script>
</body>
</html>

04. 数组的扩展【ES5】

html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>04_Array扩展</title>
</head>
<body>
<!--
1. Array.prototype.indexOf(value) : 得到值在数组中的第一个下标
2. Array.prototype.lastIndexOf(value) : 得到值在数组中的最后一个下标
3. Array.prototype.forEach(function(item, index){}) : 遍历数组
4. Array.prototype.map(function(item, index){}) : 遍历数组返回一个新的数组,返回加工之后的值
5. Array.prototype.filter(function(item, index){}) : 遍历过滤出一个新的子数组, 返回条件为true的值
-->
<script type="text/javascript">
  /*
   需求:
   1. 输出第一个6的下标
   2. 输出最后一个6的下标
   3. 输出所有元素的值和下标
   4. 根据arr产生一个新数组,要求每个元素都比原来大10
   5. 根据arr产生一个新数组, 返回的每个元素要大于4
   */
    var arr = [4,5,2,8,1,3,5,6]
    console.info(arr.indexOf(2));
    console.info(arr.lastIndexOf(5));
    arr.forEach(function(item, index) {
        console.info(`${item} => ${index}`)
    })
    var arr1 = arr.map(function(item, index) {
        return item + 10;
    })
    console.info(arr1)
    var arr2 = arr.filter(function(item, index){
        return item % 2 === 0
    })
    console.info(arr2)

</script>
</body>
</html>

05. Function的扩展call、apply、bind用法详解【ES5】

html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>05_Function扩展</title>
</head>
<body>
<!--
1. Function.prototype.bind(obj) :
  * 作用: 将函数内的this绑定为obj, 并将函数返回
2. 面试题: 区别bind()与call()和apply()?
  * 都能指定函数中的this
  * call()/apply()是立即调用函数
  * bind()是将函数返回
-->
<script type="text/javascript">
    var obj = {"userName": 'jiliang'};
    function foo(...data) {
        console.info(this, data)
    }
    // 函数的this指向window
    //foo(55);
    // 使用apply和call函数,让方法中的this指向指定对象
    //foo.call(obj, 22,33) // call方法直接从第二个参数开始,依次传入
    //foo.apply(obj, [22,33]) // apply方法第二个参数必须是数组,存放在数组里传

    // 使用bind的函数,绑定this完之后不会直接调用当前函数,而是将函数返回, 传参的方式和call一样
    var bar = foo.bind(obj, 99)
    // 调用同时,多传一个参数
    bar(88)
</script>
</body>
</html>

06. let、const、var关键字【ES6】

html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>01_let&const关键字</title>
</head>
<body>

<button>测试1</button>
<br>
<button>测试2</button>
<br>
<button>测试3</button>
<br>
<!--
***let
1. 作用:
  * 与var类似, 用于声明一个变量
2. 特点:
  * 在块作用域内有效
  * 不能重复声明
  * 不会预处理, 不存在提升
3. 应用:
  * 循环遍历加监听
  * 使用let取代var是趋势

*** const
    1. 作用:
      * 定义一个常量
    2. 特点:
      * 不能修改
      * 其它特点同let
    3. 应用:
      * 保存不用改变的数据
-->
<script type="text/javascript">
    let username = 'huang'
    // 将会报错,因为作用域内不可重复声明
    // let username = 'jiliang'
    console.info(username)

    var obj = document.getElementsByTagName('button');
    /* 
    for(var i = 0 , length = obj.length ; i < length ; i++) {
        var btn = obj[i]
        btn.onclick = function() {
            // 使用var不会循环监听
            console.info(i)
        }
    }
     */
    for(let i = 0 , length = obj.length ; i < length ; i++) {
        var btn = obj[i]
        btn.onclick = function() {
            // 使用var不会循环监听
            console.info(i)
        }
    }

    //////////////////////////////////
    // const 定义的常量一般是不可更改
    // 可以更改对象里的属性(比如:不可以修改个人,但是可以修改个人年龄)
    const man = {username: 'jiliang', age : 88};
    // Uncaught TypeError: Assignment to constant variable.
    // man = {password: 'huang'}
    console.info(man)

    man.age = 28
    console.info(man)

</script>
</body>

</html>

07. 变量的解构赋值【ES6】

html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>03_变量的解构赋值</title>
</head>
<body>
<!--
1. 理解:
  * 从对象或数组中提取数据, 并赋值给变量(多个)
2. 对象的解构赋值
  let {n, a} = {n:'tom', a:12}
3. 数组的解构赋值
  let [a,b] = [1, 'atguigu'];
4. 用途
  * 给多个形参赋值
-->
<script type="text/javascript">
    let obj = {username: 'jiliang', age: 28}
    // 原型方式获取对象属性值
    // let username = obj.username
    // let age = obj.age
    // console.info(username, age)
    // 解构赋值
    let {username, age} = obj
    console.info(username, age)
    // 原始方式
    function foo (obj) {
        console.info(obj.username, obj.age)
    }
    foo(obj)
    // 解构赋值调用
    function foo1 ({username, age}) {
        console.info(username, age)
    }
    foo1(obj)

    let arr = [1, 5, 3,'huang', 'jiliang']
    // 远是方式
    // 数组解构赋值
    let [, a, b, c] = arr
    console.info(a , b ,c)

</script>
</body>
</html>

08. 模板字符串【ES6】

html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>04_模板字符串</title>
</head>
<body>
<!--
1. 模板字符串 : 简化字符串的拼接
  * 模板字符串必须用 `` 包含
  * 变化的部分使用${xxx}定义
-->
<script type="text/javascript">
    let firstName = 'huang', lastName = 'jiliang'
    // 原始方式
    console.info(firstName + " " + lastName)
    // 模板字符串
    console.info(`${firstName} ${lastName}`)
</script>
</body>
</html>

09. 对象的简写方式【ES6】

html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>05_简化的对象写法</title>
</head>
<body>
<!--
简化的对象写法
* 省略同名的属性值
* 省略方法的function
-->
<script type="text/javascript">
  let x = 10;
  let y = 20;
    // 原始方式
    let obj = {
        x: x,
        y: y,
        setX: function (x) {
            return this.x = x
        }
    }
    // ES6对象简写方式
  let point = {
    x, // 同名的属性可以省略不写
    y,
    setX (x) {this.x = x}  // 可以简写function
  };
</script>
</body>
</html>

10. 箭头函数详解【ES6】

html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>06_箭头函数</title>

</head>
<body>
    <button id="btn1">测试箭头函数this_1</button>
    <button id="btn2">测试箭头函数this_2</button>


<!--
* 作用: 定义匿名函数
* 基本语法:
  * 没有参数: () => console.log('xxxx')
  * 一个参数: i => i+2
  * 大于一个参数: (i,j) => i+j
  * 函数体不用大括号: 默认返回结果
  * 函数体如果有多个语句, 需要用{}包围,若有需要返回的内容,需要手动返回
* 使用场景: 多用来定义回调函数

* 箭头函数的特点:
    1、简洁
    2、箭头函数没有自己的this,箭头函数的this不是调用的时候决定的,而是在定义的时候处在的对象就是它的this
    3、扩展理解: 箭头函数的this看外层的是否有函数,
        如果有,外层函数的this就是内部箭头函数的this,
        如果没有,则this是window。
-->
<script type="text/javascript">
    // 形参参数情况
    // 1.无形参(小括号必须存在)
    let foo = () => {console.info("我是箭头函数")}
    foo()
    // 2.只有一个形参(可以省略形参的小括号)
    let foo1 = (a) => {console.info(a)}
    let foo2 = a => {console.info(a)}
    foo1("有小括号")
    foo2("没有小括号")
    // 3.有两个及两个以上(小括号不可以省略))
    let foo3 = (a, b) => {console.info(a, b)}
    foo3("aaa", "bbb")

    // 函数体的情况
    // 1. 函数体只有一条语句或者表达式的时候{}可以省略.  省略{}的时候,会自动返回语句的结果;如果没有省略{} ,需要return返回
    let func1 = (x, y) => {return x + y}
    let func2 = (x, y) => x + y;
    console.info(func1(12, 10))
    console.info(func2(10, 12))
    // 2.函数体不止一条语句或者是表达式的情况 :{}不可以省略;如果需要返回值,需要使用return返回
    let func3 = (x, y) => {
        console.info("1111")
        return x + y
    }
    console.info(func3(15, 16))

    // 箭头函数的this指向
    let btn1 = document.getElementById("btn1");
    let btn2 = document.getElementById("btn2");
    btn1.onclick = function () {console.info(this)}
    //btn2.onclick = () => {console.info(this)}

    let obj1 = {}
    let obj = {
        "name": '箭头函数',
        getName : function()  {
            console.log(this);
            btn2.onclick = () => {
                console.log(this);
            }
        },
        getValue: () => {
            console.log(this);
            btn2.onclick = () => {
                console.log(this);
            }
        }
    }

    // let fun1 = obj.getName();
    let fun1 = obj.getValue();

</script>

</body>
</html>

11. 三点运算符【ES6】

html
<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>07_3点运算符</title>
    </head>
    <body>
        <!--
* 用途
1. rest(可变)参数
    * 用来取代arguments 但比 arguments 灵活,只能是最后部分形参参数
2. 扩展运算符
  let arr1 = [1,3,5];
  let arr2 = [2,...arr1,6];
  arr2.push(...arr1);
-->
        <script type="text/javascript">
            function fun(...values) {
                // arguments伪数组.没有方法,只有length属性.arguments.callee()指向函数本身
                console.log(arguments);
                // arguments属于伪数组不可以遍历
                /* arguments.forEach(function(item, index) {
                    console.log(item, index);
                }); */
                console.log(values);
                // values可以进行遍历
                values.forEach(function(item, index) {
                    console.log(item, index);
                })
            }
            fun(1, 2, 3);
            // a为占位符
            function fun1 (a, ...values) {
                console.info(values)
            }
            fun1(1,2,3,4,5)
            // 扩展

            let arr1 = [1, 6]
            let arr2 = [2, 5, 7]
            // push arr1数组内所有数据
            arr2.push(...arr1);
            console.log(arr2)
            console.info(1,2,3,...arr1,9,8)
        </script>

    </body>
</html>

12. 形参默认值【ES6】

html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>08_形参默认值</title>
</head>
<body>
<!--
    * 形参的默认值----当不传入参数的时候默认使用形参里的默认值
    function Point(x = 1,y = 2) {
    this.x = x;
    this.y = y;
    }
-->
<script type="text/javascript">


</script>

</body>
</html>

13. promise对象原理详解【ES6】

html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>11_Promise对象</title>
</head>
<body>
<!--
1. 理解:
  * Promise对象: 代表了未来某个将要发生的事件(通常是一个异步操作)
  * 有了promise对象, 可以将异步操作以同步的流程表达出来, 避免了层层嵌套的回调函数(俗称'回调地狱')
  * ES6的Promise是一个构造函数, 用来生成promise实例
2. 使用promise基本步骤(2步):
  * 创建promise对象
    let promise = new Promise((resolve, reject) => {
        //初始化promise状态为 pending
      //执行异步操作
      if(异步操作成功) {
        resolve(value);//修改promise的状态为fullfilled
      } else {
        reject(errMsg);//修改promise的状态为rejected
      }
    })
  * 调用promise的then()
    promise.then(function(
      result => console.log(result),
      errorMsg => alert(errorMsg)
    ))
3. promise对象的3个状态
  * pending: 初始化状态
  * fullfilled: 成功状态
  * rejected: 失败状态
4. 应用:
  * 使用promise实现超时处理

  * 使用promise封装处理ajax请求
    let request = new XMLHttpRequest();
    request.onreadystatechange = function () {
    }
    request.responseType = 'json';
    request.open("GET", url);
    request.send();
-->

<script type="text/javascript">

 // 创建Promise对象
 let promise = new Promise((resolve, reject) => {
     // 初始化promise状态, pending:初始化
     console.info("1111")
     // 执行异步操作.例如:发送ajax请求, 开启定时器
     setTimeout(() => {
         console.info("3333")
         // 根据异步任务的返回结果去修改promise的状态
         // 异步任务执行成功时执行resolve()
         //resolve("hello world ") // 修改promise的状态为: fullfilled=》成功状态=>打印:成功回调

         //异步任务执行失败时调用reject()
         reject("exception") // 修改promise的状态为:rejected=>失败状态=>打印:失败回调
     }, 100)
 })
 console.info("2222")
    promise
        .then((result) => {
            console.info(result + "成功回调!")
        }, (error) => {
            console.info(error + "  失败回调!")
        })
</script>

</body>
</html>

14. Symbol属性介绍【ES6】

html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Symbol</title>
</head>
<body>
  <!--
    前言:ES5中对象的属性名都是字符串,容易造成重名,污染环境
    Symbol:
      概念:ES6中的添加了一种原始数据类型symbol(已有的原始数据类型:String, Number, boolean, null, undefined, 对象)
      特点:
        1、Symbol属性对应的值是唯一的,解决命名冲突问题
        2、Symbol值不能与其他数据进行计算,包括同字符串拼串
        3、for in, for of遍历时不会遍历symbol属性。
      使用:
        1、调用Symbol函数得到symbol值
          let symbol = Symbol();
          let obj = {};
          obj[symbol] = 'hello';
        2、传参标识
          let symbol = Symbol('one');
          let symbol2 = Symbol('two');
          console.log(symbol);// Symbol('one')
          console.log(symbol2);// Symbol('two')
        3、内置Symbol值
          * 除了定义自己使用的Symbol值以外,ES6还提供了11个内置的Symbol值,指向语言内部使用的方法。
          - Symbol.iterator
           * 对象的Symbol.iterator属性,指向该对象的默认遍历器方法(在iterator篇章讲解)

  -->


<script type="text/javascript">
            let symbol = Symbol()
            let obj = {userName: 'jiliang', age: 25}
            // 设置symbol值
            obj[symbol] = 'id_123456'
            console.info(obj)
            // 获取symbol值
            console.info(obj[symbol])

            let symbol1 = Symbol('one')
            let symbol2 = Symbol('two')
            console.info(symbol1 == symbol2)
            console.info(symbol1, symbol2)

            for(item in obj) {
                // 没有打印symbol属性
                console.info(item)
            }
</script>

</body>
</html>

15. iterator接口机制【ES6】

html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Iterator遍历器</title>
</head>
<body>
  <!--
    概念: iterator是一种接口机制,为各种不同的数据结构提供统一的访问机制
    作用:
      1、为各种数据结构,提供一个统一的、简便的访问接口;
      2、使得数据结构的成员能够按某种次序排列
      3、ES6创造了一种新的遍历命令for...of循环,Iterator接口主要供for...of消费。
    工作原理:
      - 创建一个指针对象(遍历器对象),指向数据结构的起始位置。
      - 第一次调用next方法,指针自动指向数据结构的第一个成员
      - 接下来不断调用next方法,指针会一直往后移动,直到指向最后一个成员
      - 每调用next方法返回的是一个包含value和done的对象,{value: 当前成员的值,done: 布尔值}
        * value表示当前成员的值,done对应的布尔值表示当前的数据的结构是否遍历结束。
        * 当遍历结束的时候返回的value值是undefined,done值为true
    原生具备iterator接口的数据(可用for of遍历)
      1、Array
      2、arguments
      3、set容器
      4、map容器
      5、String
      。。。
  -->

  <script type="text/javascript">
        // 模拟遍历器对象(指针对象)
        function iterator(arr){
            // 指针位置
            let index = 0;
            return{
                next: () => {
                    return {value: arr[index++], done: index==(arr.length+1)}
                }
            }
        }

        var arr = [1,2,3,4]
        let abcdf = iterator(arr);
        console.info(abcdf.next());
        console.info(abcdf.next());
        console.info(abcdf.next());
        console.info(abcdf.next());
        console.info(abcdf.next());


        // 将iterator接口部署到指定的数据类型上,可以使用for of循环遍历(es6 具备的数据类型有:数组、字符串、arguments、set容器、map容器、String).
        // 注意:普通的对象没有实现itaertor接口,所以不能使用for of接口进行遍历
        // 遍历数组
        for (let item of arr) {
            console.info(item)
        }
        let str = 'jiliang'
        // 遍历字符串
        for (let item of str) {
            console.info(item)
        }

        function fun(...values) {
            // 遍历arguments
            for (let item of  arguments) {
                console.info(item)
            }
            for (let item of  values) {
                console.info(item)
            }
        }
        fun(1,5,6,1,'yiyi')

        let obj = {userName: 'jiliang', age: 28}
        // 普通的对象没有实现itaertor接口,所以不能使用for of接口进行遍历
        /* for(let item of obj) {
            console.info(item)
        } */

        // Symbol.Iterator
        // 等同于在指定的数据结构上部署了iterator接口
        // 当使用for of去遍历某一个数据解构的时候,首先去找Symbol.iterator, 找到了就去遍历,没有找到的话就不能遍历 报错: is not iterator
        let targetData = {
            [Symbol.iterator]: function (){
                // 指针位置
                let index = 0;
                return{
                    next: () => {
                        return {value: this[index++], done: index==(this.length+1)}
                    }
                }
            }
        }

        // 使用参数三点运算符,解构赋值,默认去调用iterator接口
        let arr2 = [1,6]
        let arr3 = [2,...arr2,12]
        console.info(arr3)
        let [a, b] = arr2
        console.info(a, b)

  </script>
</body>
</html>

16. Generato函数详解【ES6】

html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Generator函数</title>
</head>
<body>

  <!--
   Generator函数
    概念:
      1、ES6提供的解决异步编程的方案之一
      2、Generator函数是一个状态机,内部封装了不同状态的数据,
      3、用来生成遍历器对象
      4、可暂停函数(惰性求值), yield可暂停,next方法可启动。每次返回的是yield后的表达式结果
    特点:
      1、function 与函数名之间有一个星号
      2、内部用yield表达式来定义不同的状态
      例如:
        function* generatorExample(){
          let result = yield 'hello';  // 状态值为hello
          yield 'generator'; // 状态值为generator
        }
      3、generator函数返回的是指针对象(接11章节里iterator),而不会执行函数内部逻辑
      4、调用next方法函数内部逻辑开始执行,遇到yield表达式停止,返回{value: yield后的表达式结果/undefined, done: false/true}
      5、再次调用next方法会从上一次停止时的yield处开始,直到最后
      6、yield语句返回结果通常为undefined, 当调用next方法时传参内容会作为启动时yield语句的返回值。
  -->
<script type="text/javascript" src="./js/jquery-1.10.1.min.js"></script>
<script type="text/javascript">

    function* myGenerator() {
        console.info("开始执行")
        let data1 = yield '1'
        console.info("1开始完了  "+data1)
        let data = yield '2'
        console.info(data)
        return "执行结束"
    }
    let my = myGenerator()
    console.info(my.next())
    // 参数是传给指针上一次停留位置的yiled返回值.如果不传值,默认是undefined
    console.info(my.next("传过去的值,就是执行yiled 返回值"))
    console.info(my.next())

    // 对象的symbol.iterator属性  指向遍历器对象
        let obj = {userName: 'jiliang', age: 23}
        // Generator函数返回的是遍历器对象.所以obj对象可以使用for of遍历
        // 每遍历obj一次,就调用next()方法一次,使得指针往前移动
        obj[Symbol.iterator] = function* myTest() {
            yield 1
            yield 2
            yield 3
        }
        for( let item of obj) {
            console.info(item)
        }
</script>
</body>
</html>

17. Async函数详解及应用【ES6】

html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>async函数</title>
</head>
<body>

<!--
  async函数(源自ES2017)
  概念: 真正意义上去解决异步回调的问题,同步流程表达异步操作
  本质: Generator的语法糖
  语法:
      async function foo(){
        await 异步操作;
        await 异步操作;
      }
  特点:
    1、不需要像Generator去调用next方法,遇到await等待,当前的异步操作完成就往下执行
    2、返回的总是Promise对象,可以用then方法进行下一步操作
    3、async取代Generator函数的星号*,await取代Generator的yield
    4、语意上更为明确,使用简单,经临床验证,暂时没有任何副作用

-->
<script type="text/javascript" src="./js/jquery-1.10.1.min.js"></script>
<script type="text/javascript">
        // 定义async函数,async函数总返回Promise对象
    async function foo() {
            return new Promise((resolve, reject) => {
                // 异步任务
                setTimeout(resolve, 2000);
            })
        }

        async function test() {
            console.info("开始执行async函数")
            await foo()
            console.info("任务执行结束")
        }
        //test()

        // async 函数的await返回值
        // 1.普通函数.是普通函数return返回值
        function test2() {
            return "test2,返回值"
        }
        // Promise函数,是resolve、reject(控制台飘红报错.【Uncaught (in promise) reject实参】)函数的实参
        async function asyncReturn() {
            let testReturn = await test2()
            console.info(testReturn)
            let resolveReturn = await Promise.resolve('resolve实参')
            console.info(resolveReturn)
            let rejectReturn = await Promise.reject('reject实参')
            console.info(rejectReturn)
        }
        asyncReturn()
</script>

</body>
</html>

18. class类使用详解【ES6】

html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>12_class</title>
</head>
<body>
</body>
<!--
1. 通过class定义类/实现类的继承
2. 在类中通过constructor定义构造方法
3. 通过new来创建类的实例
4. 通过extends来实现类的继承
5. 通过super调用父类的构造方法
6. 重写从父类中继承的一般方法
-->
<script type="text/javascript">

    // 原始定义方式
     function Person(name, age) {
        this.name = name
        this.age = age
    }
    let person = new Person('jiliang', 27)
    console.info(person) 
    // class方式定义
    class Person1{
        // 类的构造方法
        constructor(name, age) {
            this.name = name;
            this.age = age;
        }
        // 类的一般方法
        showName() {
            console.info(this.name)
        }
    }
    let person1 = new Person1('huang', 28)
    console.info(person1)
    // 调用普通方法
    person1.showName()

    // 子类继承Person1
    class Son extends Person1 {
        constructor(name, age, sal) {
            // 调用父类的构造方法
            super(name, age);
            this.sal = sal
        }
        showName() {
            console.info(this.name, this.age, this.sal)
        }
    }
    let son = new Son('son', 18, 10000)
    console.info(son)
    // 子类没有定义showName()方法时,则调用了从父类继承过来的普通方法;如果自己有定义,则调用自己的
    son.showName()

</script>
</html>

19. 字符串、数值的扩展【ES6】

html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>字符串&数值扩展</title>
</head>
<body>
<!--
--------字符串--------
1. includes(str) : 判断是否包含指定的字符串 // 返回boolean值
2. startsWith(str) : 判断是否以指定字符串开头 // 返回boolean值
3. endsWith(str) : 判断是否以指定字符串结尾 // 返回boolean值
4. repeat(count) : 重复指定次数 // 返回指定重复次数的字符串值
--------数值--------
1. 二进制与八进制数值表示法: 二进制用0b, 八进制用0o
2. Number.isFinite(i) : 判断是否是有限大的数
3. Number.isNaN(i) : 判断是否是NaN
4. Number.isInteger(i) : 判断是否是整数
5. Number.parseInt(str) : 将字符串转换为对应的数值
6. Math.trunc(i) : 直接去除小数部分
-->
<script type="text/javascript">

    let str = 'abcd'
    console.info(str.includes('s')) // false
    console.info(str.startsWith('a')) // true
    console.info(str.endsWith('d')) // true
    console.info(str.repeat(3)) // abcdabcdabcd

    console.info(0b1010) // 10
    console.info(0o56) // 46
    console.info(Number.isFinite(11)) // true
    console.info(Number.isFinite(Infinity)) // fasle

    console.info(Number.isNaN(NaN)) // true

    console.info(Number.isInteger(123.52)) // false
    console.info(Number.isInteger(123.0)) // true
    console.info(Number.parseFloat('123.545adas')) //123.54
    console.info(Number.parseInt('1253.45das')) // 1253
    console.info(Number.parseInt('a1245')) // NaN

    console.info(Math.trunc(156456.4646456)) //156456
</script>
</body>
</html>

20. 数组方法的扩展【ES6】

html
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>03_数组扩展</title>
</head>
<body>
<button>测试1</button>
<br>
<button>测试2</button>
<br>
<button>测试3</button>
<br>

<!--
1. Array.from(v) : 将伪数组对象或可遍历对象转换为真数组
2. Array.of(v1, v2, v3) : 将一系列值转换成数组
3. find(function(value, index, arr){return true}) : 找出第一个满足条件返回true的元素
4. findIndex(function(value, index, arr){return true}) : 找出第一个满足条件返回true的元素下标
-->
<script type="text/javascript">
    // btnss属于伪数组,不可以遍历.可以使用Array.from(btns) 转换为真数组
    let btns = document.getElementsByTagName('button');
    Array.from(btns).forEach(function(item, index){
        console.info(item)
    })
    // 将一系列值转换为数组
    let arr = Array.of(1,5,6,'dajsiasd')
    console.info(arr)
    // find方法寻找符合条件的值,并将其返回
    let item = arr.find(function(item, index){
        return item > 5
    })
    console.info(item)
    // findIndex方法寻找符合条件的值,并将符合条件值的下标返回
    let index = arr.findIndex(function(item, index){
        return item > 5;
    })
    console.info(index)

</script>
</body>

</html>

21. 对象方法的扩展【ES6】

html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>04_对象扩展</title>
</head>
<body>
<!--
1. Object.is(v1, v2)
  * 判断2个数据是否完全相等
2. Object.assign(target, source1, source2..)
  * 将源对象的属性复制到目标对象上
3. 直接操作 __proto__ 属性
  let obj2 = {};
  obj2.__proto__ = obj1;
-->

<script type="text/javascript">
    console.info(0 == -0) // true
    console.info(NaN == NaN) // false
    // 以字符串的方式比较 即:'0' == '-0'  'NaN' == 'NaN'
    console.info(Object.is(0, -0)) // false 
    console.info(Object.is(NaN, NaN)) // true

    let obj = {}
    let obj1 = {userName: 'jiliang', age: 28}
    let obj2 = {sex: ''}
    // 将obj1  obj2对象属性复制到obj对象上
    Object.assign(obj, obj1, obj2)
    console.info(obj)

    let obj3 = {}
    let obj4 = {money: 10000}
    // 将obj4绑到obj3的原型上
    obj3.__proto__ = obj4
    console.info(obj3)
    // 从原型上获取obj4的属性
    console.info(obj3.money)
</script>
</body>

</html>

22. 深度克隆【ES6】

html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>对象的深度克隆</title>
</head>
<body>

<!--
  1、数据类型:
    * 数据分为基本的数据类型(String, Number, boolean, Null, Undefined)和对象数据类型
    - 基本数据类型:
      特点: 存储的是该对象的实际数据
    - 对象数据类型:
      特点: 存储的是该对象在栈中引用,真实的数据存放在堆内存里
  2、复制数据
    - 基本数据类型存放的就是实际的数据,可直接复制
      let number2 = 2;
      let number1 = number2;
    - 克隆数据:对象/数组
      1、区别: 浅拷贝/深度拷贝
         判断: 拷贝是否产生了新的数据还是拷贝的是数据的引用
         知识点:对象数据存放的是对象在栈内存的引用,直接复制的是对象的引用
         let obj = {username: 'kobe'}
         let obj1 = obj; // obj1 复制了obj在栈内存的引用
      2、常用的拷贝技术
        1). arr.concat(): 数组浅拷贝
        2). arr.slice(): 数组浅拷贝
        3). JSON.parse(JSON.stringify(arr/obj)): 数组或对象深拷贝, 但不能处理函数数据
        4). 浅拷贝包含函数数据的对象/数组
        5). 深拷贝包含函数数据的对象/数组
-->
<script type="text/javascript">
  // 复制的对象的方式
  // 浅度复制
  let obj = {username: 'kobe', age: 39, sex: {option1: '', option2: ''}};
  let obj1 = obj;
  console.log(obj1);
  obj1.sex.option1 = '不男不女'; // 修改复制的对象会影响原对象
  console.log(obj1, obj);

  console.log('-----------');
  // Object.assign();  浅复制
  let obj2 = {};
  Object.assign(obj2, obj);
  console.log(obj2);
  obj2.sex.option1 = ''; // 修改复制的对象会影响原对象
  console.log(obj2, obj);

  // 深度克隆(复制)

  function getObjClass(obj) {
    let result = Object.prototype.toString.call(obj).slice(8, -1);
    if(result === 'Null'){
      return 'Null';
    }else if(result === 'Undefined'){
      return 'Undefined';
    }else {
      return result;
    }
  }
  // for in 遍历数组的时候遍历的是下标
  let testArr = [1,2,3,4];
  for(let i in testArr){
    console.log(i); // 对应的下标索引
  }

  // 深度克隆
  function deepClone(obj) {
    let result, objClass = getObjClass(obj);
    if(objClass === 'Object'){
      result = {};
    }else if(objClass === 'Array'){
      result = [];
    }else {
      return obj; // 如果是其他数据类型不复制,直接将数据返回
    }
    // 遍历目标对象
    for(let key in obj){
      let value = obj[key];
      if(getObjClass(value) === "Object" || 'Array'){
        result[key] = deepClone(value);
      }else {
        result[key] = obj[key];
      }
    }
    return result;
  }

  let obj3 = {username: 'kobe',age: 39, sex: {option1: '', option2: ''}};
  let obj4 = deepClone(obj3);
  console.log(obj4);
  obj4.sex.option1 = '不男不女'; // 修改复制后的对象不会影响原对象
  console.log(obj4, obj3);

</script> 
</body>
</html>

23. set、map容器详解【ES6】

html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>05_Set和Map数据结构</title>
</head>
<body>
<!--
1. Set容器 : 无序不可重复的多个value的集合体
  * Set() // 初始化
  * Set(array) // 初始化同时将array加入到set容器
  * add(value) // 添加元素
  * delete(value) // 删除元素
  * has(value) // 判断是否有元素存在
  * clear() // 清空set容器
  * size // set容器大小
2. Map容器 : 无序的 key不重复的多个key-value的集合体
  * Map()
  * Map(array) // array为二维数组
  * set(key, value)//添加
  * get(key) // 获取值
  * delete(key) // 删除值
  * has(key) // 判断是否有值
  * clear() // 清空
  * size // map容器大小
-->

<script type="text/javascript">
        // 数组重复时,会自动删除只保留一个
    let set = new Set([1,2,3,4,3,2,1,6]);
    console.log(set);
    set.add('abc');
    console.log(set, set.size);
    //delete(value)
    set.delete(2);
    console.log(set);
    //has(value)
    console.log(set.has(2));//false
    console.log(set.has(1));//true
    //clear()
    set.clear();
    console.log(set);
        // 初始化时传入二维数组.数组里面只能有两个值,第一个是key,第二个是value
    let map = new Map([['abc', 12],[25, 'age']]);
    console.log(map);
    map.set('', '性别');
    console.log(map);
    console.log(map.get(25));//age
    //delete(key)
    map.delete('');
    console.log(map);
    console.log(map.has(''));//false
    console.log(map.has('abc'));//true
    map.clear();
    console.log(map);
</script>
</body>

</html>

24. for of的用法详解【ES6】

html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>06_for_of循环</title>
</head>
<body>

<!--
for(let value of target){}循环遍历
  1. 遍历数组
  2. 遍历Set
  3. 遍历Map
  4. 遍历字符串
  5. 遍历伪数组
-->

<button>按钮1</button>
<button>按钮2</button>
<button>按钮3</button>

<script type="text/javascript">

    let arr = [1,2,3,4,5];
    for(let num of arr){
        console.log(num);
    }
    let set = new Set([1,2,3,4,5]);
    for(let num of set){
        console.log(num);
    }
    let str = 'abcdefg';
    for(let num of str){
        console.log(num);
    }
    let btns = document.getElementsByTagName('button');
    for(let btn of btns){
        console.log(btn.innerHTML);
    }

</script>
</body>

</html>

25. ES7方法介绍【ES7】

html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
</head>
<body>
<!--
1. 指数运算符(幂): **
2. Array.prototype.includes(value) : 判断数组中是否包含指定value

-->
<script type="text/javascript">
    console.log(3 ** 3);//27
    let arr = [1,2,3,4, 'abc'];
    console.log(arr.includes(2));//true
    console.log(arr.includes(5));//false
</script>
</body>
</html>