设为首页 加入收藏

TOP

js闭包函数(一)
2019-09-17 19:09:36 】 浏览:131
Tags:函数

闭包函数

什么是闭包函数?

闭包函数是一种函数的使用方式,最常见的如下:

function fn1(){
    function fn(){

    }
    return fn;
}

这种函数的嵌套方式就是闭包函数,这种模式的好处是可以让内层函数访问到外层函数的变量,并且让函数整体不至于因为函数的执行完毕而被销毁。

例如:

function fn1(){
    var a =10;
    function fn(){
        console.log(a); // 10
    }
    return fn;
}

再比如下面的代码,随着函数的每次执行,变量的值都会进行递增1,原因是因为外层函数的变量处于内层函数的作用域链当中,被内层函数所使用着,当js垃圾回收机制读取到这一情况后就不会进行垃圾回收。

例如:

function fn1(){
    var a = 1;
    function fn(){
        a++;
        console.log(a);
    }
    return fn;
}

// 调用函数
var x  = fn1();
x(); // 2
x();//3

闭包函数在js的开发当中是非常常见的写法,例如下面这种写法,功能是实现了对数组的一些常规操作的封装,也是属于对闭包函数的一种应用。

let Utils = (function(){
    var list = [];
    return {
        add:function(item){
            if(list.indexOf(item)>-1) return; // 如果数组内元素存在,那么不在重复添加
            list.push(item);
        },
        remove:function(item){
            if(list.indexOf(item) < 0) return; // 如果要删除的数组数组之内不存在,那么就返回
            list.splice(list.indexOf(item),1);
        },
        get_length:function(){
            return list.length;
        },
        get_showData:function() {
            return list;
        }
    }
})();
Utils.add("hello,world");
Utils.add("this is test");
console.log(Utils.get_showData());// ["hello,world","this is test"]

在上面的代码中,函数嵌套函数形成了闭包函数的结构,在开发中是比较常见的写法。

闭包的概念:

闭包是指有权限访问上一级父作用域的变量的函数.

立即执行函数(IIFE)

在js开发中,经常碰到立即执行函数的写法。大体如下:

// 下面的这种写法就是立即执行函数
// 在函数内部的内容会自动执行
(function(){
    var a = 10;
    var b = 20;
    console.log(a+b); // 30
})();

我们也可以通过第二个括号内传入参数:

(function(i){
    console.log(i);
})(i);

这种自调用的写法本质上来讲也是一个闭包函数

通过这种闭包函数,我们可以有效的避免变量污染等问题,从而创建一个独立的作用域。

但是问题相对来说也很明显,就是在这个独立的作用域当中,我们没有办法将其中的函数或者变量让外部访问的到。所以如果我们在外部需要
访问这个立即执行函数中的变量或者方法,我们就需要通过第二个括号将window这个全局的变量对象传入,并且将需要外部访问的变量或者函数赋值
给window,这样做相当于将其暴露在了全局的作用域范围之内。

需要注意的是,通常情况下我们只需要将必要的方法暴露,这样才能保证代码并不会相互产生过多的影响,从而降低耦合度。

例如:

(function (window){
    var a = 10; // 私有属性

    function show(){
        return a++;
    }


    function sayHello(){ // 私有方法
        alert("hello,world");
    }
    window.show = show;// 将show方法暴露在外部
})(window);

需要理解的是,在很多的代码中,总是在(function(){})()的最前面加上一个;,目的是为了防止合并代码的时候js将代码解析成(function(){})()(function(){})()这种情况。

闭包函数的变异

因为js的特殊性,所以很多时候我们在学习js的时候,除了js代码的语法以外,还要学习很多为了解决实际问题的方案,例如下面的这种写法就是为了
实现module的写法。

例如:

var testModule = function(){
    var name = "张三"; // 私有属性,外部无法访问

    return {
        get_name:function(){ // 暴露在外部的方法
            alert(name);
        },
        set_name:function(new_name){ // 暴露在外部的方法
            name = new_name;
        }
    }
}

我们也可以将这种写法进行升级,和立即执行函数进行适度的结合也是常见的写法:

例如:

var blogModule = (function (my) {
    my.name = "zhangsan";
    // 添加一些功能   
    my.sayHello = function(){
        console.log(this.name)
    }
    return my;
} (blogModule || {}));  

console.log(blogModule.sayHello())

自调用函数(自执行匿名函数(Self-executing anonymous function))和立即执行函数的区别

自调用函数其实也就是递归函数

自调用函数顾名思义,就是调用自身的函数,而立即执行函数则是立即会及执行的函数。

下面是二者的一些比较:

// 这是一个自执行的函数,函数内部执行自身,递归
function foo() { foo(); }

// 这是一个自执行的匿名函数,因为没有标示名称
// 必须使用arguments.callee属性来执行自己
var foo = function () { arguments.callee(); };

// 这可能也是一个自执行的匿名函数,仅仅是foo标示名称引用它自身
// 如果你将foo改变成其它的,你将得到一个used-to-self-execute匿名函数
var foo = function () { foo(); };

// 有些人叫这个是自执行的匿名函数(即便它不是),因为它没有调用自身,它只是立即执行而已。
(function () { /* code */ } ());

// 为函数表达式添加一个标示名称,可以方便Debug
// 但一定命名了,这个函数就不再是匿名的了
(function foo() { /* code */ } ());

// 立即调用的函数表达式(IIFE)也可以自执行,不过可能不常用罢了
(function () { arguments.callee(); } ());
(function foo() { foo(); } ());

作用域与作用域链

  1. 作用域

所谓的作用域,指的就是变量函数可访问范围,控制着变量和函数的

首页 上一页 1 2 3 4 5 6 下一页 尾页 1/6/6
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇全面分析前端的网络请求方式 下一篇微信小程序-强制手机端更新

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目