javascript基础知识:闭包(closure)

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了javascript基础知识:闭包(closure)相关的知识,希望对你有一定的参考价值。


(1)
javascript的变量特点:函数内部可以直接读取全局变量,但是在函数外部无法读取函数内部的局部变量。
在函数内部声明变量的时候,一定要使用var命令。如果不用的话,声明的是一个全局变量!

闭包就是有权访问另一个函数作用域内变量的函数
函数能够记住自己定义时所处的作用域的环境
闭包的用途:可以读取函数内部的变量,让这些变量的值始终保持在内存中,不会在调用后被自动清除。
使用闭包的注意事项:
正常的情况下函数调用结束之后函数的执行环境离开环境栈,定义的变量会被垃圾回收机制回收,变量对象会被销毁,内存释放。但是因为闭包的作用,函数的变量有可能再被引用,垃圾收集机制不会将变量废弃,在内存中保留的相应的变量对象。这样就加大了对内存的占用。造成网页的性能问题。解决方法,在退出函数之前,将不使用的局部变量删除。

eg:
function myfuntion(){
  var n=1;
}
alert(n);
//Uncaught ReferenceError: n is not defined(…)
在函数外部,无法读取函数内部的局部变量
funtion outer(){
  var a=1;
  function inner(){
    console.log(a);
  }
  return inner;
}
var innerFunction=outer();
innerFunction();// 1
//函数内部,在定义一个函数。里面可以访问a,outer执行的时候将inner,作为返回值。
//innerFunction(),执行就是inner执行。
eg:
var inner;
function outer(){
  var a = 1;
  var b = 2;
  inner = function(){
    console.log(a);
    console.log(b);
  }
}
outer(); //执行的时候 内部函数赋值给全局的inner
var a = 2;
var b = 3;
inner(); //调用的时候。先去找自己定义时候的作用域 a=1;b=2
console.log(a);
console.log(b);
//1
//2
//2
//3
eg:
function outer(x){
  function inner(y){
    console.log(x + y);
  }
  return inner;
}
var innerFunction = outer(1); //x是1
innerFunction(2); //3 y是2
innerFunction(3); //4 y是3
innerFunction(4); //5 y是4
innerFunction(5); //6 y是5
(2) 重新引用函数的时候闭包是全新的闭包
通过return返回的每一个闭包内的活动对象都是独立的
innerFunction1、innerFunction2中的变量count是独立的,存储在各自的作用域里,互不干涉
function outer(){
  var count = 0;
  function inner(){
    count++;
    console.log(count);
  }
  return inner;
}
var innerFunction1 = outer();
var innerFunction2 = outer();
innerFunction1();
innerFunction1();
innerFunction2();
innerFunction2();
innerFunction1();
innerFunction1();
//1
//2
//1
//2
//3
//4
(3)闭包中this值
函数中this指向调用该函数的对象,若无明确调用对象则指向window对象。
var name="xiao A";
var obj={
  name:"xiao B",
  getName:function(){
    return function(){
      return this.name;
    }
  }
}
alert(obj.getName()());
//xiao A
//obj.getName()执行的时候返回的是一个函数(匿名函数)
//function(){
// return this.name;
//}
//var k=obj.getName()=function(){
// return this.name;
// };
//全局作用域。()执行的话。 this是window
(4)
var name="xiao A";
var obj={
  name:"xiao B",
  getName:function(){
    var o=this;
    return function(){
      return o.name;
    }
  }
}
alert(obj.getName()());
//xiao B
//obj.getName()执行的时候返回的是一个函数(匿名函数)
//function(){
// return o.name;
//}
//var k=obj.getName()=function(){
// return o.name;
// };
//()执行的话。 o就是this是obj
(5):
var name = ‘global‘;
var obj = {
  name : ‘obj‘,
  dose : function(){
    this.name = ‘dose‘;
    return function(){
      return this.name;
    }
  }
}
alert(obj.dose().call(this))
//obj.dose().call(this) call(this)相当于将函数运行环境中的this对象替换成window
//window.name
//‘global‘
(6)
function f(x){
  var temp=x; //局部变量
  return function(x){
    temp+=x;
    alert(temp);
  }
}
var a=f(50);
//a即function(x){
// temp+=x;
// alert(temp);
// }
a(5); //55
a(10); //65
a(20); //85
(7)
function fun(n,o) {
  console.log(o)
  return {
    fun:function(m){
      return fun(m,n);
    }
  };
}
var a = fun(0); a.fun(1); a.fun(2); a.fun(3);
var b = fun(0).fun(1).fun(2).fun(3);
var c = fun(0).fun(1); c.fun(2); c.fun(3);
//undefined 开始的时候fun(0); 没传值,所以o是undefined
//0 n=0;a.fun(1);m=1;fun(m,n); fun(1,0);
//0 同上
//0 同上
//undefined fun(0); 没传值,所以o是undefined n=0
//0 fun(0).fun(1); m=1;fun(m,n);fun(1,0); n=1;
//1 fun(0).fun(1).fun(2); m=2; fun(m,n);fun(2,1); n=2;
//2 同上
//undefined 开始的时候fun(0); 没传值,所以o是undefined
//0 fun(0).fun(1); m=1;fun(m,n);fun(1,0); n=1;
//1 c.fun(2); m=2;n=1;fun(m,n);fun(2,1);
//1 c.fun(3); m=3;n=1;fun(m,n);fun(3,1);
(8)
//for循环执行完后。result被垃圾回收,但是i不会。还有用处
//i = 10;
//funcs = result;
//result = null;
function myfuntion(){
  var result = new Array();
  for (var i=0; i < 10; i++){
    result[i] = function(){
      return i;
    };
  }
  return result;
}
var funcs = myfuntion();
for (var i=0; i < funcs.length; i++){
  console.log(funcs[i]());
}
//输出的是10个10
//函数带()才是执行函数
//result[0] = function(){ return i; };
//...
//result[9] = function(){ return i; }; //没执行函数,函数内部不变i!
//函数内部for循环完了之后i = 10;
//funcs[0]() return i;
(9)解决内存问题
function example(){
  var ele=document.getElementByID("someElement");
  ele.onclick = function() {
    alert("This is a leak!");
  }
  ele= null; //变量设置为null
}
//ele.id 的一个副本保存在一个变量中
function example(){
  var ele= document.getElementById("someElement");
  var id = ele.id;
  ele.onclick = function(){
    alert(id);
  };
  ele = null;
}

垃圾回收机制回收





























































































































































































































以上是关于javascript基础知识:闭包(closure)的主要内容,如果未能解决你的问题,请参考以下文章

学习Javascript闭包(Closure)

深入理解JavaScript闭包(Closure)

JavaScript 初识闭包closure及总结

关于Javascript闭包(Closure)

学习Javascript闭包(Closure)

学习Javascript闭包(Closure)