那些年我们一起过的JS闭包,作用域,this,让我们一起划上完美的句号。

  之前有写过闭包,作用域,this方面的文章,但现在想想当时写的真是废话太多了,以至于绕来绕去的,让新手反而更难理解了,所以就有了此篇文章,也好和闭包,作用域,this告一段落。

 

第一个问题:什么是闭包?

我不想回答这个问题,但是我可以告诉你的是闭包可以解决函数外部无法访问函数内部变量的问题。下面是一段没有使用闭包的代码:

  function fn(){

    var a = 10;

  }

alert(a);

//报错了,因为a没有定义,虽然函数fn里面定义了a但是,但是它只能在函数fn中使用。也就是作用域的问题。

   再看‘闭包可以解决函数外部无法访问函数内部变量的问题’这段话,好像有点意思,那么究竟闭包是怎么做的,看下面代码。

  function fn(){

//定义了一个变量name

   var name = ‘追梦子‘;

//我现在想在外部访问这个变量name怎么办呢?哈:不是有return,我把它返回出去,我再用个变量接收一下不就可以了,哈哈哈哈~~~~~

return name;

}

var name = fn();//接收fn返回的name值。

alert(name);//追梦子;

原来·······所谓的闭包就是利用函数的return,但好像也没有那样神奇对吧?其实闭包还有一个很重要的特性。来看一个例子。

  var lis= document.getElementsByTagName[‘li‘];

  //假如这段代码中的lis.length = 5;

for(var i=0;i<lis.length;i++){

    lis[i].onclick = function(){

      alert(i);

    };

}

  最终结果是不管单击哪个li元素都是弹4。不信你试试。为什么呢。看下面分析。

    

  for(var i=0;i<lis.length;i++){

}

// i = 4对吧

  lis[0].onclick = function(){

    alert(i);

  };

  lis[1].onclick = function(){

    alert(i);

  };

  lis[2].onclick = function(){

    alert(i);

  };

  lis[3].onclick = function(){

    alert(i);

  };

  lis[4].onclick = function(){

    alert(i);

  };

为什么会这样呢,因为你for循环只是给li绑定事件,但是里面的函数代码并不会执行啊,这个执行是在你点击的时候才执行的好吧?但是此时的i已经是4了,所以所有的都打印出4来了。

  如果想解决这个问题我们可以使用闭包,闭包的特点不只是让函数外部访问函数内部变量这么简单,还有一个大的特点就是通过闭包我们可以让函数中的变量持久保持。来看。

  function fn(){

    var num = 0;

   return function(){

    num+=1;

alert(num);   

};  

}

var f = fn();

f(); //1

f(); //2

如果你是初学者可能没觉得这有什么。OK,让你看个东西。

  function fn(){

var num = 5;

num+=1;

alert(num);

}  

fn(); //6

fn(); //6

为什么呢?因为函数一旦调用里面的内容就会被销毁,下一次调用又是一个新的函数,和上一个调用的不相关了,不过有个特殊的情况,看这:

  

  function fn(){

    var num = 0;

   return function(){

    num+=1;

alert(num);   

};  

}

var f = fn();

f(); //1

f(); //2

这段代码很简单,不要被它欺骗了,我们首页定义了一个fn函数,里面有个num默认为0,接着返回了一个匿名函数(也就是没有名字的函数)。我们在外部用f接收这个返回的函数。这个匿名函数干的事情就是把num加1,还有我们用来调试的alert。

  这里之所以执行玩这个函数num没有被销毁是因为那个匿名函数的问题,因为这个匿名函数用到了这个num,所以没有被销毁,一直保持在内存中,因此我们f()时num可以一直加。

这里你可以看不懂了,之所以有这种感觉是因为js回收机制你不懂,强烈建议你看我之前的再次讲解js中的回收机制是怎么一回事。这篇文章。

关于闭包的知识就到这里了,如果你想看关于闭包的案例可以看这篇:从闭包案例中学习闭包的作用,会不会由你。

而外:关于在for循环中绑定事件打印变量i是最后一次。

 作用域竟然上面已经讲完了~~~

大前端 369451410欢迎你的加入。

那就说一下this:

  我们经常用this,但是也许你还不清楚它是什么吧?

lis[i].onclick=function(){this.style.border="1px solid #ccc";} ;

此时的this表示lis[?]它的引用。

这里的i不是i实际上是一个准确的数字:如lis[2].onclick = function(){this.style.border="1px solid #ccc";}; this = lis[2] ;

简单来说this它始终引用一个对象。

       lis[2]它也一个对象,是一个HTMLElement对象。

  其实不管什么情况下它都会有对象的,这个你不用操心,看

    function fn(){

     this.name = "追梦子";    

};    

fn();

alert(this.name);//追梦子

//当然也可以这样

    alert(name);

虽然这段代码中看似没有对象,但大错特错,因为浏览器环境中默认就有一个window对象,因此你在函数中直接用this.name实际上这个this就表示window。

  var json = {

    name:‘yyy‘,

    fn:function(){alert(this.name)} 

};

json.fn(); // yyy;

  fn属于json,所以this实际上就是json。

如果你是初学者建议你暂时先记住这三点,当然this还有很多要说的,不过做为初学者你可以在项目中通过console.log来检查this是否是你预期的那样。

更多关于this的内容,可以看彻底理解js中this的指向,不必硬背。

这篇文章并不算是一篇入门的教程,这篇文章主要是总结之前没有理解的地方,或者是以一种更加简单明了的方式写的,当然是按照我自己的理解来的,不一定你能理解,sorry,好了一切就从这里结束吧。

时间: 2024-10-17 22:37:32

那些年我们一起过的JS闭包,作用域,this,让我们一起划上完美的句号。的相关文章

简述JS的作用域和闭包

作用域:它是指对某一变量和方法具有访问权限的代码空间, 在JS中, 作用域是在函数中维护的.表示变量或函数起作用的区域,指代了它们在什么样的上下文中执行,亦即上下文执行环境.Javascript的作用域只有两种:全局作用域和本地作用域,本地作用域是按照函数来区分的. 闭包:在js中的我的理解就是函数嵌套函数,当内部函数在定义它的作用域的外部被引用时,就创建了该内部函数的闭包 ,如果内部函数引用了位于外部函数的变量,当外部函数调用完毕后,这些变量在内存不会被 释放,因为闭包需要它们. 作用域的嵌套

js:深入闭包(作用域)

/** * 闭包的作用域 */ fn1(); //fn1 能够执行,不会报错,对于通过function func_name()这种写法来定义的函数,永远都会被最先初始化. function fn1(){ console.log("fn1"); } fn2(); //报错:fn2 is not a function /** *使用如下方式定义函数,不会被先执行,如果在定义之前调用,报错. *这种函数的定义方式是先在内存中创建一块区域,之后通过一个fn2的变量指向这块区域, *这块区域的函

JS 之作用域链和闭包

1.JS无块级作用域 <script> function Main(){ if (1==1){ var name = "alex"; } console.log(name); } Main(); </script>执行结果:{}即块级作用域. alex 2.JS采用函数作为作用域链 <script> function Main(){ var innerValue = "alex"; } Main(); console.log(in

谈谈自己对js闭包,执行上下文,作用域链,活动对象AO,变量对象VO的理解

引子:关于闭包什么是闭包呢?  从定义上来看,所有的函数都可以是闭包.当一个函数在调用时,引用了不是自己作用域内定义的变量(通常称其为自由变量),则形成了闭包:闭包是代码块和创建该代码块的上下文中数据的结合. 例子:   function mytest( ){                                var test=10;          return function( ){                  test++;               alert(t

浅谈Js闭包现象

一.1.我们探究这个问题的时候如果按照正常的思维顺序,需要知道闭包是什么它是什么意思,但是这样做会让我们很困惑,了解这个问题我们需要知道它的来源,就是我们为什么要使用闭包,先不管它是什么意思!      2.我们使用闭包是因为js的作用域问题,前面我们已经对作用域了解了一些,在函数中,外部不能读取到内部的变量,而内部可以读取到外部的变量,这其实也是js特殊的一个地方!(这个特殊其实是因为函数的作用域是一条作用域链,而且作用域链是有顺序的,我们称之为链式作用域结构!)那么问题来了,如果我们想要从函

js闭包浅了解

js闭包浅理解 要理解闭包,得先知道js的变量作用域,在js中,有两种变量作用域: 全局作用域 局部作用域 一.在函数内可以访问全局变量 比如,下面的例子: <!--lang:js--> <script> var n = 100; function f1(){ console.log(n); } f1()//返回100 </script> 上面的例子很简单,下面是另一种情况. 二.在函数外无法读取函数内的局部变量 还是一个小例子: <!--lang:js-->

javascript深入理解js闭包

一.变量的作用域 要理解闭包,首先必须理解Javascript特殊的变量作用域. 变量的作用域无非就是两种:全局变量和局部变量. Javascript语言的特殊之处,就在于函数内部可以直接读取全局变量. Js代码 var n=999; function f1(){ alert(n); } f1(); // 999 另一方面,在函数外部自然无法读取函数内的局部变量. Js代码 function f1(){ var n=999; } alert(n); // error 这里有一个地方需要注意,函数

谈谈我对JS闭包的理解

这一篇博客承接上一篇,如果大家没看上一篇,建议看看.....直通车..... 好吧,咱们一起来看看这个闭包,这次我们的重点并不是弄明白闭包是什么?而是搞清楚JS的闭包是怎么产生的.接着上一篇博客的示例: var a = function(x){ var b = 'bb'; var inner = function(){ var c = 'cc'; }; return b; }; 当a函数执行到给inner变量赋值匿名函数之后,形成下面的引用关系,直接复用上次博客的图: 从上图很容易看出,这时候i

深入理解js闭包

闭包(closure)是Javascript语言的一个难点,也是它的特色,很多高级应用都要依靠闭包实现. 一.变量的作用域 要理解闭包,首先必须理解Javascript特殊的变量作用域. 变量的作用域无非就是两种:全局变量和局部变量. Javascript语言的特殊之处,就在于函数内部可以直接读取全局变量. Js代码 var n=999; function f1(){ alert(n); } f1(); // 999 另一方面,在函数外部自然无法读取函数内的局部变量. Js代码 function