需求:点击某个按钮,提示点击的是第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();