提供一种间接的方式可以访问到函数内部的数据(变量)javascript
在函数内部建立函数(内部函数),在这个内部函数中,能够操做外部函数中的变量
01 在函数(外部)中建立函数(内部函数),在该函数(内部函数)中操做外部函数中的变量
02 在外部函数中,把内部函数做为返回值返回
03 调用外部函数,并接收其返回值(是一个函数)
04 调用接收到的返回值(内部函数),来间接的操做外部函数中的变量segmentfault
function inner(){ var num = 10; return num; }; var fn1 = inner(); var fn2 = inner(); console.log(fn1); //10 console.log(fn2); //10
其实每个函数体就是一个闭包,但该博文所指的闭包并无这么简单。这里的inner尽管也能从外部读取inner函数的局部变量,但fn1,fn2是经过各开辟一个内存空间去存储num的值,就至关于fn1=new Number(10),fn2 = new Number(10),这样不能修改inner里面的变量值,并不能达到获取内部变量和修改内部变量,其次咱们想要获得的是将inner内部的变量暴露出外部使用,这明显fn1,fn2各玩各的。数组
需求:想要在函外面(另一个函数中)访问某一个函数内部的局部变量
闭包:在函数内部使用函数
闭包链式做用域:一个子对象能够沿着他的父对象访问父对象的全部变量,反之,则不行多线程
function sum() { var a = 10; function showMessage() { //根据链式做用域在这个函数内部能够访问变量a alert(a); } return showMessage; } //调用sum var showMes = sum();//调用完成后,正常状况局部变量应该被销毁,但最终没有 showMes();
//经过上面的使用,局部变量a没有销毁
//闭包的做用:1.延长局部变量的生命周期
//若是有不少局部变量,那么延长他们的生命周期,会大量占用内存,慎重使用闭包
1、获取单个数据(考虑赋值)并发
function func() { var num = 123; return function (a) { if (a !== undefined) //容错操做 { num = a; } return num; } } var f1 = func(); var x = f1(456); //经过参数修改内部变量 var y = f1(); console.log(x); //456 console.log(y); //123
function func() { var name = "张学友"; var age = 40; return [ function getName() { return name; }, function getAge() { return age; } ] } var foo = func(); console.log(foo[0]()); //张学友 console.log(foo[1]()); //40
说明:上面的代码可以知足返回多个变量值的需求,可是要数组操做的方式并不常见,且和使用习惯不符合。函数
利用对象返回并设置对个变量值spa
function foo() { var name = "张学友"; var age = 45; return { getName:function () { return name; }, getAge:function () { return age; }, setName:function (nameValue) { name = nameValue; }, setAge:function (ageValue) { age = ageValue; } } } var func = foo(); console.log(func.getName()); //张学友 console.log(func.getAge()); //45 func.setName("张三"); func.setAge(30); console.log(func.getName()); //张三 console.log(func.getAge()); //30
1、在函数中使用var
操做符定义一个变量,那么当这个函数执行完毕以后,这个变量也会被销毁(也有的状况下不会,好比闭包,后面会说明),而全局变量会一直存在。因此在咱们写代码时,尽可能少的使用全局变量,滥用全局变量,简直就是一个会使人恶心的习惯,由于它会带来不少没必要要的麻烦。线程
有两个网址都是第一个解释做用域和闭包,第二个解释闭包,做用域链,和垃圾回收机制
***************************************************************************
进程指的是系统中正在运行的一个应用程序。
线程:一个进程中能够有一个或多个线程,线程是CPU调度的最小单位,是真正执行任务的。
多线程:一个中可能有多条线程,多条线程之间并发的执行多个不一样的任务。
单线程:一个进程中只有一条线程,即同一时间只能执行一个操做,只能干一件事情。
javascript是单线程的:
js中的线程主要处理三块任务:(由上到下优先级处理)
01 渲染任务
02 js的代码执行任务
03 js中的事件处理任务(如setTimeOut方法)
一、DOM操做
//函数定义和调用一块儿使用, //形式:(function sum(){})(),简化成(函数的定义)(函数的调用); var btns = document.getElementsByTagName('button'); //遍历按钮 for(var i= 0;i < btns.length;i++){ // btns[i].onclick = (function (a) { // alert(a); // })(i) (function (a) { btns[a].onclick = function () { alert(a); } })(i) ; }
当点击按钮的时候,须要输出i值,那么这个函数首先回会去寻找本身函数内部有没有对应的i值,若是有就直接访问这个i值,若是没有就要沿着闭包链式做用域去他的父对象中寻找对应变量i, 因此会去for循环中寻找i值,可是注意函数执行实在按钮点击的时候才触发,按钮点击是一个延迟操做,当按钮点击的时候for中的i值执行已经完毕,并且值是循环长度,因此咱们获取的值5;(注释部分)
经过闭包每一次循环都会保存i值,在弹出i值所在的函数中放置一个变量,那么就能够实现输出0-4;
*************************************************************************************************
二、定时器中闭包的使用
for(var i = 0; i < 4; ++i){ // (function(a){ // setInterval(function(){ // console.log(a); // },0) // })(i) setInterval((function (a) { console.log(a) })(i),0); }
注释部分是出现无序的数字,而且定时器没有中止,反之第二种写法能够得到想要效果
其余:函数名函数只能函数体内调用:
var a = function b(){ console.log(1); }; a(); //1 b(); //not defined (只能在局部使用,相似闭包)
var a = function b(){ console.log(1); console.log(b); }(); // 1 function b(){...}