第十三节: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 : 原创博客请在转载时保留原文链接或在文章开头加上本人博客地址,否则保留追究法律责任的权利。
 
posted @ 2022-03-19 18:31  Yaopengfei  阅读(445)  评论(1编辑  收藏  举报