折腾自己的js闭包(一)
闭包是什么鬼?
15年10月份初到现在的公司时,有天晚上加班后临下班时,当时的组长问我知道闭包不,由于我是半路出家来做程序的,几乎很少用到闭包这个东东,并不是很了解这个概念,组长写出了这么段代码。
var temp = {
data: [],
totalRecords: 0
};
(function(dm){
for(var i=0;i<10;i++){
dm.data.push(i*i);
dm.totalRecords += 1;
}
})(temp);
console.log(temp); //结果得到 object{data:Array[10],totalRecords:10}
我当时就觉得很神奇了,函数内部的dm变量,经过这么一折腾,在外面也就可以访问到其变化之后的值了,原因何在?于是乎,后来我花了时间来研究这个闭包,到底是什么鬼?到底会有什么时候需要用到?
首先来说我们平常遇到的一个很普遍的变量的作用域的问题,例如有如下js代码:
function f1(){
var strB = strA + " is writing code."
document.write(strB);
}
f1(); //结果当然是2个字符串拼接起来 xiangxiao's weekend is writing code.
这个无需多解释,因为在js函数内部肯定是可以访问并使用在函数体外面的变量的嘛;
再来看另一段js代码:
function f1(){
var strA = "xiangxiao's weekend";
var strB = strA + " is writing code."
};
document.write(strB); //此处报错
报错的原因就是这个strA和strB是函数f1 的局部变量,它 的作用域仅限于f1函数体内部,外部是访问不了的,这里牵扯到作用域的问题,既然说到这儿也就耗一点篇幅来讲这个作用域的东东吧。
在JavaScript中,函数也是对象,也可以通过var func = new Function('a','b','return a+b')这样的形式来定义函数,一般不这样做的原因是将众多代码弄在一个超长的字符串里,代码的可读性太差。简单的说,作用域就是变量与函数的可访问范围,即作用域控制着变量与函数的可见性和生命周期。在JavaScript中,变量的作用域有全局作用域和局部作用域两种。
1、全局作用域
即在代码中任何地方都能访问到的对象拥有全局作用域,一般来说以下几种情形拥有全局作用域:
(1)最外层函数和在最外层函数外面定义的变量拥有全局作用域,例如:
(2)未使用var关键字定义的变量也被赋予了全局的作用域;
};
say(); //结果是xiangxiao
document.write(authorName);//报错
document.write(blogName);//结果是dearxiangxiao
(3)所有window对象的属性拥有全局作用域。
这个就无需举例了,window.innerWidth诸如此类的东东,用得也蛮多的了。window对象还可自定义属性和方法,当然跟这里没啥关系了。
2、局部作用域
和全局作用域相反,局部作用域一般只在固定的代码片段内可访问到,最常见的例如函数内部,所以在一些地方也会看到有人把这种作用域称为函数作用域。
之前1中的(1)那个例子
Fn(); // 这是语句,Statement;解释器遇到语句是会运行它的。
function Fn(){ //some code}();
当然是不能,但是为什么呢?因为 function Fn(){ //some code} 这个部分只是一个声明,对于解释器来说,就好像你写了一个字符串 "function Fn(){ //some code}",它需要使用解析函数,比如 eval() 来执行它才可以。所以把 () 直接放在声明后面是不会执行,这是错误的语法。
如何把它变得正确?说起来也简单,只要把 声明 变成 表达式(Expression) 就可以了。实际上转变表达式的办法还是很多的,最常见的办法是把函数声明用一对 () 包裹起来,于是就变成了:
(function Fn() { //some code})();
这样等价于:
function Fn() { //some code};
Fn();
另外,还有很多其他写法可以将函数声明变为表达式,比如:
!function() { //some code}();
+function() {// some code}();
再回到那段组长写的代码
var temp = {
data: [],
totalRecords: 0
};
(function(dm){
for(var i=0;i<10;i++){
dm.data.push(i*i);
dm.totalRecords += 1;
}
})(temp);
console.log(temp);
这里相当于定义了一个以temp为参数的函数,(function(dm){ //......省略代码})() 这部分里第一个括号里相当于定义了一个函数,返回值是一个函数,第二个括号就是在执行这个被返回的函数了,dm只不过是形参,temp的值在那个匿名函数里改变了,后面再打印temp的值,理所当然的是 object{data:Array[10],totalRecords:10}了。
这就是这篇博文的全部内容了,个人简见解,不喜勿喷,后面我还会研究下闭包的具体用途。
ps:吐槽一下成都的这个鬼天气,今年感觉没春天啊,冬天之后立马到夏天,放个清明节下了2天雨。
折腾自己的js闭包(一)的更多相关文章
- 折腾自己的js闭包(二)
前面我大致探讨了js里的闭包的相关概念,那么,到底在什么时候用它最好呢?存在即真理,只不过以前没发现它而已,先来看看下面的这几个用途吧 一.我首先想到的就是从函数外面访问它的内部变量,从而达到自己的一 ...
- js闭包的作用域以及闭包案列的介绍:
转载▼ 标签: it js闭包的作用域以及闭包案列的介绍: 首先我们根据前面的介绍来分析js闭包有什么作用,他会给我们编程带来什么好处? 闭包是为了更方便我们在处理js函数的时候会遇到以下的几 ...
- 大部分人都会做错的经典JS闭包面试题
由工作中演变而来的面试题 这是一个我工作当中的遇到的一个问题,似乎很有趣,就当做了一道题去面试,发现几乎没人能全部答对并说出原因,遂拿出来聊一聊吧. 先看题目代码: function fun(n,o) ...
- Js闭包常见三种用法
Js闭包特性源于内部函数可以将外部函数的活动对象保存在自己的作用域链上,所以使内部函数的可以将外部函数的活动对象占为己有,可以在外部函数销毁时依然存有外部函数内的活动对象内容,这样做的好处是可 ...
- js闭包之初步理解( JavaScript closure)
闭包一直是js中一个比较难于理解的东西,而平时用途又非常多,因此不得不对闭包进行必要的理解,现在来说说我对js闭包的理解. 要理解闭包,肯定是要先了解js的一个重要特性, 回想一下,那就是函数作用域, ...
- (原创)JS闭包看代码理解
<html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="C ...
- js闭包理解
js闭包的作用是使函数外可以访问函数内部的变量,是通过 在函数内部 定义 访问函数内变量 的函数实现的,内部的一个函数产生一个闭包 function a() { var i=0; return fun ...
- js闭包理解实例小结
Js闭包 闭包前要了解的知识 1. 函数作用域 (1).Js语言特殊之处在于函数内部可以直接读取全局变量 <script type="text/javascript"> ...
- Js闭包的用途
本来想总结一点JavaScript中的闭包的一些用法,在查资料的时候发现了一篇很好的文章,就转过来收藏了,下面附上传送门: js闭包的用途 ---------sunlylorn 我们来看看闭包的用途. ...
随机推荐
- EditPlus编辑java代码 常规配置
- Python3 迭代器与生成器 - 学习笔记
可迭代对象(Iterable) 迭代器(Iterator) 定义 迭代器和可迭代对象的区别 创建一个迭代器 创建一个迭代器类 使用内置iter()函数 StopIteration异常 生成器(gene ...
- Spring官网阅读(二)(依赖注入及方法注入)
上篇文章我们学习了官网中的1.2,1.3两小节,主要是涉及了容器,以及Spring实例化对象的一些知识.这篇文章我们继续学习Spring官网,主要是针对1.4小节,主要涉及到Spring的依赖注入.虽 ...
- 【FPGA篇章六】FPGA编译向导:详解编译预处理功能
欢迎大家关注我的微信公众账号,支持程序媛写出更多优秀的文章 Verilog HDL语言和C语言一样也提供了编译预处理功能. Verilog HDL允许在程序中使用特殊的编译预处理语句. 在编译时,通常 ...
- 【Kafka】Consumer API
Consumer API Kafka官网文档给了基本格式 http://kafka.apachecn.org/10/javadoc/index.html?org/apache/kafka/client ...
- asp.net core计划任务探索之hangfire+redis+cluster
研究了一整天的quartz.net,发现一直无法解决cluster模式下多个node独立运行的问题,改了很多配置项,仍然是每个node各自为战.本来cluster模式下的各个node应该是负载均衡的, ...
- Mysql常用sql语句(17)- left/right join 外连接
测试必备的Mysql常用sql语句系列 https://www.cnblogs.com/poloyy/category/1683347.html 前言 外连接分为两种:left join.right ...
- [zoj3591]Nim 游戏
题意:有n堆火柴,选择连续若干堆火柴进行Nim游戏,求让先手胜的选择方案数. 思路:让先手胜等同于这些数的异或值不同于0,不妨转化为求让先手败的方案数.此时记录一个前缀的异或和val[i],那么答案就 ...
- 透过面试题掌握HashMap【持续更新中】
本文主要是自己阅读了HashMap和ConcurrentHashMap源码及一些Java容器类相关的博客后,找了一些很多面经中涉及到的Java容器相关的面试题,自己全部手写的解答,也花了一些流程图,之 ...
- 字符串匹配算法:Sunday算法
背景 我们第一次接触字符串匹配,想到的肯定是直接用2个循环来遍历,这样代码虽然简单,但时间复杂度却是\(Ω(m*n)\),也就是达到了字符串匹配效率的下限.于是后来人经过研究,构造出了著名的KMP算法 ...