函数表达式

说在前面 :

我们定义函数有两种方式:1.函数声明式 2.函数表达式

函数声明式:存在函数声明提升,所以可以在声明之前调用


sayHi() //hi

    //函数声明式

    function sayHi(){

      console.log('hi')

    }


函数表达式:在使用前必须被赋值

sayHi() //报错

    //函数声明式

    var sayHi = function(){

      console.log('hi')

    }

1.递归

说明:递归函数就是函数自己又调自己的情况 ,使用递归实现阶乘   :

function factorial(num){

      if(num <= 1){

        return 1;

      }else{

        return num * factorial(num-1)

      }

    }

但是这样,会有一种情况,执行下面代码时,中间把函数factorial赋值为null,递归调用时内部的factorial已经不函数了 ,报错,解决方式是用argument.calee,他会指向正在执行的函数 (严格模式无法使用)

var fun = factorial;

    factorial = null

    alert(fun(4))

2.1闭包

说明:闭包是啥?是有权访问另一个函数作用域中的变量的函数,常见闭包方式,一个函数内部创建另一个函数,内部函数访问了外部变量

function createFunction(property){

      return function(obj1,obj2){

        var val1 = obj1[property];

        var val2 = obj2[property];

        if(val1>val2){

          return 1;

        }else{

          return -1;

        }

      }

    }

// 创建函数

    var compare = createFunction('name')

    // 调用函数

    var result = compare({name:"nike"},{name:'grays'})

    // 解除对匿名函数的引用

    compare = null

内部匿名函数 使用着外部函数的参数,是可以使用到的,原因涉及到作用域链的问题 ,一个函数被调用时,会创建一个执行环境和相应的作用链,,使用argumens和其他命名参数初始化活动对象,它的外部函数的对象处在第二位,依次往外类推

2.2闭包与变量

因为保存的是整个变量对象,不是某个特殊的值,会造成一个问题,闭包只能取到函数中任何变量的最后一个值

我们看下面的例子

function createFun(){

      var result = new Array()

      for(var i = 0;i < 10;i++){

        result[i] = function(num){

          // return function(){

            return num

          // };

        }

      }

      return result;

    }

数组的每一项都是一个函数,儿每个函数内部存储的值均为  循环结束时的10,解决方法  我们可以利用函数的自执行保存每一个值

function createFun(){

      var result = new Array()

      for(var i = 0;i < 10;i++){

        result[i] = (function(num){

          return function(){

            return num

          };

        }(i))()

      }

      return result;

    }

    console.log(createFun()) //[0,1,2...9]

2.3  关于this指向

在闭包中,我们返回的是一个匿名函数,匿名函数的执行环境是全局的,所以该匿名函数里的this 是通常指向window,一般下面的情况 ,this就指向window

var name = "window";

    var obj ={

      name :"obj",

      getName : function(){

        return function(){

          return this.name

        }

      }

    }

    console.log("name====>",obj.getName()())  //window

想要this指向调用方法的对象,我们可以在return匿名函数之前定义一个属性保留this指向

var name = "window";

    var obj ={

      name :"obj",

      getName : function(){

        var that = this

        return function(){

          return that.name

        }

      }

    }

    console.log("name====>",obj.getName()())  //obj

2.4 内存泄漏

因为内部函数始终使用着外部的属性或者元素,意味着元素无法释放而被销毁,我们有必要在使用结束后,将其设为null,具体见2.1

3.模仿块级作用域

原因:

1.js中不存在块级作用域

2.只要在变量定义在函数的活动对象里,在函数内部随处可以调用

3.多次声明不会报错,对后面的声明忽略

方法:匿名函数模仿块级作用域

(function(){

      //块级作用域

    })()

实例:

function kuai(count){

      (function(){

      //块级作用域

      for(var i = 0;i < count;i++){

        alert(i)

      }

    })()

    alert(i)  //出了块级作用域  i undefined

    }

4.私有变量

js没有私有成员的概念,每个属性都是对象共有的。但是js有私有变量的定义。任何定义在函数中的变量,都是私有变量,如果我们再函数内部创建一个闭包,闭包通过自己的作用域链访问函数私有变量,

我们把能访问私有变量&私有方法的公有方法称为特权方法

function myObj(){

      // 私有变量  私有函数

      var  priPropoty = 10;

      function priFunction(){

        return false

      }

      //特权方法

      this.pubFunction = function(){

        priPropoty++;

        return  priFunction();

      }

    }

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。