博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
深入理解闭包系列第五篇——闭包的10种形式
阅读量:7002 次
发布时间:2019-06-27

本文共 3056 字,大约阅读时间需要 10 分钟。

前面的话

  根据,我们知道,无论通过何种手段,只要将内部函数传递到所在的词法作用域以外,它都会持有对原始作用域的引用,无论在何处执行这个函数都会使用闭包。接下来,本文将详细介绍闭包的10种形式

 

返回值

  最常用的一种形式是函数作为返回值被返回

var F = function(){    var b = 'local';    var N = function(){        return b;    }    return N;}console.log(F()());

 

函数赋值

  一种变形的形式是将内部函数赋值给一个外部变量

var inner;var F = function(){    var b = 'local';    var N = function(){        return b;    };    inner = N;};F();console.log(inner());

 

函数参数

  闭包可以通过函数参数传递函数的形式来实现

var Inner = function(fn){    console.log(fn());}var F = function(){    var b = 'local';    var N = function(){        return b;    }    Inner(N);}F();

 

IIFE

  由前面的示例代码可知,函数F()都是在声明后立即被调用,因此可以使用IIFE来替代。但是,要注意的是,这里的Inner()只能使用函数声明语句的形式,而不能使用函数表达式。详细原因

function Inner(fn){    console.log(fn());}(function(){    var b = 'local';    var N = function(){        return b;    }    Inner(N);})();

 

循环赋值

  在闭包问题上,最常见的一个错误就是循环赋值的错误。关于其错误原因的详细解释

function foo(){    var arr = [];    for(var i = 0; i < 2; i++){        arr[i] = function(){            return i;        }    }    return arr;}var bar = foo();console.log(bar[0]());//2

  正确的写法如下

function foo(){    var arr = [];    for(var i = 0; i < 2; i++){        arr[i] = (function fn(j){            return function test(){                return j;            }        })(i);    }    return arr;}var bar = foo();console.log(bar[0]());//0

 

g(s)etter

  我们通过提供getter()和setter()函数来将要操作的变量保存在函数内部,防止其暴露在外部

var getValue,setValue;(function(){    var secret = 0;    getValue = function(){        return secret;    }    setValue = function(v){        if(typeof v === 'number'){            secret = v;        }    }})();console.log(getValue());//0setValue(1);console.log(getValue());//1

 

迭代器

  我们经常使用闭包来实现一个累加器

var add = (function(){    var counter = 0;    return function(){        return ++counter;     }})();console.log(add())//1console.log(add())//2

  类似地,使用闭包可以很方便的实现一个迭代器

function setup(x){    var i = 0;    return function(){        return x[i++];    }}var next = setup(['a','b','c']);console.log(next());//'a'console.log(next());//'b'console.log(next());//'c'

 

区分首次

var firstLoad = (function(){  var _list = [];  return function(id){    if(_list.indexOf(id) >= 0){      return false;    }else{      _list.push(id);      return true;    }  }})();firstLoad(10);//truefirstLoad(10);//falsefirstLoad(20);//truefirstLoad(20);//false

 

缓存机制

  通过闭包加入缓存机制,使得相同的参数不用重复计算,来提高函数的性能

  未加入缓存机制前的代码如下

var mult = function(){  var a = 1;  for(var i = 0,len = arguments.length; i

  加入缓存机制后,代码如下

var mult = function(){  var cache = {};  var calculate = function(){    var a = 1;    for(var i = 0,len = arguments.length; i

 

img对象

  img对象经常用于数据上报

var report = function(src){  var img = new Image();  img.src = src;}report('http://xx.com/getUserInfo');

  但是,在一些低版本浏览器中,使用report函数进行数据上报会丢失30%左右的数据,也就是说,report函数并不是每一次都成功地发起了HTTP请求

  原因是img是report函数中的局部变量,当report函数的调用结束后,img局部变量随即被销毁,而此时或许还没来得及发出HTTP请求,所以此次请求就会丢失掉

  现在把img变量用闭包封闭起来,就能解决请求丢失的问题

var report = (function(){  var imgs = [];  return function(src){    var img = new Image();    imgs.push(img);    img.src = src;  }})()report('http://xx.com/getUserInfo');

 

转载地址:http://geevl.baihongyu.com/

你可能感兴趣的文章
对使用Redux和Redux-saga管理状态的思考
查看>>
vscode中执行gulp的task
查看>>
intelli idea mac 的安装与配置
查看>>
说说如何使用 Tomcat 搭建文件服务器
查看>>
Vitalik探讨改进以太坊Casper CBC协议
查看>>
猎头最爱问的java面试题附答案(三)
查看>>
说说你生活中高颜值的程序员?
查看>>
从科学记数法到浮点数标准IEEE 754
查看>>
Netty杂记1—BIO网络编程
查看>>
Vue: Binding与Watcher
查看>>
Swift泛型定义 同时限定T的类(class)和多协议(protocol)
查看>>
从闭包函数的变量自增的角度 - 解析js垃圾回收机制
查看>>
pip安装报错return _setlocale(category, locale)locale.Error: unsupported locale setti
查看>>
在 Create React App 项目中使用 Prettier
查看>>
表格数据处理的2种写法,伪元素和操作dom
查看>>
LeetCode11.盛最多水的容器 JavaScript
查看>>
在Spring 5中调试Reactive Streams
查看>>
SpingMvc复杂参数传收总结
查看>>
Shell脚本(1)
查看>>
网页上的声音如何在线录制,电脑音频录制软件哪个好
查看>>