您的位置:首页 > Web前端 > JavaScript

3 javascript闭包学习总结

2017-05-09 18:35 267 查看

闭包几个思想

javascript中有两种作用域,全局和局部,由于局部作用域的存在导致外部无法访问函数内部变量,从而出现了闭包思想。闭包的关键是作为沟通函数内外部的数据桥梁。

//一个实现
function closure() {
var innerVar = 0;
function inner() {
return  ++innerVar;//可以直接修改innervar的值
}
return inner;
}
var quote = closure();
echo(pclosure1, quote());//1
echo(pclosure1, quote());//2


js是函数作用域的,即一个function就是一个局部作用域,innerVar在函数作用域里面。但是希望能操作该内部变量。 那么其内部的函数就可以访问并修改这个局部变量。所以在第二次调用时,第一次调用的结果仍然保存着。

2:闭包中涉及的静态与动态作用于思想

var name = "xiaofu";
var person = function(lastname){
var name = 'yang';

function personName(){
return name + lastname;
}
return personName;
}
var pName = person();
pName("xiaoming");


js 中一个function就是一个作用域,所以personName在person这个函数的作用域里面。但是调用的是在这个作用域的外面,那么当personName执行的时候,它里面的name取的是person这个作用域还是最外层的作用域呢?

如果是静态作用域则调用的是person里面的 name, 如果是动态作用域则调用的是外层的name(“xiaofu”);而不是”yang”。

闭包就是用来实现静态作用域的一种方式,即通过闭包将函数和它声明时的作用域保存下来,这样在调用的时候取到的就是声明时所在作用域 而不是调用时的作用域。

this

this则与变量有点不同,即this采用的是类似于动态作用域的情况。js里面一切都是对象,所以函数也都是某个对象的方法,如果没有显示指定则是全局对象window。

var person = {
fullname: function{
console.log(this);
},
printAge: function(){
console.log(this);
}
}
person.fullname();      //this指向person
var age = person.printAge;
age();                  //this指向window(浏览器中)


将person.printAge赋值给age之后,再执行age(),此时age没有显示指定调用对象则默认是window(浏览器环境)。所以this并不是声明所在的环境。

3箭头函数(es6)

es6中新增了箭头函数,箭头函数与通过function声明的函数不同,它的this是使用的声明时上下文中的this.并且不可通过apply, call等改变所以在使用箭头函数时一定要注意this指向问题。

4 闭包的应用—立即执行函数

1:关键立即执行函数本身即是一个闭包

2:闭包可以操作所在函数中的变量(利用这点锁住每次循环的变量值到内存中)

有个网友问了个问题,如下的html,为什么每次输出都是5,而不是点击每个p,就alert出对应的1,2,3,4,5。

<html >
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>闭包演示</title>
<script type="text/javascript">

function init() {
var pAry = document.getElementsByTagName("p");
for( var i=0; i<pAry.length; i++ ) {
pAry[i].onclick = function() {
alert(i);
}
}
}
</script>
</head>
<body onload="init();">
<p>产品一</p>
<p>产品二</p>
<p>产品三</p>
<p>产品四</p>
<p>产品五</p>
</body>
</html>


使用闭包可以解决异步加载问题:,

方法1、将变量 i 保存给在每个段落对象(p)上

“`

function init() {

var pAry = document.getElementsByTagName(“p”);

for( var i=0; i

**方法2、将变量 i 保存在匿名函数自身**
```
function init2() {
var pAry = document.getElementsByTagName("p");
for( var i=0; i<pAry.length; i++ ) {
(pAry[i].onclick = function() {
alert(arguments.callee.i);
}).i = i;
}
}


方法3、加一层闭包,i以函数参数形式传递给内层函数

function init3() {
var pAry = document.getElementsByTagName("p");
for( var i=0; i<pAry.length; i++ ) {
(function(arg){
pAry[i].onclick = function() {
alert(arg);
};
})(i);//调用时参数
}
}


方法4、加一层闭包,i以局部变量形式传递给内存函数

function init4() {
var pAry = document.getElementsByTagName("p");
for( var i=0; i<pAry.length; i++ ) {
(function () {
var temp = i;//调用时局部变量
pAry[i].onclick = function() {
alert(temp);
}
})();
}
}


方法5、加一层闭包,返回一个函数作为响应事件(注意与3的细微区别)

function init5() {
var pAry = document.getElementsByTagName("p");
for( var i=0; i<pAry.length; i++ ) {
pAry[i].onclick = function(arg) {
return function() {//返回一个函数
alert(arg);
}
}(i);
}
}


方法6、用Function实现,实际上每产生一个函数实例就会产生一个闭包

function init6() {
var pAry = document.getElementsByTagName("p");
for( var i=0; i<pAry.length; i++ ) {
pAry[i].onclick = new Function("alert(" + i + ");");//new一次就产生一个函数实例
}
}


方法7、用Function实现,注意与6的区别

function init7() {
var pAry = document.getElementsByTagName("p");
for( var i=0; i<pAry.length; i++ ) {
pAry[i].onclick = Function('alert('+i+')')
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  javascript 函数 闭包