JavaScript 函数表达式 闭包

创建函数有两种方式:一种是函数声明,另一种是函数表达式


1.函数声明

function functionName(i,j){
    //函数体
}

说明:首先是函数关键字function,然后是函数的名字functionName
最大的特征:函数声明提升,这就意味着函数声明可以放在调用它的语句之后

sayHi();//函数调用在前
function sayHi(){//函数声明在后
    alert("hi");
}

2.函数表达式

最常见的方式如下:

var functionName=function(i,j){
    //函数体
}

说明:形式很像变量赋值语句,即创建一个函数并将它赋给变量functionName。这种情况下创建的函数叫做匿名函数(也叫拉姆达函数),因为function关键字后面没有标识符。
重要特征:必须先声明再调用。

sayHi();//错误:函数不存在
var sayHi=function(){
    alert("Hi);
}
闭包

闭包是指:有权访问另一个函数作用域中的变量的函数 闭包常见的创建方式:在一个函数内部创建另一个函数。

function createComparsionFunction(propertyName){
    return function(object1,object2){
    //这是一个闭包,不能简单认为匿名函数就是闭包
        var value1=object1[propertyName];
        var value2=object2[propertyName];
        if(value1<value2){
            return -1;
        }
        else if(value1>value2){
            return 1;
        }
        else{
            return 0;
        }
    ;
}
//创建函数
var compareNames=creatComparsionFunction("name");
//调用函数
var result=compareNames({name:"Nicholas"},{name:"Greg"});
//解除对匿名函数的引用(以便释放内存)
compareNames=null;

说明:在匿名函数从createComparsionFunction()中被返回后,它的作用域被初始化为包含 createComparsionFunction()函数的活动对象和全局变量对象。
更重要的是: createComparsionFunction()函数在执行完毕后,它的活动对象也不会被销毁!!!,因为匿名函数的作用域链仍然在引用这个活动对象。
换句话说:当createComparsionFunction()函数返回后,其作用域链被销毁,但其活动对象仍然在内存中,直到匿名函数被销毁之后才销毁。
通过compareNames=null,解除该函数的引用,等于通知垃圾回收例程将其回收。随着匿名函数的作用域链被销毁,其他作用域(除了全局作用域)也都可以安全的销毁了。
这里写图片描述

  • 闭包的副作用:即闭包只能取得包含函数(外部函数)中任何变量的最后一个值,注意哦是最后一个!!!
function createFunctions(){
    var result=new Array();
    for (var i=0; i<10; i++){
        result[i]=function(){//这是一个闭包,也是匿名函数
            return i;
        };
        //result[]里面保存的都是10,而不是期望的索引值0到9.
        //什么情况看后面!!!
    return result;
}

**解释:每个匿名函数的作用域链中都保存这createFunction()函数的活动对象。就像其前面所说的当createFunction()函数返回后,其作用域链被销毁,但其活动对象仍然在内存中,直到匿名函数被销毁之后才销毁。 它返回之后i=10。而每个函数都引用了保存这个变量i的活动对象,所以每个函数的内部都是10

  • 解决方法:创建另一个匿名函数强制让闭包的行为符合预期

function createFunctions(){
    var result=new Array();
    for (var i=0; i<10; i++){
        result[i]=function(num){
        //再创建一个匿名函数,有一个参数num
        //每次调用时都将变量i的当前值赋给参数num
            return function(){
            //创建一个返回num的闭包
                return num;
            };
        }(i);//每次调用时都将变量i的当前值赋给参数num
        //这样result[]中的每个函数都有自己num变量的一个副本,因此能返回各个不同的值
    }
        //result[]里面保存的是期望的索引值0到9.
    return result;
}
  • 闭包中的this对象
    我们知道this对象在运行时基于函数的执行环境绑定的:在全局函数中,this等于window对象。而当函数被作为某个对象的方法调用时,this等于那个对象。
    不过匿名函数的执行环境具有全局性,因此this对象通常指向window对象
var name="The Window",
var object={
    name:"my boject";
    getNameFunction:function(){
        return function(){
            rerurn this.name;
        };
    }
}
alert(object.getNameFunction()());//The Window
//object.getNameFunction()返回一个函数
//object.getNameFunction()()立即调用返回的这个函数

解决:将外部作用域中的this对象保存在一个闭包能够访问到的变量里,就可以让闭包访问这个对象了

var name="The Window",
var object={
    name:"My Object";
    getNameFunction:function(){
        var that=this;//外部的this对象保存在that中
        return function(){
            rerurn that.name;//而不是this.name
        };
    }
}
alert(object.getNameFunction()());//My Object
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值