闭包与this学习

最近刚好又遇到闭包知识,之前一直没弄懂,不过时间一久,慢慢就明白了。

正如很多大牛博客上说的,闭包就是能够读取其他函数内部变量的函数。

代码例子来自:阮一峰的网络日志---学习javascript闭包 也是我的参考资料

 function f1(){
    var n=999;
    nAdd=function(){n+=1}
    function f2(){
      alert(n);
    }
    return f2;
  }
  var result=f1();
  result(); // 999
  nAdd();
  result(); // 1000

由于在Javascript语言中,只有函数内部的子函数才能读取局部变量,因此可以把闭包简单理解成"定义在一个函数内部的函数"。所以,在本质上,闭包就是将函数内部和函数外部连接起来的一座桥梁。

它的最大用处有两个,一个是前面提到的可以读取函数内部的变量,另一个就是让这些变量的值始终保持在内存中。
 

 

博客最后抛出一个有关this的问题:

var name = "The Window";
  var object = {
    name : "My Object",
    getNameFunc : function(){
      var that = this;
      return function(){
        return that.name;
      };
    }
  };
  alert(object.getNameFunc()());

这里用了that来存储this。从而引起了我对this的关注。

于是乎google之下,见到又一大神博客:深入javascript之this关键字 

才明白this的指向,是根据调用其所在函数调用时的上下文所决定的,即普通function的主人是window,此时this会指向window,而function如果是在某个对象中时,this则指向此对象。

博客中用的例子是以onclick事件函数作为例子,这里我加了点修改。同时也解答了正确指向this的用法;

事件处理函数
            dom.onclick = funtionMethod;
            dom.onclick = function(){
                //use this;
            };
            <input onclick="alert(this);" />
非事件函数
            functionN.call(obj, arg1, arg2);
            functionN.apply(obj, args);
<html>
<head>
<title>
function execute methods
</title>
</head>
<body>
<input type='button' value="button1" id='btn1' />
<input type='button' value="button2" id='btn2' />
<input type='button' value="button2.5" id='btn25' />
<input type='button' value="button3" id='btn3' onclick='buttonClicked();'/>
<input type='button' value="button4" id='btn4' onclick='alert(this.value);alert(this.onclick);'/>
<script type='text/javascript'>
function buttonClicked(){
    alert(this.value);
    alert(this.onclick);
} //函数A
var button1 = document.getElementById("btn1");
var button2 = document.getElementById("btn2");
var button25 = document.getElementById("btn25");
button1.onclick = buttonClicked; //赋值函数A到对象,所以此时函数属于对象
button2.onclick = function(){buttonClicked();}; //虽然是定义函数,但函数内是直接调用函数A,所以函数A是window的
button25.onclick = function(){alert(this.value);alert(this.onclick);}; // 定义函数,函数是input对象的。
// button3 的使用方式跟button2很像(还不确定)
// button4 引号内容就如button2.5
</script> </body> </html>

到了这里,本来一切都明了了。但又看了一下第一篇博客里面相关链接。

无标题文档---闭包的秘密

function Container(param) {
    var sercert = 3;
    this.member = param;
    var that    = this; // 注意这行

    function dec() {
        return (sercert > 0) ? --secret : false;
    }

    this.service = function() {
        return (dec()) ? that.member : null;
    }
}

差点给误导的感觉,可能我一下子先入为主了,以为这里的that是必要的。但其实这里that不需要用。因为service定义的函数是直接使用this,则this应当指向的是service的主人,即Container的实例。

我也写下例子:

<html>
<head></head>
<body onload='board();'>
<script type="text/javascript">
function Container0(param) {
    var sercert = 3;
    this.member = param;
    function dec() {
        return (sercert > 0) ? --sercert : false;
    }
    this.service = function() {
        return (dec()) ? this.member : null; //这里是直接定义函数,因此不需要var that保存
    }
}
function Container(param) {
    var sercert = 3;
    this.member = param;
    var that    = this; // 注意这行
    function dec() {
        return (sercert > 0) ? --sercert : false;
    }
    this.service = function() {
        return (dec()) ? that.member : null;
    }
}
var usage = function(){
    return this.member;
};
function Container2(param) {
    var sercert = 3;
    this.member = param;
    var that    = this; // 注意这行
    function dec() {
        return (sercert > 0) ? --sercert : false;
    }
    this.service = usage; //直接赋值法,usage会成为Container2的成员函数,this则指向本身
}
function Container3(param) {
    var sercert = 3;
    this.member = param;
    function dec() {
        return (sercert > 0) ? --sercert : false;
    }

    this.service = function() {
        return function(){ //函数体中返回的函数,属于外部函数,this指向windows
          //  return (dec()) ? this.member : null;  //--> undefined
            return this; //window not container3 object
        }
    }
}
function board(){
    var t = new Container(1);
    alert(t.service());
    var t2 = new Container2(2);
    alert(t2.service());
    var t0 = new Container0(3);
    alert(t0.service());
    var t3 = new Container3(4);
    alert(t3.service()());
}
</script>
</body>
</html>

一切都明朗了的感觉。

再重新回来看,发现表述太过浅,迟点记录一下作用域链以及this的特殊性

posted @ 2013-04-04 01:24  Dont  阅读(...)  评论(...编辑  收藏