js闭包
需求:点击某个按钮,提示点击的是第n个按钮
var btns=document.getElementsByTagName('button'); for(var i=0;i<btns.length;i++){ var btn=btns[i]; btn.onclick=function () { alert('点击'+(i+1)+'个'); } }
运行上面的代码,i始终是btns.length+1
改进:
var btns=document.getElementsByTagName('button'); for(var i=0;i<btns.length;i++){ (function (i) { var btn=btns[i]; btn.onclick=function () { alert('点击'+(i+1)+'个'); } })(i); }
如何产生闭包:
当一个嵌套的内部(子)函数引用了嵌套的外部(父)函数的变量(函数)时,就产生了闭包.
使用chrome调试查看
理解一:闭包是嵌套的内部函数
理解二:包含被引用变量(函数)的对象
注意:闭包存在于嵌套的内部函数中
常见的闭包使用形式:
1.将函数作为另一个函数的返回值
function fn1() { var num=10; function fn2(){ num++; console.log(num); } return fn2; } var f=fn1(); f();//11
f();//12
2.将函数的形参作为实参传递给另一个函数调用.
//大的函数中包含小的函数,小函数中引入了大函数的变量,就形成了闭包 function logMsgDelay(msg,time) { setTimeout(function () { console.log(msg); },time); } logMsgDelay('老石',1000);
function myTool(){ var money=1000; //提供操作私有函数的操作 function get(){ money*=10; console.log('总资产:'+money+'元'); } function send(){ money--; console.log('花了一笔钱,总资产:'+money+'元'); } return { 'get':get, 'send':send }; }
调用:
<script type="text/javascript" src="s/myTool.js"></script> <script> var toolObj= myTool(); toolObj.get(); </script>
另一种写法:
(function(w){ var money=1000; function get(){ money*=10; console.log('总资产:'+money+'元'); }; function send(){ money--; console.log('花了一笔钱,总资产:'+money+'元'); } w.myTool={ 'get':get, 'send':send } })(window)
myTool.get(); myTool.send();
高级排他:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <style> li{ border:1px solid #000; background-color: #ccc; cursor: pointer; } .current{ background-color: orangered;; } </style> </head> <body> <ul> <li class="current"></li> <li></li> <li></li> <li></li> <li></li> <li></li> </ul> <script> window.onload = function () { var allLis = document.getElementsByTagName('li'); for(var i=0; i<allLis.length; i++){ var li = allLis[i]; li.onmouseover = function () { for(var j=0; j<allLis.length; j++){ allLis[j].className = ''; } this.className = 'current'; } } } window.onload = function () { var allLis = document.getElementsByTagName('li'); // 记录移动前选中li对应的索引 var preSelectLiIndex = 0; for(var i=0; i<allLis.length; i++){ (function (i) { var li = allLis[i]; li.onmouseover = function () { // 清除 allLis[preSelectLiIndex].className = ''; // 设置 this.className = 'current'; // 赋值 preSelectLiIndex = i; } })(i); } } </script> </body>
实现函数节流:
var timer = null; window.onresize = function () { clearTimeout(timer); timer = setTimeout(function () { console.log('输出的内容!!!!'); }, 200); }
内存泄露:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>02_内存溢出与内存泄露</title> </head> <body> <!-- 1. 内存溢出 一种程序运行出现的错误 当程序运行需要的内存超过了剩余的内存时, 就抛出内存溢出的错误 2. 内存泄露 占用的内存没有及时释放 内存泄露积累多了就容易导致内存溢出 常见的内存泄露: 1. 占用内存很大的全局变量 2. 没有及时清理的计时器/定时器 3. 闭包 --> <script type="text/javascript"> // 1. 内存溢出 /* var arrObj = {}; for(var i=0; i<100000000; i++){ arrObj[i] = new Array(999999); console.log(arrObj); }*/ // 2. 常见的内存泄露 // 占用内存很大的全局变量 /* var num = new Array(99999999); var num1 = new Array(99999999); var num2 = new Array(99999999); var num3 = new Array(99999999); var num4 = new Array(99999999); var num5 = new Array(99999999); var num6 = new Array(99999999); var num7 = new Array(99999999); num = null;*/ // 没有及时清理的计时器/定时器 /* var intervalId = setInterval(function () { console.log("-----"); }, 1000); clearInterval(intervalId);*/ // 闭包 function fn1() { var num = 1111; function fn2() { num--; console.log(num); } return fn2; } var f = fn1(); f(); f = null; </script> </body> </html>
构造函数设置属性和方法
<script type="text/html"> // 注意: 以下的属性和方法, 都是绑定在使用构造函数创建出来的对象p上; 最终使用的时候也是使用对象p来进行访问; // 我们把这种类型的属性和方法, 称为 实例属性/实例方法 function Person(name, age, doFunc) { this.name = name; this.age = age; this.doFunc = doFunc; } var p1 = new Person('sz', 18, function () { console.log('sz在上课'); }); var p2 = new Person('王二小', 18, function () { console.log('王二小在放羊'); }); console.log(p1.name); console.log(p1.age); p1.doFunc(); console.log(p2.name); console.log(p2.age); p2.doFunc(); </script>
// 静态属性, 静态方法
// 绑定在函数身上, 一定要注意: 函数本质也是一个对象, 既然是个对象, 那么就可以动态的添加属性和方法
// 只要函数存在, 那么绑定在它身上的属性和方法, 也会一直存在
// 想要记录总共创建了多少个人?
function Person(name, age, doFunc) { this.name = name; this.age = age; this.doFunc = doFunc; if (!Person.personCount) { Person.personCount = 0; } Person.personCount++; } Person.printPersonCount = function () { console.log('总共创建了'+ Person.personCount + '个人'); }; var p1 = new Person('sz', 18, function () { console.log('sz在上课'); }); var p2 = new Person('王二小', 18, function () { console.log('王二小在放羊'); }); console.log(p1.name); console.log(p1.age); p1.doFunc(); console.log(p2.name); console.log(p2.age); p2.doFunc(); Person.printPersonCount();