• ES6 函数的扩展


    一、 函数 参数默认值

    1. 规则

    • (1)ES6 允许为函数的参数设置默认值: 在形参出直接定义即可,不用关键字声明
    function ff(x, y = 'World') {
        console.log(x, y);
    }
    
    console.log(ff('Hello')); // Hello World
    console.log(ff('Hello', 'China')); // Hello China
    console.log(ff('Hello', '')); // Hello
    
    • (2)函数参数 在形参处默认声明: 规定 函数内不能用 letconst 再次声明,否则会报错
    function foo(x = 5) {
        let x = 1; // error
        const x = 2; // error
    }
    
    • (3)函数参数 设置默认值: 不会被记录到 函数.length
      • 函数.length 用于获取形参个数
    (function (a) {}).length // 1
    (function (a = 5) {}).length // 0
    (function (a, b, c = 5) {}).length // 2
    
    • (4)函数参数 设置默认值: 参数会在形参处 形成一个单独的作用域(conext)
    var x = 1;
    
    function f(x, y = x) {
        console.log(y);
    }
    
    f(2) // 2
    
    let x = 1;
    
    function f(y = x) {
        let x = 2;
        console.log(y);
    }
    
    f() // 1
    

    2. 函数参数 解构赋值

    • 函数 参数为对象,设置默认值
    function foo({
        x = 10,
        y = 5
    }) {
        console.log(x, y);
    }
    
    foo({})       // 10 5
    foo({x: 1})   // 1 5
    foo()         // TypeError: Cannot read property 'x' of undefined
    
    function foo({
        x = 10,
        y = 5
    } = {}) {
        console.log(x, y);
    }
    
    foo({})       // 10 5
    foo({x: 1})   // 1 5
    foo()         // 1 5
    
    function foo({
        x = 10,
        y
    }) {
        console.log(x, y);
    }
    
    foo({})       // 10 undefined
    foo({x: 1})   // 1 undefined
    foo()         // TypeError: Cannot read property 'x' of undefined
    
    • 重点区分
    // 写法一
    function m1({x = 0, y = 0} = {}) {
      return [x, y];
    }
    
    // 写法二
    function m2({x, y} = { x: 0, y: 0 }) {
      return [x, y];
    }
    
    // 函数没有参数的情况
    m1() // [0, 0]
    m2() // [0, 0]
    
    // x 和 y 都有值的情况
    m1({x: 3, y: 8}) // [3, 8]
    m2({x: 3, y: 8}) // [3, 8]
    
    // x 有值,y 无值的情况
    m1({x: 3}) // [3, 0]
    m2({x: 3}) // [3, undefined]
    
    // x 和 y 都无值的情况
    m1({}) // [0, 0];
    m2({}) // [undefined, undefined]
    
    m1({z: 3}) // [0, 0]
    m2({z: 3}) // [undefined, undefined]
    
    // 写法三
    function m3({x = 1, y = 0} = {}) {
      return [x, y];
    }
    
    // 写法四
    function m4({x = 1, y} = { x: 0, y: 0 }) {
      return [x, y];
    }
    
    
    m1() // [1, 0]
    m2() // [0, 0]
    

    3. 函数参数默认值 的应用

    • 应用一: 指定某一个参数,不能省略
    function throwIfMissing() {
      throw new Error('Missing parameter');
    }
    
    function foo(mustBeProvided = throwIfMissing()) {
      return mustBeProvided;
    }
    
    foo()
    // Error: Missing parameter
    
    • 应用二: 某一个参数可省略
    function foo(optional = undefined) { ··· }
    

    二、 函数 的 rest 参数

    • ES6 定义了 rest 参数,用于获取函数的多余参数(在不确定函数有多少个参数时,最适用)

    • 语法:

      • 函数形参中 (...rest) ,在函数内部 变量 rest 是存储着多余参数的一个真数组

      • rest 只是一个变量,可以为任意值

    function add(...values) {
        let sum = 0;
        
        for (var val of values) {
            sum += val;
        }
        
        return sum;
    }
    
    add(2, 5, 3) // 10
    add(2, 5, 3, 5) // 15
    
    • rest 参数 约束:

      • ...rest 中包含的参数,不计入 函数.length 中;当然,设置默认值的参数,也不计入 函数.length

      • 函数的 ...rest 参数必须作为函数的最后一个参数,其后 不能再有其他参数(否则 函数初始化时就会报错)

    • 对比 ES5 中的 arguments

      • arguments: 函数内部的一个属性,存储着函数中 所有实参的伪数组arguments 是固定值,函数内部直接访问即可; 箭头函数中不再支持 arguments

      • rest: 函数中的一个参数,存储着多余参数的一个真数组rest 是个变量,声明形参,才能在函数中访问

    三、 箭头函数

    1. 箭头函数 语法

    • 箭头函数的 主要构成:

      • 箭头函数 参数:不需要参数 或 需要多个参数,就使用 一个圆括号 代表参数部分

      • 箭头函数 函数体:函数体重 多于一条语句,要使用 大括号 将它们括起来

      • 箭头函数 返回值:函数体中 多于一条语句,且有返回值时 return 关键字不能省略

    var sum = (num1, num2) => { 
        return num1 + num2; 
    }
    
    • 最简化 的箭头函数 var f = v => v

      • 省略了 参数圆括号代码块中括号return 关键字
    var f = v => v;
    
    // 等同于
    var f = function(v) {
        return v;
    };
    

    2. 箭头函数 this 指向

    • 声明: 箭头函数 内部没有this属性;所以 箭头函数内 this 指向 外层代码块的 this

    • 纠正:

      • ES5 语法中的函数,看this指向时的原则:谁调用了函数 this就指向谁

      • ES6 语法中的函数,分析this指向,只要找到箭头函数外层this指向即可(而不是看谁调用的函数)

    <script>
        const fn1 = {
            name: function() {
                console.log(this);  // fn1
            }
        }
    
        fn1.name();
    
        const fn2 = {
            name: () => {
                console.log(this);  // window
            }
        }
    
        fn2.name();
    </script>
    
    <script>
        let box1 = document.getElementById('box1');
        box1.name = 'wang'
        this.name = 'zhang';
        
        box1.addEventListener('click', function() {
            console.log(this.name);     // 'wang' 因为是dom对象,调用了回调函数
        });
        
        
        let box2 = document.getElementById('box2');
        box2.name = 'wang'
        this.name = 'zhang';
            
        box2.addEventListener('click', () => {
            console.log(this.name);     // 'zhang' this.指向外层的this
        });
    </script>
    
    • 借用方法 callapplybind ,不能改变 this指向
    var a = 2;
    var obj = {
        a: 100
    };
    
    var fn1 = (a) => {
        console.log(this.a);
    };
    
    var fn2 = function(a) {
        console.log(this.a);
    };
       
        
    fn1.call(obj);    // 2
    fn2.call(obj);    // 100
    

    3. 箭头函数 的约束

    • 箭头函数 不能当作 构造函数(因为 自身没有 this 机制)

    • 箭头函数内 不能使用arguments对象, 用 rest 参数代替

    • 箭头函数 中没有 argumentssupernew.target 这是三个变量, 均指向外层函数 的变量

    四、 函数的 name 属性 被写入标准

    • 函数的 name 属性, 早就被浏览器广泛支持,但是直到 ES6,才将其写入了标准

    • 对比:

      • 写入标准之前:将 匿名函数 赋值给一个变量;访问 函数.name 返回空字符串

      • 写入标准之后:将 匿名函数 赋值给一个变量;访问 函数.name 返回 变量名

    
    const test = function baz() {};
    
    console.log(test.name); // ES5输出:""
    console.log(test.name); // ES6输出:"baz"
    

    五、 函数内 关于 严格模式的约束

    • ES2016 规定: 函数参数 如果使用了默认值、解构赋值、扩展运算符,函数内部就不能显式设定为严格模式(否则会报错)

    • 原因猜想: (待证实)可理解为函数式一个整体,函数 执行的时候:先执行函数参数,然后再执行函数体;函数执行到中间 发现语法 要遵循 严格模式,就会报错

    • 解决方案:

    // 方案一:
    'use strict';
    
    function doSomething(a, b = a) {
      // code
    }
    
    // 方案二:
    const doSomething = (function () {
        'use strict';
        return function(value = 42) {
            return value;
        };
    }());
    
  • 相关阅读:
    P4910 帕秋莉的手环
    P3216 [HNOI2011]数学作业
    洛谷 P2894 [USACO08FEB]酒店
    [网络流24题]魔术球问题
    [网络流24题]飞行员配对方案问题
    [网络流24题]最小路径覆盖问题
    洛谷 P1503鬼子进村
    BZOJ 3631: [JLOI2014]松鼠的新家
    洛谷 P2922 [USACO08DEC]秘密消息Secret Message
    洛谷 P1379 八数码难题
  • 原文地址:https://www.cnblogs.com/zxvictory/p/8439172.html
Copyright © 2020-2023  润新知