4、函数表达式

简介

1.1

定义函数的两种方式:

  • 1、函数声明:函数声明提升,在执行代码之前会先读取函数声明,name属性值为function后的标识符(ie没有)
  • 2、函数表达式:使用必须在定义之后,name属性值是空字符串

1.2 递归

function factorial(num){
    if(num<=1){
        return 1;
    }else{
        return num*factorial(num-1);
    }
}
undefined
factorial(5);
//120

这是一个简单的递归表达式,此时,若是将函数引用替换将会发生错误

var newfunc = factorial;
factorial = null;
newfunc(5);//出现异常

解决方法有两种

  • 1、使用arguments.callee,此指针会指向当前执行的函数
  • 2、使用函数命名表达式

1.3 闭包

1.3.1 作用域链及其细节

当某个函数被调用时,会创建一个执行环境以及相应的作用域链。然后使用arguments和其它命名参数的值来初始化这个函数的活动对象。此时,作用域链的形式为参见下图

在这里插入图片描述

function compare(value1,value2){
    if(value1 < value2){
        return -1;
    }else if(value1 > value2){
        return 1;
    }else{
        return 0
    }
}
var result = compare(5,10);

注意函数活动对象以及全局变量对象的的形式

1.3.2 变量对象
  • 1、每个执行环境都有一个表示变量的对象(此对象包含此环境内的所有变量)—变量对象
  • 2、全局环境的变量对象始终存在,函数的变量对象在函数接受后消失
  • 3、创建函数 时,会创建一个预先包含全局环境的作用域链,被保存在内部属性[[Scope]]中
  • 4、调用函数时,会创建一个执行环境,然后通过复制[[Scope]]属性值对象来构建作用域链,随后将活动对象(作为变量对象使用)推入执行环境作用域链的的前端
  • 5、无论什么时候在函数中访问一个变量时,都会从作用域中搜索具有相同名字的变量。一般来讲,函数执行完毕后,局部的对象会被销毁,内存中仅保留全局执行环境变量对象

综述:函数在创建提供了作用域链的环境基础(函数的[[Scope]]属性),函数调用时利用变量对象构建起当前函数的作用域

1.3.3 闭包情形
  • 当在一个函数A内部定义函数B时,会将A的活动对象添加到其作用域链
  • 当A执行完之后,其活动对象不会被摧毁,而是一直保存在内存中,知道匿名函数被摧毁
    在这里插入图片描述
    闭包情形的作用域链如上图所示
1.3.4闭包与变量
  • 闭包只能取得包含函数变量的最后一个值(显而易见,闭包是对外部变量对象的引用)
function createFunction(){
    var result = new Array();
    for(var i=0;i<10;i++){
        result[i] = function(){return i}
    }
    return result;
}

var re = createFunction();
re[0]();
//10

上面是一个非常典型的例子。

  • 1、外部函数 createFunction执行结束后,其内部变量(i)仍然存在于内存中。
  • 2、闭包只取得了i的最后一个值 即 10.
    要想返回正常的函数,只需要将i变为匿名函数的内部对象即可或者创建10个不同的变量

function createNiceFunction(){
    var result = new Array();
    for(var i=0;i<10;i++){
        result[i] = (function(j){
            //块级作用域
            return function(){return j;};
        })(i);
    }
    return result
};
var re =  createNiceFunction();  
re[1]();
//1
1.3.4 关于this对象

匿名函数的执行环境具有全局性,其this对象通常指向windows。这样理解 ,在函数里面定义变量时,如果不加上 var 那么这个变量为全局变量,这里的匿名函数也是如此。
若是想在闭包内使用当前的作用域,可以利用闭包的性质,外部定义this变量,然后在闭包内部引用

1.4 模仿块级作用域

javaScript中是没有块级作用域的
利用 匿名函数实现块级作用域 语法为 (function(){ 块级作用域在这里})();
这种写法就是一个直接执行函数;
使用:在需要使用临时变量或者私有作用域时,使用块级作用域

1.5 私有变量

任何函数中定义的变量都是私有变量
然后可以定义特权方法访问他们,类似java

function MyObject(){
    var privateVariable = 10;//私有变量
    function privateFunction(){//私有方法
        return false;
    }
    this.publicMethod = function(){
        privateVariable++;
        return privateFunction();
    };

}
var myobj = new MyObject();
myobj.publicMethod;
//ƒ (){
   //     privateVariable++;
    //    return privateFunction();
//    }
var re = myobj.publicMethod();
re;
//false
1.5.1 单例(只有一个实例的对象)创建私有变量和特权方法

即创建对象时,将其放在块级作用域中 语法 var obj = function(){ 返回对象的代码,这里面为私有作用去 return onj}();

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值