《深入理解ES6》-3-函数-笔记

2017-11-07  本文已影响0人  Revontulet

函数

函数形参的默认值

在ES5中模拟默认参数

    function aa(num, callback) {
        num = num || 100;
        callback = callback = function() {};
    }
    function aa(num, callback) {
        num = (typeof num !== "undefined") ? num : 100;
        callback = (typeof callback !== "undefined") ? callback : function() {};
    }

ES6中的默认参数

    function aa(num = 100, callback = function() {}) {
        // ...
    }

默认参数对arguments对象的影响

    function aa(x, y ="y") {
        console.log(arguments.length);
        console.log(x === arguments[0]);
        console.log(y === arguments[1]);
        x = "x";
        y = "000"
        console.log(x === arguments[0]);
        console.log(y === arguments[1]);
    }
 + 输出结果为:```1, true, false, false, false```
 + 这种特性可以让我们通过arguments对象将参数回复为初始值

默认参数表达式

    function getValue() {
        return 5
    }
    function add(x, y = getValue()) {
        return x + y;
    }

    console.log(add(1, 1));
    // 2
    console.log(add(1));
    // 6
 + 当使用函数调用结果作为默认参数值时,如果忘记写小括号,最终传入的是函数的引用,而不是函数调用的结果
    function add(x = y, y) {
        return x + y;
    }

    console.log(add(1, 1));
    // 2
    console.log(add(1));
    // 抛出错误
    // 表示调用add(undefined, 1), 即:
    // let x = y;
    // let y = 1;
    // 此时会报错

默认参数的临时死区

处理无命名参数

ES5中的无命名参数

    function pick(obj) {
        let result = Object.create(null);
        // 从第二个参数开始
        for (let i = 1, len = arguments.length; i < len; i++) {
            result[arguments[i]] = obj[arguments[i]];
        }
        return result;
    }

    let book = {
        author: "shaun",
        age: 20
    };

    let data = pick(book, "author", "age");
    // shaun
    console.log(data.author);
    // 20
    console.log(data.age);

不定参数

    function pick(obj, ...keys) {
        let result = Object.create(null);
        for (let i = 1, len = arguments.length; i < len; i++) {
            result[keys[i]] = obj[keys[i]];
        }
        return result;
    }
    let obj = {
        // 会报错,不可以在setter中使用不定参数
        set name(...value) {
            // to do...
        }
    }
    function check(...args) {
        console.log(args.length);
        console.log(arguments.length);
        console.log(args.[0], arguments[0]);
        console.log(args.[1], arguments[1]);
    }

    check("a", "b");
    // 输出:
    // 2
    // 2
    // a a
    // b b

增强的Function构造函数

    var add = new Function("x", "y", "return x + y");
    // 2
    console.log(add(1, 1));
    var add = new Function("x", "y = 2", "return x + y");
    // 2
    console.log(add(1, 1));
    // 3
    console.log(add(1));
 + 不定参数(只能在最后一个参数前加...)
    var pick = new Function("...args", "return args[0]");
    // 1
    console.log(pick(1, 2));

展开运算符

    let value = [25, 50, 75, 100];
    // 100
    console.log(Math.max.apply(Math, value));
    let value = [25, 50, 75, 100];
    // 等价于
    // console.log(Math.max(25, 50, 75, 100));
    // 100
    console.log(Math.max(...value));
    let value = [25, -50, -75, -100];
    let value2 = [-25, -50, -75, -100];
    // 25
    console.log(Math.max(...value, 0));
    // 0
    console.log(Math.max(...value2, 0));

name属性

如何选择合适的名称

    function dosth() {
        //
    }
    var doelse function() {
        //
    };
    // dosth
    dosth.name;
    // doelse
    doelse.name;

name属性的特殊情况

    var dosth = function doelse() {
        //
    };
    var person = {
        get firstName() {
            return "shaun";
        },
        sayName: function() {
            console.log(this.name);
        }
    }
    // 由于函数表达式的名字比函数本身被赋值的变量的权重高
    // doelse
    dosth.name;
    // 取值对象字面量
    // sayName
    person.sayName.name;
    // getter和setter,都会有前缀
    // get firstName
    person.firstName.name;
 + 其他两种前缀
    var dosth = function() {
        //
    };
    // bound dosth
    dosth.bind().name;
    // anonymous
    (new Function()).name;

明确函数的多重用途

在ES5中判断函数被调用的方法

    function person() {
        if (this instanceof person) {
            this.name = name;
        } else {
            throw new Error("msg")
        }
    }
    // 成功执行
    var person = new Preson("shaun");
    // 抛错
    var notPerson = Preson("shaun");
    // 也被成功执行
    var notPerson2 = Preson.call(person, "shaun");

元属性(Metaproperty) new.target

块级函数

块级函数的使用场景

箭头函数

箭头函数语法

    let fn = val => val;
    let sum = (x, y) => x + y;
    let name = () => "shaun";
    let sum = (x, y) => { return x + y; };
    let getId = id => ({ id: id, name: "shaun" });
    // 相当于
    let getId = function(id) {
        return {
            id: id,
            name: "shaun"
        };
    };

创建立即执行函数表达式

    let person = function(name) {
        return {
            getName: function() {
                return name;
            }
        };
    }("shaun");
    // shaun
    console.log( person.getName());
    let person = ((name) => {
        return {
            getName: function() {
                return name;
            }
        };
    })("shaun");
    // shaun
    console.log( person.getName());

箭头函数没有this绑定

箭头函数和数组

    var value = [1, 2, 3, 9, 8];
    // 老办法
    var result = value.sort(function(a, b) {
        return a - b;
    })
    // 新办法
    var result2 = value.sort((a, b) => a - b); 

箭头函数没有argument绑定

箭头函数的辨识方法

    var result = (a, b) => a - b;
    // function
    console.log(typeof result); 
    // true
    console.log(result instanceof Function);
    var result = (a, b) => a + b;
    // 3
    console.log(result.call(null, 1, 2)); 
    // 3
    console.log(result.call(null, 1, 2)); 

    var boundResult = result.bind(null, 1, 2);
    // bind后的方法不用传参
    // 3
    console.log(boundResult());

尾调用优化

    function dosth() {
        // 尾调用
        return doelse();
    }

ES6中的尾调用优化

如何利用尾调用优化

    function fn(n) {
        if (n <= 1) {
            return 1;
        } else {
            return n * fn(n - 1);
        }
    } 
    function fn(n, p = 1) {
        if (n <= 1) {
            return 1 * p;
        } else {
            let result = n * p;
            // 优化后
            return fn(n - 1, result);
        }
    }
上一篇 下一篇

猜你喜欢

热点阅读