• 第十三节:ES6之模板字符串、Function、展开运算符和剩余参数、Number详解


    一. 模板字符串

    1. 模板字符串

         我们会使用 `` 符号来编写字符串,称之为模板字符串; 其次,在模板字符串中,我们可以通过 ${expression} 来嵌入动态的内容;

    {
        const name = "ypf";
        const age = 1.82;
        function getMsg() {
            return "你好,ypf";
        }
        console.log(`name:${name},age:${age},msg:${getMsg()}`);
    }

    2. 标签字符串

        (1). 第一个参数依然是模块字符串中整个字符串, 只是被切成多块,放到了一个数组中

        (2). 第二个参数是模块字符串中, 第一个 ${}

        (3). 第三个参数是模块字符串中, 第二个 ${}

    {
        function foo(m, n, x) {
            console.log("---------", m, n, x);
        }
        const name = "ypf";
        const age = 1.82;
        foo`hi${name}hello${age}`; //--------- [ 'hi', 'hello', '' ] ypf 1.82
    }

    二. Function详解

    1. 默认参数

        (1). ES5时期,对参数进行判断,如果没有值,则赋一个默认值,通过 || 符号来实现,但这种模式有个bug,  它认为:0和空字符串"",都是false

        (2). ES6中引入默认参数解决上述痛点问题,通过 = 符号直接参数赋值

        (3). 默认值的参数尽量往后放,这样当用默认值的时候,后续的参数可以省略不用输入

        注:默认值会改变函数的length的个数,默认值以及后面的参数都不计算在length之内了!

    // 1. ES5时候默认参数的判断
    {
        function foo(name, age) {
            name = name || "ypf";
            age = age || 1.82;
            console.log(name, age);
        }
        foo("", 0); //ypf 1.82  , 实际上我们想输出 “” 0,这就是bug所在
        foo(undefined, undefined); //ypf 1.82
    }
    
    // 2. 默认参数
    {
        function foo(name = "ypf", age = 1.82) {
            console.log(name, age);
        }
        foo("", 0); //"" 0
        foo(undefined, undefined); //ypf 1.82
        foo("lmr", 1.99); //lmr 1.99
    
        function foo2(name, age, msg) {
            console.log(name, age, msg);
        }
        function foo3(name, age = 1.82, msg) {
            console.log(name, age, msg);
        }
        console.log(foo2.length); //3
        console.log(foo3.length); //1
    }

    2. 剩余参数

        (1). 用途:在写函数的时候,部分情况我们不是很确定参数有多少个,可以使用剩余参数, 形式为 ...变量名

        (2). 剩余参数的中数据存放在一个数组里

        (3). 剩余参数必须放在最后的位置

     PS:与arguments的区别:剩余参数只包含那些没有对应形参的实参,而 arguments 对象包含了传给函数的所有实参;arguments对象不是一个真正的数组,而rest参数是一个真正的数组,可以进行数组的所有操作;arguments是早期的ECMAScript中为了方便去获取所有的参数提供的一个数据结构,而rest参数是ES6中提供并且希望以此来替代arguments的。

    {
        function sum(m, ...nums) {
            let total = m;
            nums.forEach(item => (total = total + item));
            return total;
        }
        console.log(sum(10, 1, 2, 3, 4, 5)); //25
    }

    3. length属性

         返回函数参数的个数

         注:默认值会改变函数的length的个数,默认值以及后面的参数都不计算在length之内了!

        function foo2(name, age, msg) {
            console.log(name, age, msg);
        }
        function foo3(name, age = 1.82, msg) {
            console.log(name, age, msg);
        }
        console.log(foo2.length); //3
        console.log(foo3.length); //1

    4. name属性

         返回函数的名称

    {
        function foo() {}
        console.log(foo.name); //foo
    }

    5. 箭头函数

    (1). 普通写法, 如下案例

    (2). 特殊写法

        A. 如果参数只有一个,可以省略小括号()

        A. 返回值是表达式,可以省略 return 和 {}

        B. 返回值是字面量, 需要加小括号()

    (3).特殊点

        A. 箭头函数中没有this,内部的this就是定义时上层作用域中的this。也就是说,箭头函数内部的this指向是固定的

        B. 不可以当作构造函数,也就是说,不可以对箭头函数使用new命令,否则会抛出一个错误。

        C. 箭头函数不可以使用arguments对象,该对象在函数体内不存在。如果要用,可以用 rest 参数代替。

    {
        //普通函数两种写法
        function sum1(m1, m2) {
            return m1 + m2;
        }
        let sum2 = function (m1, m2) {
            return m1 + m2;
        };
        // 箭头函数写法
        let sum3 = (m1, m2) => {
            return m1 + m2;
        };
        // 特殊写法
        let GetMsg = msg => {
            console.log(msg);
        };
        let pow = x => x * x;
        let GetUserInfo = name => ({
            myName: name,
            age: 20,
            addr: "Beijing City",
        });
        console.log(GetUserInfo());
        // 箭头函数this指向
        {
            var obj = {
                data: [],
                getData: function () {
                    // 发送网络请求, 将结果放到上面data属性中
    
                    // 在箭头函数之前的解决方案
                    // var _this = this
                    // setTimeout(function() {
                    //   var result = ["abc", "cba", "nba"]
                    //   _this.data = result
                    // }, 2000);
    
                    // 箭头函数之后(不绑定this,就去外层作用域(也就是getData中的this),也就是obj)
                    setTimeout(() => {
                        var result = ["abc", "cba", "nba"];
                        this.data = result;
                    }, 2000);
                },
            };
            obj.getData();
        }
    }

    三. 展开运算符

    1. 含义

          把固定的数组内容“打散”到对应的参数中

          可以在函数调用/数组构造时, 将数组表达式或者string在语法层面展开;还可以在构造字面量对象时, 将对象表达式按key-value的方式展开

    2. 用法

            A. 函数调用的时候,将数组或者字符串展开到参数中,如:foo(...names);

            B. 构造数组时,将数组或者字符串展开到参数中,如:[...names, ...name];

            C. 构建对象字面量时, 将对象或者字符串展开到参数中,后面的属性会覆盖前面的, 如:{ ...myInfo, age, height: 1.82 };

    {
        const names = ["ypf1", "ypf2", "ypf3"];
        const name = "ypf";
        const myInfo = { name: "ypf", age: 30 };
    
        // 1.1 函数调用
        function foo(x, y, z) {
            console.log(x, y, z);
        }
        foo(...names); //ypf1 ypf2 ypf3
        foo(...name); //y p f
        foo.apply(null, names); //ypf1 ypf2 ypf3
    
        // 1.2 构造数组时
        const myNames = [...names, ...name];
        console.log(myNames); //[ 'ypf1', 'ypf2', 'ypf3', 'y', 'p', 'f' ]
    
        // 1.3 构建对象字面量时(ES9-ES2018)
        let age = 40;
        const myObj = { ...myInfo, age, height: 1.82 };
        console.log(myObj); //{ name: 'ypf', age: 40, height: 1.82 }
    
        //1.4 对象+数组
        {
            // filterRouteArray是一个数组,数组中的每个值都是一个{}对象
            // pathMatch是一个对象
            filterRouteEnd[0].children = [...filterRouteArray, { ...pathMatch }];
        }
    }

    3. 复制数组、对象(浅拷贝)

       A. 对于数组:数组是复合的数据类型,直接复制的话,只是复制了指向底层数据结构的指针,而不是克隆一个全新的数组。

                              使用展开运算符,相当于获得一份新的数据空间,新的引用地址,指向新的栈空间

       B. 对于对象:展开运算符是浅拷贝,只能将对象中的一级内容直接copy,对于对象中的对象,copy的仍然是引用地址!!

    //数组的复制-浅拷贝
        {
            //直接把array1赋值给array2,相当于把引用地址赋值给了array2, 这个时候array1和array2都指向堆内存的同一个空间
            const array1 = [1, 2, 3];
            const array2 = array1;
            array2[0] = 111;
            console.log(array1[0]); //111
        }
        {
            // 使用展开运算符,相当于array2获得一份新的数据空间,新的引用地址,指向新的栈空间
            const array1 = [1, 2, 3];
            const array2 = [...array1];
            array2[0] = 111;
            console.log(array1[0]); //1
        }
        // 对象的赋值--浅拷贝
        {
            let obj1 = {
                name: "ypf",
                age: 18,
                myChild: {
                    cName: "ypf1",
                    cAge: 20,
                },
            };
            let obj2 = { ...obj1 };
            obj2.name = "lmr";
            obj2.myChild.cName = "lmr1";
            console.log(obj1.name, obj1.myChild.cName); //ypf  lmr1
        }

    4. 数组合并

        使用展开运算符,可以实现数组的合并,但是不能去重,如果想去重,需要借助Set数据结构来实现。

    {
        let array1 = [1, 3, 4];
        let array2 = [2, 3, 5];
        // 展开运算符合并数组(注:不去充)
        console.log([...array1, ...array2]); //[ 1, 3, 4, 2, 3, 5 ]  不去重!!!
        // 配合Set数据类型进行去重
        let s = new Set([...array1, ...array2]);
        console.log([...s]); //[ 1, 3, 4, 2, 5 ]
        //或者利用Array.from转成数组
        console.log(Array.from(s)); //[ 1, 3, 4, 2, 5 ]
    }

    四. 剩余参数

    1. 含义

           把固定的数组内容“打散”到对应的参数 【同Function章节介绍的一样】

    2. 用途

      在写函数的时候,部分情况我们不是很确定参数有多少个,可以使用剩余参数, 形式为 ...变量名

    3. 剩余参数的中数据存放在一个数组里

    4. 剩余参数必须放在最后的位置

    PS:与arguments的区别:剩余参数只包含那些没有对应形参的实参,而 arguments 对象包含了传给函数的所有实参;arguments对象不是一个真正的数组,而rest参数是一个真正的数组,可以进行数组的所有操作;

            arguments是早期的ECMAScript中为了方便去获取所有的参数提供的一个数据结构,而rest参数是ES6中提供并且希望以此来替代arguments的。

    {
        function sum(m, ...nums) {
            let total = m;
            nums.forEach(item => (total = total + item));
            return total;
        }
        console.log(sum(10, 1, 2, 3, 4, 5)); //25
    }
    {
        console.log("-----------------1. 剩余参数---------------------");
        function sum1(...nums) {
            console.log(nums);
            console.log(
                nums.reduce((preValue, currentValue) => preValue + currentValue, 0)
            ); //求和
        }
        //调用
        sum1(1, 2); //[1,2]
        sum1(1, 2, 3); //[1,2,3]
        sum1(1, 2, 3, 4); //[1,2,3,4]
    
        function sum2(num1, num2, ...nums) {
            console.log(nums);
            console.log(
                nums.reduce(
                    (preValue, currentValue) => preValue + currentValue,
                    num1 + num2
                )
            ); //求和
        }
        //调用
        sum2(1, 2); //[]
        sum2(1, 2, 3); //[3]
        sum2(1, 2, 3, 4); //[3,4]
    }

    五. Number详解

    1. 进制的新写法

        二进制和八进制数值的新的写法,分别用前缀0b(或0B)和0o(或0O)表示

    {
        // b -> binary
        const num2 = 0b100; // 二进制
        // o -> octonary
        const num3 = 0o100; // 八进制
        // x -> hexadecimal
        const num4 = 0x100; // 十六进制
    }

    2. 新增方法

        (详见:http://es.xiecheng.live/es6/number.html#新增方法)

        (1). Number.parseInt(): ES6 将全局方法parseInt()移植到Number对象上面,行为完全保持不变。

        (2). Number.parseFloat(): ES6 将全局方法parseFloat()移植到Number对象上面,行为完全保持不变。

        (3). Number.isInteger(): 用来判断一个数值是否为整数。

        (4). Number.isFinite()

        (5). Number.isNaN()

        (6). Number.MAX_SAFE_INTEGER

        (7). Number.MIN_SAFE_INTEGER

        (8). Number.isSafeInteger()

       {
            // ES5的写法
            console.log(parseInt("12.34")); // 12
            // ES6的写法
            console.log(Number.parseInt("12.34")); // 12
        }
        {
            // ES5的写法
            console.log(parseFloat("123.45#")); // 123.45
            // ES6的写法
            console.log(Number.parseFloat("123.45#")); // 123.45
        }
        {
            Number.isInteger(25); // true
            Number.isInteger(25.1); // false
            Number.isInteger(); // false
            Number.isInteger(null); // false
            Number.isInteger("15"); // false
            Number.isInteger(true); // false
        }

    3. Math扩展

        (1). Math.trunc():方法用于去除一个数的小数部分,返回整数部分。

        (2). Math.sign(): 方法用来判断一个数到底是正数、负数、还是零。对于非数值,会先将其转换为数值。

        (3). Math.cbrt():方法用于计算一个数的立方根。

    4. ES2021新增特性

     数字过长时,可以使用_作为连接符

    {
        // 大的数值的连接符(ES2021 ES12)
        const num = 10_000_000_000_000_000;
        console.log(num);
    }

    !

    • 作       者 : Yaopengfei(姚鹏飞)
    • 博客地址 : http://www.cnblogs.com/yaopengfei/
    • 声     明1 : 如有错误,欢迎讨论,请勿谩骂^_^。
    • 声     明2 : 原创博客请在转载时保留原文链接或在文章开头加上本人博客地址,否则保留追究法律责任的权利。
     
  • 相关阅读:
    线性代数学习之初等矩阵和矩阵的可逆性
    线性代数学习之线性系统
    容器远程访问vnc--CentOS 6.8安装和配置VNC
    docker安装-单机/多机安装
    docker aufs存储驱动文件系统
    基于PowerCli自动部署和配置vmvare虚拟机
    使用Kubespray在ubuntu上自动部署K8s1.9.0集群
    python应用-pycharm新建模板默认添加shebang编码作者时间等信息
    python开发基础作业01:模拟登陆系统
    git 添加码云远程仓库和上传到码云的命令
  • 原文地址:https://www.cnblogs.com/yaopengfei/p/16027402.html
Copyright © 2020-2023  润新知