JavaScript中闭包的使用
2017-03-09 16:33
155 查看
闭包属于JavaScript中的一个难点,要想理解闭包,要先来了解一下JavaScript中的一个的局部变量与全局变量,也就是JavaScript的作用域。
1.在JavaScript函数的内部可以读取函数之外的全局变量
2.而在函数的外部是无法获取到函数内的局部变量
在上面的例子中如果定义的变量没有使用var来进行定义,而是直接num = 1; 这样定义的话,这个变量就是全局变量,在函数外面也是可以访问的
3.那么对于函数内部的局部变量如果外面想要获取到,这时又该怎么做?这时可以在函数的内部再定义一个函数
这样把f1内部的局部变量作为函数的返回值就可以访问内部的变量了,所以闭包是指有权访问另一个函数作用域中的变量的函数,创建闭包常见的方式,就是在一个函数的内部创建另一个函数,通过另一个函数访问这个函数的局部变量。
4.当然,使用闭包有一个优点,同时也是他的缺点,就是可以把局部变量驻留在内存中,可以避免使用全局变量(全局变量污染导致应用程序不可预测性,每个模块都可以调用必将引来灾难,所以推荐使用私有的,封装的局部变量)。
使用全局变量实现累加
使用闭包实现局部变量驻留内存中从而累加
6.闭包中的this对象
在闭包中使用this对象也有可能会造成一些问题,this对象是在运行时基于函数的执行环境绑定的,如果this在全局范围就是window,如果在对象内部就指向这个对象。而闭包却在运行时指向window的,因为闭包并不属于这个对象的属性或方法
如果使用了闭包的话
var user = "The Window"
var userObj = {
user : "The userObj",
getUser:function(){
return function(){
return this.user;
}
}
}
alert(user); //"The Window"
alert(userObj.getUser()()); //"The Window"
//可以看出使用闭包这时对象指向了window,如果想要指向userObj
//1)使用对象冒充
alert(userObj.getUser().call(userObj));
//2)
var user = "The Window"
var userObj = {
user : "The userObj",
getUser:function(){
//这里作用域的this是userObj
var that = this; //这样的话that指向userObj
return function(){
//这里作用域的this是window
return that.user;
}
}
}
alert(user); //"The Window"
alert(userObj.getUser()()); //"The userObj"
由于闭包会使得函数中的变量都被保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题,比如在IE中的JavaScript对象和DOM对象使用不同垃圾收集方式,因此闭包在IE中可能导致内存泄露,也就是无法销毁驻留在内存中的元素。解决方法是,在退出函数之前,将不使用的局部变量全部删除
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
</head>
<body>
<div id="div1">点击</div>
<script>
function fun(){
var oDiv=document.getElementById("div1"); // 1
// oDiv.onclick = function(){ //这里引用了1
// alert(oDiv.innerHTML); //这里用oDiv又引用了上面的1,所以会导致内存泄漏,
// }
//这样的话在oDiv在被null时保存了它的内容
var text = oDiv.innerHTML;
oDiv.onclick = function(){
alert(text);
}
oDiv=null; //解除引用,等待垃圾回收
alert(oDiv);
}
fun();
</script>
</body>
</html>
1.在JavaScript函数的内部可以读取函数之外的全局变量
var num = 1; function f1(){ alert(num); } f1();
2.而在函数的外部是无法获取到函数内的局部变量
function f1(){ var num = 1; } alert(num); //这里会报错
在上面的例子中如果定义的变量没有使用var来进行定义,而是直接num = 1; 这样定义的话,这个变量就是全局变量,在函数外面也是可以访问的
3.那么对于函数内部的局部变量如果外面想要获取到,这时又该怎么做?这时可以在函数的内部再定义一个函数
function f1(){ var num =1; return function(){ return num; }; } alert(f1()()); //注意这里使用的是f1()(),而不是f1(),f1()返回的是function(){return num;}; 只有()才是执行操作 //返回1
这样把f1内部的局部变量作为函数的返回值就可以访问内部的变量了,所以闭包是指有权访问另一个函数作用域中的变量的函数,创建闭包常见的方式,就是在一个函数的内部创建另一个函数,通过另一个函数访问这个函数的局部变量。
4.当然,使用闭包有一个优点,同时也是他的缺点,就是可以把局部变量驻留在内存中,可以避免使用全局变量(全局变量污染导致应用程序不可预测性,每个模块都可以调用必将引来灾难,所以推荐使用私有的,封装的局部变量)。
使用全局变量实现累加
var num = 100; function f1(){ num++; } alert(num); // 100 f1(); alert(num); // 101
使用闭包实现局部变量驻留内存中从而累加
function f1(){ var num = 100; function f2(){ return num++; } return f2; } var f = f1(); alert(f()); // 100 alert(f()); // 101 f = null; //接触引用,等待垃圾回收
6.闭包中的this对象
在闭包中使用this对象也有可能会造成一些问题,this对象是在运行时基于函数的执行环境绑定的,如果this在全局范围就是window,如果在对象内部就指向这个对象。而闭包却在运行时指向window的,因为闭包并不属于这个对象的属性或方法
var user = "The Window" var userObj = { user : "The userObj", getUser:function(){ return this.user; } } alert(user); //"The Window" alert(userObj.getUser()); //"The UserObj"
如果使用了闭包的话
var user = "The Window"
var userObj = {
user : "The userObj",
getUser:function(){
return function(){
return this.user;
}
}
}
alert(user); //"The Window"
alert(userObj.getUser()()); //"The Window"
//可以看出使用闭包这时对象指向了window,如果想要指向userObj
//1)使用对象冒充
alert(userObj.getUser().call(userObj));
//2)
var user = "The Window"
var userObj = {
user : "The userObj",
getUser:function(){
//这里作用域的this是userObj
var that = this; //这样的话that指向userObj
return function(){
//这里作用域的this是window
return that.user;
}
}
}
alert(user); //"The Window"
alert(userObj.getUser()()); //"The userObj"
由于闭包会使得函数中的变量都被保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题,比如在IE中的JavaScript对象和DOM对象使用不同垃圾收集方式,因此闭包在IE中可能导致内存泄露,也就是无法销毁驻留在内存中的元素。解决方法是,在退出函数之前,将不使用的局部变量全部删除
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
</head>
<body>
<div id="div1">点击</div>
<script>
function fun(){
var oDiv=document.getElementById("div1"); // 1
// oDiv.onclick = function(){ //这里引用了1
// alert(oDiv.innerHTML); //这里用oDiv又引用了上面的1,所以会导致内存泄漏,
// }
//这样的话在oDiv在被null时保存了它的内容
var text = oDiv.innerHTML;
oDiv.onclick = function(){
alert(text);
}
oDiv=null; //解除引用,等待垃圾回收
alert(oDiv);
}
fun();
</script>
</body>
</html>
相关文章推荐
- javascript中闭包的使用
- javascript中闭包的使用
- Effective JavaScript Item 35 使用闭包来保存私有数据
- Effective JavaScript Item 35 使用闭包来保存私有数据
- javascript使用闭包模拟私有属性和方法
- 文盲的 JavaScript 经验谈之四:在 JS 中使用闭包
- JavaScript使用闭包编写累加函数
- Effective JavaScript Item 27 使用闭包而不是字符串来封装代码
- Javascript的setTimeout()使用闭包特性时需要注意的问题
- [Effective JavaScript 笔记]第27条:使用闭包而不是字符串来封装代码
- javascript中闭包的使用
- JavaScript 闭包的使用
- javascript中闭包的使用
- 每天一个JavaScript实例-使用带有定时器的函数闭包
- javascript作用域和闭包使用详解
- javascript中闭包的使用
- javascript中闭包的使用
- javaScript的使用(4)闭包
- JavaScript setTimeout使用闭包功能实现定时打印数值
- [Effective JavaScript 笔记]第35条:使用闭包存储私有数据