【JS学习笔记】 匿名函数和闭包

时间:2022-01-25 19:17:01

晓石头的博客
邮箱:178673693@qq.com
转载请注明出处,原文链接:http://blog.csdn.net/qiulanzhu/article/details/50612274


index.html:

<!DOCTYPE HEML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=gb2312"/>
<title>使用JS</title>

</head>
<body>
<div id="oDiv">Lee</div>
</body>


</html>
<script type="text/javascript" src="demo.js"></script>


demo.js

/*=============================匿名函数和闭包============================*/
//普通函数
function box(){
return "qiu";
};

//匿名函数
//把匿名函数赋值给变量
var fun1 = function (){
return "yi";
};

document.write(fun1() +"<br>");//这里有括号

//通过表达式自我执行
(function(){
document.write("qiuyi<br>");
})();

//把匿名函数执行结果赋值给变量
var fun2 = (function(){
return "qiuyi";
})();

document.write(fun2 +"<br>");//这里没有括号

//直接打印匿名函数的运行结果
document.write( (function(){
return "direct printf<br>";
})() );

// 匿名函数传参运行
(function(age){
document.write(age +"<br>");
})(27);

//函数里放一个匿名函数
function desk(){
return function(){//闭包
return "qiuqiu";
}
}

document.write(desk + "<br>");
document.write(desk() + "<br>");
document.write(desk()() + "<br>");

/*==========================闭包===========================*/
//闭包的含义:闭包说白了就是函数的嵌套,内层的函数可以使用外层函数的所有变量,即使外层函数已经执行完毕(这点涉及JavaScript作用域链)。
//闭包是指有权访问另一个函数作用域的变量的函数。
//创建闭包的常见方式:一个函数内创建另外一个函数

//通过闭包返回局部变量
function flower(){
var age = 100;

return function(){
return age;
}
}

document.write(flower()());

//闭包实现累加,让局部变量驻留内存中

function add(){
var num = 100;
return function(){
return ++num;
}
}

var myadd = add();
document.write( myadd() +"<br>");
document.write( myadd() +"<br>");
document.write( myadd() +"<br>"); //实现局部变量的累加
myadd = null;//结束引用,等待垃圾回收

//循环里,匿名函数的取值问题
function loop(){
var arr = [];

for(var i=0; i<5; i++){
arr[i] = function(){
return i;
}
}

return arr;
}

document.write(loop() + "<br>");
document.write(loop()[0] +"<br>");
document.write(loop()[0]() + "<br>");

//实现匿名函数里返回0,1,2,3,4,5
//改版1
function loop1(){
var arr = [];

for(var i=0; i<5; i++){
arr[i] = (function(i){//通过及时执行匿名函数,()():能够实现及时执行。在赋给一个变量时,可以不用前一个()。
return i;
})(i)
}

return arr;
}

for(var i=0; i<5; i++){
document.write(loop1()[i]);
}
document.write("<br>");

//改版2
function loop2(){
var arr = [];

for(var i=0; i<5; i++){
arr[i] = (function(num){//num为传入的参数,等于i;
return function(){
return num;
}
})(i)
}
return arr;
}

for(var i=0; i<5; i++){
document.write(loop2()[i]());
}
document.write("<br>");



/*============================this对象==============================*/
//全局:this指window
//对象内部:this指这个对象
//闭包:this指window,因为闭包不属于这个函数的属性或者方法。

//全局
document.write(this +"<br>");

//对象内部
var testThis = {
getThis : function(){
return this;
}
}
document.write(testThis.getThis() +"<br>");

//闭包
var testThis1 = {
getThis : function(){
return function(){
return this;
}
}
}
document.write(testThis1.getThis()() +"<br>");

var usr = "this window";

var bibao = {
usr : "this inner",

run : function(){
return function(){
return this.usr;//返回this window
}
}
}

document.write(bibao.run()() +"<br>");

//让闭包里的this 指向对象
//方法一:对象冒充
document.write(bibao.run().call(bibao) +"<br>");

//方法二:变量替换
var usrs = "window";
var bibao2 = {
usrs : "inner",
run : function(){
var that = this;
return function(){
return that.usrs;
}
}
}

document.write(bibao2.run()() +"<br>");


/*============================内存泄漏===============================*/
//内存泄漏:对象引用没有办法释放掉
function leak(){
var oDiv = document.getElementById("oDiv");
oDiv.onclick = function(){
alert(oDiv.innerHTML);//IE会存在内存泄漏
}
}
//leak();

//修改
function leak1(){
var oDiv = document.getElementById("oDiv");
var tmp = oDiv.innerHTML;
oDiv.onclick = function(){
alert(tmp);
}
oDiv = null;//解除应用,等待垃圾回收
}
leak1();

/*==========================模拟块级作用域==============================*/
//JS没有真实的块级作用域
function testi(){
for(var i=0; i<5; i++){
document.write(i);
}
document.write("<br>" +i+"<br>"); //i依然能够访问到,证实了JS没有块级作用域
}
testi();


//匿名函数模拟块级作用域
//匿名函数中定义的任何变量,都在执行结束后被销毁
//减少闭包占用内存问题
function testi2(){
(function(){
for(var j=0; j<5; j++){
document.write(j);
}
})()

//document.write(j);//j不可见
}

testi2();

//私有数据
//get和set
function Night(){
var age = 100;//私有变量
function run(){//私有函数
return "运行中...";
}

this.getAll = function(){
return age + run();
}

this.setAge = function(num){
age = num;
}
}

var night = new Night();
night.setAge(200);
document.write(night.getAll());


//静态私有变量
//实现私有数据共享
(function(){
var age = 100;
Qiu = function(iage){//全局的构造函数,外部能够访问
age = iage;
}

Qiu.prototype.getAge = function(){
return age;
}
})()

var age1 = new Qiu(27);
document.write(age1.getAge());
var age2 = new Qiu(28);
document.write(age1.getAge());//age1中的age也发生了变换

/*==============================模块模式=============================*/
//之前都是用构造函数的方式来创建私有变量和特权方法。
//对象字面量方式就采用模块模式来创建。
//字面量被看作一种单例模式,永远保持一个对象实例
var phone = (function(){
var age = 100;
function run(){
return "运行中..";
}

var obj = {
getAll : function(){
return age + run();
}
}
return obj;
})()
document.write(phone.getAll());

//增强型的模块模式,这种模式适合返回自定义对象,也就是构造函数
function Pen(){};

var pen = (function(){
var age= 100;
function run(){
return "运行中..."
}

var myPen = new Pen();
myPen.getAge = function(){
return age;
}

return myPen;
})()

document.write(pen.getAge());