之前有写过闭包,作用域,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。除了通过return还可以通过其他的几种方法如下:

  

  方法1:

    

function fn(){
  var a = 0;
  b = a;
}
alert(b)

  这里利用了js的一个特性,如果在函数中没有用var定义变量,那么这个变量属于全局的,但这种方法多少有些不好。

  

  方法2:

  

var f = null;
function fn(){
  var a = 0;
  f = function(){
    a++;
    f.a = a;
  };
}
fn();
f();
alert(f.a);//1
f();
alert(f.a);//2

但好像也没有那样神奇对吧?其实闭包还有一个很重要的特性。来看一个例子。

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

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

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

    lis[i].onclick = function(){

      alert(i);

    };

}

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

    

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

}

// i = 5对吧

  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已经是5了,所以所有的都打印出5来了。

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

  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是最后一次。

  

而外说一句:这里并不是说return就是闭包,这里只是强调return的重要性,如果你还是一个新手建议你多看一些初级文章,在来看这篇文章,希望你会有新收获。写这篇文章一开始我也说了它的目的是回顾一下当初我没有理解的地方,当初已经理解的这篇文章并没有过多的去讲。

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

大前端 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,好了一切就从这里结束吧。

js 闭包,作用域,this 终结篇(转)的更多相关文章

  1. 第九十九篇:JS闭包

    好家伙,总是要来的,去面对那些晦涩难懂的原理,它就在那里,等着我去搞定它 首先我要去补充一些最基本的概念, 1.什么是内存? 新华字典永远的神, 但这个解释显然不够   去看看百度百科: 内存: CP ...

  2. JS组件系列——表格组件神器:bootstrap table(三:终结篇,最后的干货福利)

    前言:前面介绍了两篇关于bootstrap table的基础用法,这章我们继续来看看它比较常用的一些功能,来个终结篇吧,毛爷爷告诉我们做事要有始有终~~bootstrap table这东西要想所有功能 ...

  3. js闭包的作用域以及闭包案列的介绍:

    转载▼ 标签: it   js闭包的作用域以及闭包案列的介绍:   首先我们根据前面的介绍来分析js闭包有什么作用,他会给我们编程带来什么好处? 闭包是为了更方便我们在处理js函数的时候会遇到以下的几 ...

  4. JS 之作用域链和闭包

    1.JS无块级作用域 <script> function Main(){ if (1==1){ var name = "alex"; } console.log(nam ...

  5. JS之作用域与闭包

    JS之作用域与闭包   作用域在JS中同样也是一个重要的概念.它不复杂,因为ES5中只有全局作用域和函数作用域,我们都知道他没有块级作用域.但在ES6中多了一个let,他可以保证外层块不受内层块的影响 ...

  6. 深入理解JS函数作用域链与闭包问题

    function fun(n,o) { console.log(o) return { fun:function(m){ return fun(m,n); } }; } ); a.fun(); a.f ...

  7. Js闭包的用途

    本来想总结一点JavaScript中的闭包的一些用法,在查资料的时候发现了一篇很好的文章,就转过来收藏了,下面附上传送门: js闭包的用途 ---------sunlylorn 我们来看看闭包的用途. ...

  8. 揭开JS闭包的面纱

    今天看了关于js闭包方面的文章,还是有些云里雾里,对于一个菜鸟来说,学习闭包确实有一定的难度,不说别的,能够在网上找到一篇优秀的是那样的不易. 当然之所以闭包难理解,个人觉得是基础知识掌握的不牢,因为 ...

  9. js闭包实例汇总

    本文是通过实例来帮助大家深刻理解js闭包,是篇非常不错的文章,这里推荐给大家,有需要的小伙伴可以参考下 Js闭包 闭包前要了解的知识 1. 函数作用域 (1).Js语言特殊之处在于函数内部可以直接读取 ...

  10. 转自知乎大神----JS 闭包是什么

    大名鼎鼎的闭包!这一题终于来了,面试必问. 请用自己的话简述 什么是「闭包」. 「闭包」的作用是什么. --------------------------------------- 首先来简述什么是 ...

随机推荐

  1. python面试必问 知识整理

      一 数据类型 1 数字 整型与浮点型   #整型int 作用:年纪,等级,身份证号,qq号等整型数字相关 定义: age=10 #本质age=int(10) #浮点型float 作用:薪资,身高, ...

  2. 4. Spring 如何通过 XML 文件配置Bean,以及如何获取Bean

    在 Spring 容器内拼凑 bean 叫做装配.装配 bean 的时候,你是在告诉容器,需要哪些 bean ,以及容器如何使用依赖注入将它们配合在一起. 理论上,bean 装配的信息可以从任何资源获 ...

  3. Sting、StringBuffer、StringBuilder

    (1)String是字符串常量,一旦创建之后不可更改:StringBuffer和StringBuilder是字符串变量,可以更改.String的不可变,所以适合作为Map的键. (2)StringBu ...

  4. css 制作翻页布局

    代码: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8 ...

  5. web测试注意点

    关于网页测试我们需要注意的地方有: 1.每次测试之前都需要代码更新.清理缓存,测试数据使用新数据. 2.各模块的信息归类是否正确.比如进入一级栏目或二级栏目的列表页,查看左侧栏目名称,右侧文章标题及内 ...

  6. python学习:格式化输出

    格式化输出 代码如下: name = input("Name:") age = input("Age:") job = input("Job:&quo ...

  7. jmeter--接口自动化jmeter+ant+jenkins

    的 一.介绍 接口自动化工具:jmeter+ant+jenkins 流程: -1.jmeter已录制或手动设置好脚本后 -2.配置ant,使用Ant工具,进行批量执行jmeter的脚本 -3.使用Je ...

  8. [LeetCode] Jewels and Stones 珠宝和石头

    You're given strings J representing the types of stones that are jewels, and S representing the ston ...

  9. [LeetCode] Encode N-ary Tree to Binary Tree 将N叉树编码为二叉树

    Design an algorithm to encode an N-ary tree into a binary tree and decode the binary tree to get the ...

  10. linux中vi编辑

    crt退出全屏:点击Alt+enter键 linux上传下载文件     Xftp.Filezilla.Winscp等工具 命令      sz  test.txt    #下载test.txt文件 ...