JavaScript之闭包、定时器
来源:互联网 发布:战舰世界蒙大拿数据 编辑:程序博客网 时间:2024/06/06 07:36
谈谈闭包
对于JavaScript而言,虽然没有块作用域的概念,但是有函数作用域的概念,若是想从全局环境下去访问一个函数内的局部变量,是办不到的;但是根据JavaScript中的链式作用域的概念,它是可以访问外面的全局变量的,所以,针对一个被定义在函数内的函数,它的父函数中的所有变量也是能够被它访问到的。
什么是闭包
闭包(Closure)是让内部函数能够访问外部函数中的变量。
一个最简单的闭包栗子:function Closure{ var a = 1;// 在最父函数环境中定义了a return function(){ a = 2; // 给a赋值,但是在当前作用域中并没有声明a这个变量 }}func = Closure(); // 这时的返回值即是一个函数func() // 对里面的函数进行调用,这时a的值发生了改变
闭包的作用
闭包的作用就是让内部函数能够访问到外部变量,就像上面例子中所演示的样子。
闭包的另一个作用就是让一些变量始终保存在内存中,看下面:function func(){ var a = 1; function add(){ a++; } function ret(){ return a; } return { ret:ret, add:add }}var f1 = func();f1.add();f1.add();console.log(f1.ret());
在这个栗子中,函数中的子函数add一共运行了两次,将a的值从1改变到了3,由于父函数被赋给了一个全局变量,所以它就一直在内存中,而不是在调用之后被自动清除了。
使用闭包的注意点
上文中已经说过,闭包的特点之一,也是最主要的特点就是函数的所有变量都会被保存在内存中,那么这些变量当然也会占用内存,如果闭包使用过度甚至滥用,就会给内存造成很大的负担,可能会造成性能问题甚至造成内存泄漏,所以在使用完成闭包之后一定要手动去清除这块内存,避免内存问题的出现。setTimeout 0 有什么作用
但从字面上的意思来看,这样设置就是让函数延迟0s执行,但是其实不然,它的作用是让函数放到最后去执行,比如:
setTimeout(function(){console.log(1);},0); (function(){console.log(12);}());
以上两个函数的执行顺序并不是按照顺序上的先打印1,再打印12;由于给前面的函数设置了0s的延时,执行到此处的时候它就被放进了循环队列,遵循队列后进后出的原理,在执行完成其它代码后再对队列中的代码依次执行。下面代码的输出是什么,对其进行修改让fnArr()输出i,使用2种以上的方式
var fnArr = []; for (var i = 0; i < 10; i ++) { fnArr[i] = function(){ return i; }; } console.log( fnArr[3]() ); // 10
修改1:
var fnArr = []; for (var i = 0; i < 10; i ++) { fnArr[i] = function(){ return i; }(i); } console.log( fnArr[3] ); //
修改二:
for(var i=0;i<5;i++){ (function(){ var n = i; setTimeout(function(){ console.log('delayer:' + n ); }, 0); })(); console.log(i); }
使用闭包封装汽车对象,并获取状态
var Car = carSet(); function carSet(){ var speed = 0; function setSpeed(spe){ speed = spe; } function getSpeed(){ console.log(speed); return speed; } function accelerate(){ speed += 10; } function decelerate(){ speed -= 10; } function getStatus(){ if(speed === 0){ console.log("stop"); return "stop"; }else{ console.log("running"); return "running"; } } return{ setSpeed:setSpeed, getSpeed:getSpeed, decelerate:decelerate, getStatus:getStatus, accelerate:accelerate } } Car.setSpeed(30); Car.getSpeed(); //30 Car.accelerate(); Car.getSpeed(); //40; Car.decelerate(); Car.decelerate(); Car.getSpeed(); //20 Car.getStatus(); // 'running'; Car.decelerate(); Car.decelerate(); Car.getStatus(); //'stop'; //Car.speed; //error
使用setTimeot模拟setInterval的功能。
function getsec(){ setTimeout(function(){ console.log(new Date().getSeconds()); getsec(); },1000) }
计算setTimeout的最小时间粒度
function cTime(){ var i = 0; var sta = Date.now(); var clo = setTimeout(function a(){ i++; if(i === 1000){ var end = Date.now(); clearTimeout(clo); console.log((end - sta)/i); } clo = setTimeout(a,0); },0); } cTime();
下列代码的输出
// 由于被设置延时的函数会被移动到队列中,等待所有正常执行完成之后再进行执行,所以执行的实际顺序为:var a = 1;var a;console.log(a); // 1a = 3;console.log(a); // 3setTimeout(function(){ a = 2; console.log(a);},0)
以下代码的输出
var flag = true; setTimeout(function(){ // 设置延时后,这段代码被放进队列中,等待所有执行完成之后再执行 flag = false; },0) while(flag){} // 到这里的时候,判断flag一直会使true,无法往下执行,形成死循环 console.log(flag);
以上代码在模拟控制台上会输出true,但实际只是假象
使用闭包来让下面这段函数输出delayer: 0, delayer:1...
for(var i=0;i<5;i++){ (function(){ var n = i; setTimeout(function(){ console.log('delayer:' + n ); }, 0); })(); console.log(i);}
- JavaScript之闭包、定时器
- JavaScript之闭包、定时器
- javascript 之 闭包
- JavaScript之闭包
- JavaScript 之 闭包
- JavaScript之闭包
- javascript之闭包
- javascript之闭包
- javascript之闭包
- javascript之闭包
- JavaScript之闭包
- JavaScript之闭包
- JavaScript之闭包
- JavaScript之闭包
- Javascript之闭包
- JavaScript之闭包
- JavaScript之闭包
- JavaScript之闭包
- 一句代码实现银行卡手机号输入时格式化
- js点击标题展示内容,再次点击标题关闭内容
- 17年12月学习计划
- Git 命令行
- 关于rem布局的理解
- JavaScript之闭包、定时器
- IDEA的springboot项目maven打包的时候过滤掉单元测试
- nginx性能优化
- 简单方法实现Form 无刷新提交表单
- jQuery中each的用法之退出循环和结束本次循环
- maven 的常用命令
- ORA-00845: MEMORY_TARGET not supported on thi s system导致rac安装失败
- 微信获取地理位置接口
- 机器学习专业英语单词