JS闭包问题分析
来源:互联网 发布:电脑控制多个手机源码 编辑:程序博客网 时间:2024/06/07 03:24
介于之前在网上看到很多关于javascript闭包的问题,今天刚好在学习vue的时候也用到了,借此机会做一个笔记,留下来以后也好重新复习一下,巩固一下基础知识;
介绍一个东西之前,还是先要了解一下这是个什么?
在认识闭包之前,需要了解一个变量作用域的问题;
变量作用域无非是两种:全局变量和局部变量;
var a='koala';function f(){ var b='alecor'; alert(b);}f();//alert(b)==>alecor
简单的列子:那么这里的’a‘就是全局变量,‘b’就是局部变量
最后会弹出 ”b“这个变量的值;(这里有必要提一下,就是alert这个函数它是一个同步函数,这就意味着它单击确定后,其后的操作才能进行,否则会一直等待下去)
function f1(){ var n=999; } alert(n); // error
但是你们看,下面这种情况他就不会出现错误,原因是找不到”n”这个变量(这里有一个地方需要注意,函数内部声明变量的时候,一定要使用var命令。如果不用的话,你实际上声明了一个全局变量!)
function f1(){ n=999; } f1(); alert(n); // 999,
问题来了,如何才能访问内部变量呢???
其实也很简单,我们可以把内部变量当作函数的返回值传递出去,这样外部函数就可以范围访问内部变量了;
function f1(){ var n=999; function f2(){ alert(n) } return f2; } var result=f1(); result(); // 999
其实这里面的 f2()函数,就是一个闭包
我们来看看它是如何定义的:
闭包是指可以包含自由(未绑定到特定对象)变量的代码块;这些变量不是在这个代码块内或者任何全局上下文中定义的,而是在定义代码块的环境中定义(局部变量)(来自百度)
这样理解肯定很晦涩难懂,我的理解是,闭包就是能够读取其他函数内部变量的函数。
我们接下来再看一下例子(可能跨度有些大)
var name = "The Window"; var object = { name : "My Object", getNameFunc : function(){ return function(){ return this.name; }; } }; alert(object.getNameFunc()());
其实这道题是我当初我去面试JavaWeb工程师的时候,碰到的一个题,当初就没系统的学习javascript,一直到现在才慢慢把javascript系统的学习,毕竟自己以后是想从事一个全栈,期待全栈后面的世界又会有什么在等着我???
接着看这个题目,
我们来分析一下,为了方便 我直接在备注中写分析
var name = "The Window"; 全局变量 var object = { //对象,拥有name属性和getNameFunc函数 name : "My Object", //内部变量 getNameFunc : function(){ return function(){ //第一层返回作用域(object对象) return this.name; //第二层返回作用域(window对象) }; } }; alert(object.getNameFunc()()); 这个函数最后输出的是最外一层,因为它的作用域是全局对象,因此调用最外一层的name属性
让我们在看这个列子:
var name = "The Window"; var object = { name : "My Object", getNameFunc : function(){ var that = this; return function(){ return that.name; }; } }; alert(object.getNameFunc()());在这个示例里面, 我们把object对象的this,赋值给that对象,那么此时that对象存在getNameFunc函数的局部变量,因此最后输出的回事 "myObject"
接着我们看一个关于计时器闭包的问题;
for(var i=0;i<5;i++){ setTimeout(function(){ alert(i); },i*100); }
在上述的代码中,你认为他会输出什么,通常来说你肯定以为他会输出,0,1,2,3,4 (间隔一秒钟)
但是其实这是错的,他会连续输出5个5为什么呢???
我们仔细阅读代码看看
setTimeout(function(){ alert(i); },i*100);
在这段定时器的代码中,你能找到的的参数吗? 里面的alert(i)这个i变量不就是得吗???其实并不然;
我们知道函数是可以传递参数的,但是在这个定时器的函数里面它没有给形参,也就是说定时器在调用这个函数的时候它是没有参数的,也可以说他没有局部参数;因此这里的函数仅仅只做在定时器里面的函数声明使用,并没有调用;
所以最后他会输出 5 5 5 5 5,
这里还有一点就是 定时器它是一个异步函数,它必须要等线程队列中没有主线程才会执行它自身,或者说是等队列里面的主线程执行完了,定时器才会作用;所以等for循环走完之后,定时器才开始计时,由于Javascript语言特有的”链式作用域”结构(chain scope),子对象会一级一级地向上寻找所有父对象的变量;所以for循环完之后,找到它的上一级i,也就是5,因此他会连续输出5个5;(需要好好理解)
那么怎么让他一次输出0-1-2-3-4呢???,我这里给出两种方式参考
第一种:函数当作结果值返回
var createFunction=function(i){ return function(){ alert(i); } }for(var i=0;i<5;i++){ setTimeout(createFunction(i),i*1000); }每一次运行的时候都会给函数传递一个值,此时函数执行完后会返回一个值;
第二种:自执行函数,
for(var i = 0; i < 5; i++) { setTimeout(function(i) { alert(i) }(i), i * 1000); }如何怎么理解自执行函数呢??传送门:[自执行函数](http://blog.csdn.net/limlimlim/article/details/9198111)
第三种
for(var i = 0; i < 5; i++) { (function(i) { setTimeout(function() { alert(i) }, i * 1000); })(i) }
这两种方式都是自执行函数,一种放在计时器里面使用,一种放在计时器外面使用;
好了,今晚就介绍这么多,接下来去学习vue2.0了,果然代码是敲出来的,自己思路更加清晰了很多;
- JS闭包问题分析
- [js点滴]javaScript闭包引起的问题及分析
- js 闭包 问题
- JS 闭包问题
- JS闭包问题?
- js闭包问题
- js闭包简要分析
- JS的闭包问题
- js经典闭包问题
- JS闭包问题-详解
- js中的闭包问题
- js经典闭包问题
- js的闭包问题
- JS冒泡和闭包案例分析
- JS冒泡和闭包案例分析
- js闭包的一个小问题
- 一个js闭包问题的解答
- JS的永恒闭包问题
- 3分钟读懂移动端rem使用方法
- 正确地尾调用
- netty simple demo
- 用XSL进行日期格式转换
- ADO.net用法简介
- JS闭包问题分析
- springMvc+spring+mybatis集成的mvc模型
- Number Sequence
- 01:最长上升子序列
- Java虚拟机--非堆内存的参数配置(五)
- 信号量
- Iterator 迭代器设计模式
- 同一个世界 理论分析+所有关卡攻略
- Thread.currentThread().getContextClassLoader() 和 Class.getClassLoader()区别