zoukankan      html  css  js  c++  java
  • 第3章 新手的第一堂函数课:定义与参数

    1. 函数与对象的区别

    function foo(){}
    
    class Cls {}
    
    foo();  // 函数是可调用的
    Cls();
    // Uncaught TypeError: Class constructor Cls cannot be invoked without 'new'
    

    2. 回调函数

    • 定义:将某个函数作为参数传入另一个函数,传入函数会在应用程序执行的未来某个时间点才执行,这个传入的函数被称为回调函数
      function foo(fn){ // 接收一个函数fn作为参数
          return fn(); // 返回时调用传入的函数
      }
      

    3. 函数作为对象的意义

    3.1 存储函数

    // 需求:存储唯一函数集合(即添加的函数唯一且不重复)
    var store = {
        nextId: 1,
        cache: {},
        add: function (fn) {
            if (!fn.id) {       // 检查该函数是否已经存在id属性
                fn.id = this.nextId++;
                this.cache[fn.id] = fn;
                return true;
            }
            return false;
        }
    };
    
    function fn_01(){}
    function fn_01(){}
    function fn_02(){}
    
    console.log(store.add(fn_01));      // true
    console.log(store.add(fn_01));      // false
    console.log(store.add(fn_02));      // true
    console.log(fn_01.id);      // 1
    console.log(fn_02.id);      // 2
    

    3.2 自记忆函数

    • 定义:当函数计算得到结果时就将该结果按照参数存储起来,如果另一个调用也使用相同的参数,则可以直接赶回上次存储的结果而不是再计算一边。这样可以避免重复且复杂的计算。通常用于动画中的计算、搜索不经常变化的数据或任何耗时的数学计算。
    // 判断一个值是否是素数(除了1和它本身不再有其他因数)
    function isPrime(value) {
        // 建立缓存
        if (!isPrime.answers) {
            isPrime.answers = {};
        }
        // 检查是否已经计算过这个值
        if (isPrime.answers[value] !== undefined) {
            return isPrime.answers[value];
        }
        var prime = value !== 0 && value !== 1;
        for (var i = 2; i < value; i++) {
            if  (value % i === 0) {
                prime = false;
                break;
            }
        }
        // 存储计算的值
        return isPrime.answers[value] = prime;
    }
    
    console.log(isPrime(0));        // false    
    console.log(isPrime(1));        // false
    console.log(isPrime(5));        // true
    console.log(isPrime(5));        // true
    console.log(isPrime.answers);   // {0: false, 1: false, 5: true}
    

    4. 函数定义

    4.1 函数声明和函数表达式

    • 函数声明
    function fn(params) { /** 函数体 */ }
    
    • 函数表达式
    var fn = function(params) { /** 函数体 */ }
    
    • 立即调用函数表达式(IIFE)
    // 这一特性可以模拟模块化
    (function(val) {console.log(val)})(3);      // 3
    
    (function(val) {console.log(val)}(3));  // 3  不推荐使用
    
    // 如果去掉包裹函数表达式的括号会报错,
    // 因为这个语句以function开头,解析器会认为这是一个函数声明。
    // 每个函数声明必须有名字,而这里没有
    // 所以函数报错
    
    // 立即调用函数表达式的常用形式(使用一元操作符将函数声明改为表达式)
    // 不影响最终结果
    +function(val) {console.log(val)}(3);
    -function(val) {console.log(val)}(3);
    !function(val) {console.log(val)}(3);
    ~function(val) {console.log(val)}(3);
    
    

    4.2 箭头函数(ES6)

    var vals = [1, 5, 6, 2, 9, 6, 0];
    
    // 箭头函数最简式:param => expression
    vals.sort((a, b) => a - b);
    
    console.log(vals);
    // [0, 1, 2, 5, 6, 6, 9]
    
    var getName = (() => "Wango")();
    console.log(getName);   // Wango
    // 箭头函数中只有一条语句且没有{}代码块和return时,返回值为这一条语句的结果
    
    var getName = (() => {"Wango"})();
    console.log(getName);   // undefined
    // 箭头函数的函数体时一个代码块时,值是return语句的值,
    // 这里没有return语句,所以值是undefined
    

    函数构造函数(主要用在动态创建和执行代码)和生成器函数暂未涉及

    5 函数的参数

    • 实参:调用函数时所传递给函数的值
    • 形参:定义函数时所列举的变量
    • 实参的数量大于形参时,额外的实参不会赋值给任何形参
    • 剩余参数(ES6)
    // 用...接收多个参数,并将参数放入remaining数组中
    // 只有最后一个参数才能时剩余参数,
    // 否则会:SyntaxError: Rest parameter must be last formal parameter
    function add(first, ...remaining) {
        var sum = first;
        for (var i = 0; i < remaining.length; i++) {
            sum += remaining[i];
        }
        return sum;
    }
    
    console.log(add(1, 2, 3));
    
    • 默认参数(ES6)
    // ES6之前处理默认参数的方法
    function setInfo(name, age, gender) {
        gender = typeof gender === "undefined" ? "Unknown" : gender;
        // 或者使用更简洁的判定方式
        // gender = gender || "Unknown";
        return {
            name: name,
            age: age,
            gender: gender
        };
    }
    
    console.log(setInfo("Wango", 24, "male"));
    // {name: "Wango", age: 24, gender: "male"}
    console.log(setInfo("Lily", 25));
    // name: "Lily", age: 25, gender: "Unknown"}
    
    // ES6处理默认参数的方法
    // 为形参赋值
    // 若指定了实参的值,默认值会被覆盖,否则使用默认值
    function setInfo(name, age, gender = "Unknown") {
        return {
            name: name,
            age: age,
            gender: gender
        };
    }
    
    console.log(setInfo("Wango", 24, "male"));
    // {name: "Wango", age: 24, gender: "male"}
    console.log(setInfo("Lily", 25));
    // name: "Lily", age: 25, gender: "Unknown"}
    

    对后面的默认参数赋值时可以引用前面的默认参数

  • 相关阅读:
    P3723 【[AH2017/HNOI2017]礼物】
    P4555 【[国家集训队]最长双回文串】
    manacher学习笔记
    多项式学习笔记
    题解 CF1097F 【Alex and a TV Show】
    docker数据卷容器
    python基础学习
    docker监控之cadvisor
    docker监控系统
    ssh配置详解及公私钥批量分发
  • 原文地址:https://www.cnblogs.com/hycstar/p/13997350.html
Copyright © 2011-2022 走看看