ES5高级特性


闭包

指的是一个函数能够使用另一个函数里的变量。

函数嵌套函数,内部函数就是闭包

  • 语法
一般是在一个函数里定义一个子函数,并返回子函数。
function father(){
    var num=0;
    function sun(){
        num++;
    }
    return sun;//闭包函数
}
//外部的访问不到num, 原理:执行上下文栈
  • 正常情况下:函数执行完,内部变量会销毁(释放内存空间)

  • 闭包:内部函数没有执行完,外部函数变量不会被销毁

  • 应用:

    • 封装一段代码
    • 实现私有变量,节约全局变量
    • 实现块级作用域,后期有letconst来代替。

IIFE(立即执行函数)

概念

IIFE(immediately invoked Function Expression)- 立即调用函数表达式

  • 函数声明

    //函数声明式
    function text(){
        console.log('Function Declaration')
    }
    text() //()函数名后面的括号,叫做执行符号
    
  • 函数表达式

    //将一个(匿名)函数(函数声明式) 赋值给一个变量的形式   函数表达式
    var text = function(){
        console.log('Function Expression');
    }
    

IIFE语法

(function(){
    console.log('Function Expression');
})();//这里的分号若有多个立即执行函数,必须添加,否则报错

作用

  • 可以创建一个与外界没有任何关联的作用域,独立的作用域
  • 执行完成之后,自动销毁
  • ES3,ES5没有模块的概念,立即执行函数来模拟模块化(封闭作用域,抛出接口(向外部抛出一系列属性和方法)) window上保存属性和方法

函数的柯里化

概念

  • 是把接受多个参数的函数变成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数而且返回结果的新函数的技术。
  • 即一个函数只 处理一个参数,剩余的参数就通过返回的函数进行处理
function _add(a) {
    return function(b) {
        return function(c) {
            return a + b + c;
        }
    }
}
  • 封装正则表达式检验用户输入手机邮箱

    var _check = function(check){
        return function(text){
            return check.test(text);
        }
    };
    var checkPhone = _check(/^1[34578]\d{9}$/);
    var checkEmail = _check(/^(\w)+(\.\w+)*@(\w)+((\.\w+)+)$/);
    var s=checkPhone('18388888899');
    var t=checkEmail('xxxxx@test.com');
    console.log(s,t);
    

面试题

// 实现一个add方法,使计算结果能够满足如下预期:
add(1)(2)(3) = 6;
add(1, 2, 3)(4) = 10;
add(1)(2)(3)(4)(5) = 15;


function add() {
    // 第一次执行时,定义一个数组专门用来存储所有的参数
    var _args = [].slice.call(arguments);
    // 在内部声明一个函数,利用闭包的特性保存_args并收集所有的参数值
    var adder = function () {
        var _adder = function() {
            // [].push.apply(_args, [].slice.call(arguments));
            _args.push(...arguments);
            return _adder;
        };
        // 利用隐式转换的特性,当最后执行时隐式转换,并计算最终的值返回
        _adder.toString = function () {
            return _args.reduce(function (a, b) {
                return a + b;
            });
        }
        return _adder;
    }
    // return adder.apply(null, _args);
    return adder(..._args);
}

补充

函数的隐式转换。当我们直接将函数参与其他的计算时,函数会默认调用toString方法,直接将函数体转换为字符串参与计算。

递归

  • 递归是程序的编程技巧。指函数调用自己。
function 函数名(形式参数){
    //需要通过判断来限制出现无限递归
    if(条件){
        return ; //表示递归结束。
    }
    //通过调用自己来达到类似于循环的效果
    函数名(实际参数);
}
  • 一般流程

    • 确定递归的函数是用来干什么的,功能点在哪?

    • 确定该功能能够被分解成更小的功能

    • 找到结束递归的分界点

  • 作用

    • 简化循环代码
    • 采用分治算法,让逻辑复杂的情况简单处理(将大问题分解成一个个小的问题)
  • 常见例子

    • 阶乘

      //递归案例
      function f(n){
          if(n==1){
              return 1;
          }
          return n * f(n-1);
      }
      
    • 累计(加减乘除)

    • 斐波那契数列

       //斐波那契数列 的第n项 
         // 0 1 1 2 3 5 8 13 21 34 ... 
         //f(n) = f(n-1) +f(n-2)
         function f(n){
             if(n==1){
                 return 0;
             }
             if(n==2){
                 return 1;
             }
             return f(n-1) + f(n-2);
         }
         // f(5): f(1)+f(2)+f(2)+f(1)+f(2) =0+1+1+0+1 = 3
      
    • 快速排序

      核心思想在于将排序过程分为多次,每次会吧一个数(基准数)放在合适的位置,并且该数左边的都小于,右边的都大于该数。

      快速排序利用递归来分别对左边和右边也进行排序过程

    function quickSort(arr,left,right){
        if(left>=right) return;
        var i =left,j = right;
        var key = arr[left];
        while(i!=j){
            while(i<j && arr[j]>=key){
                j--;
            }
            while(i<j && arr[i]<=key){
                i++;
            }
            if(i<j){ 3
                    var temp = arr[i];
                    arr[i] = arr[j];
                    arr[j]=temp;
                   }
        }
        arr[left]=arr[i];
        arr[i]=key;
        //一次结束
        quickSort(arr,left,i-1);
        quickSort(arr,i+1,right);
    }    
    

文章作者: 时光路人
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 时光路人 !
评论
  目录