语句

JavaScript是解释型语言,解释器是按照顺序逐句执行的(除了进行一些少量预处理,如将函数声明提前)。

顺序是由流程控制语句来控制的,常用的流程控制语句包括:

  • 条件控制语句:if...else和switch...case语句
  • 循环控制语句:while...、do...while、for和for-in语句
  • 其他:break、continue和try...catch语句

代码中除去流程控制语句,剩下的部分只做两件事:

  • 为变量赋值(声明新变量并复制如var obj = {word: "hello"},或为已有变量赋值x=y)
  • 调用函数,比如console.log("hello world")

实际上为了完成以上两件事,代码还需要编写值或对象的字面量,以及访问现有变量,但是单独这样做没有意义。

函数执行过程

上面说到,除去流程控制,代码只做两件事,为变量赋值和调用函数。前者不难理解,现在来看调用函数后发生了什么:

当解释器调用一个函数之后,就会创建与之对应的变量对象(注意,一个变量对象与一次函数调用对应,而不是与一个函数对应),函数内声明的所有局部变量都绑定在这个变量对象上,函数执行完毕后,不出意外,该变量对象就会销毁。

我们将函数执行过程中所有可以访问到的变量的集合称为函数的执行上下文。对C++来说,函数的执行上下文只有函数内部定义的变量、函数实参和全局变量,而JavaScript的最大特点在于,函数的执行上下文包括了函数调用者的执行上下文,也就是说在函数内部可以毫无障碍地访问函数外部的数据。在我们什么都没做的时候,其实已经处在了全局的执行上下文之中了。

var names = [];
function sayhi(name){
if(!names[name]){
names.push(name);
}
console.log("hello "+name);
}
sayhi("Ross");
sayhi("Rachel");
console.log(names); //-> ["Ross", "Rachel"]
console.log(name); //-> undefined

上面函数sayhi执行过程中,代码试图访问names变量,但是在函数内部并未定义names(GCC这时就要报错了),所以函数就去sayhi的调用者(window)的变量对象上找到了names。

当函数内部调用其他函数(或自己)时,变量对象就变成了三个或者更多,当在函数内试图访问某个变量时,就会从内向外依次在变量对象中查找变量,直到找到第一个变量为止。

闭包

上文说到,函数执行完毕后,不出意外,该变量对象就会销毁。实际上,经常会出现意外。如果函数执行完毕后,仍然有可能访问到函数内部的变量,此时虽然执行流程已经在函数外部了,但函数的变量对象不会被销毁

var last;
function sayhi(name){
last = function(){
return name;
}
console.log("hello "+name);
}
sayhi("Ross");
console.log(last()); //-> "Ross"

由于在sayhi函数内部,我们将外部变量last赋值为了一个新的函数,该函数返回sayhi函数的实参name,所以sayhi("Ross")之后,虽然sayhi已经执行完成了,但是last仍然可以访问到sayhi内部的变量name,所以由sayhi("Ross")这次调用带来的变量对象不会被销毁。而且,只要接下来的代码(解释器永远不知道下一行代码是什么)有可能访问到该变量对象中的元素,该变量对象就不会销毁。

变量对象未销毁,其包含的所有元素(包括那些不可能再被访问到的元素)也会保留。所以,如果使用不当,闭包会超出预期限度地加重浏览器的负担。(现在已有一些浏览器如Chrome开始尝试回收闭包中的那些不可能再被访问到的元素)。

闭包可以用来模拟对象的私有变量。下面这个对象对象chandler模拟了C++中的类的实例,两个属性name和hobby只能通过方法访问,不能被改变。

var chandler = (function(){
var name = "CHANDLER";var hobby = "joke";return {
getName : function(){return name;},
getHobby : function(){return hobby;}
}
})();

JavaScript备忘录(2)——闭包的更多相关文章

  1. 深入理解javascript原型和闭包 (转)

    该教程绕开了javascript的一些基本的语法知识,直接讲解javascript中最难理解的两个部分,也是和其他主流面向对象语言区别最大的两个部分--原型和闭包,当然,肯定少不了原型链和作用域链.帮 ...

  2. JavaScript葵花宝典之闭包

    闭包,写过JS脚本的人对这个词一定不陌生,都说闭包是JS中最奇幻的一个知识点,  虽然在工作中,项目里经常都会用到~  但是是不是你已经真正的对它足够的了解~~ 又或者是你代码中出现的闭包,并不是你刻 ...

  3. 深入理解javascript原型和闭包系列

    从下面目录中可以看到,本系列有16篇文章,外加两篇后补的,一共18篇文章.写了半个月,从9月17号开始写的.每篇文章更新时,读者的反馈还是可以的,虽然不至于上头条,但是也算是中规中矩,有看的人,也有评 ...

  4. 让你分分钟学会Javascript中的闭包

    Javascript中的闭包 前面的话: 闭包,是 javascript 中重要的一个概念,对于初学者来讲,闭包是一个特别抽象的概念,特别是ECMA规范给的定义,如果没有实战经验,你很难从定义去理解它 ...

  5. 深入理解javascript原型和闭包(1)——一切都是对象

    “一切都是对象”这句话的重点在于如何去理解“对象”这个概念. ——当然,也不是所有的都是对象,值类型就不是对象. 首先咱们还是先看看javascript中一个常用的函数——typeof().typeo ...

  6. 深入理解javascript原型和闭包(2)——函数和对象的关系

    上文(理解javascript原型和作用域系列(1)——一切都是对象)已经提到,函数就是对象的一种,因为通过instanceof函数可以判断. var fn = function () { }; co ...

  7. 深入理解javascript原型和闭包(3)——prototype原型

    既typeof之后的另一位老朋友! prototype也是我们的老朋友,即使不了解的人,也应该都听过它的大名.如果它还是您的新朋友,我估计您也是javascript的新朋友. 在咱们的第一节(深入理解 ...

  8. 深入理解javascript原型和闭包(4)——隐式原型

    注意:本文不是javascript基础教程,如果你没有接触过原型的基本知识,应该先去了解一下,推荐看<javascript高级程序设计(第三版)>第6章:面向对象的程序设计. 上节已经提到 ...

  9. 深入理解javascript原型和闭包(5)——instanceof

    又介绍一个老朋友——instanceof. 对于值类型,你可以通过typeof判断,string/number/boolean都很清楚,但是typeof在判断到引用类型的时候,返回值只有object/ ...

随机推荐

  1. yafphp框架

    学习资料 Yaf(Yet Another Framework)用户手册http://www.laruence.com/manual/index.html laruence/yafhttps://git ...

  2. C语言实现单链表-03版

    在C语言实现单链表-02版中我们只是简单的更新一下链表的组织方式: 它没有更多的更新功能,因此我们这个版本将要完成如下功能: Problem 1,搜索相关节点: 2,前插节点: 3,后追加节点: 4, ...

  3. Paip.最佳实践-- Buildin variale 内建变量 ,魔术变量,预定义变量,系统常量,系统变量 1

    Paip.最佳实践-- Buildin variale 内建变量 ,魔术变量,预定义变量,系统常量,系统变量 1.1.1       C++内建变量(__LINE__).... 1.1.2       ...

  4. paip.输出内容替换在Apache 过滤器filter的设置

    paip.输出内容替换在Apache 过滤器filter的设置 作者Attilax  艾龙,  EMAIL:1466519819@qq.com 来源:attilax的专栏 地址:http://blog ...

  5. 分享几段JavaScript

    正则表达式 /*http://www.cnblogs.com/woxpp/*/ intege: "^-?[1-9]\\d*$", /*整数*/ intege1: "^[1 ...

  6. Leetcode 110 Balanced Binary Tree 二叉树

    判断一棵树是否是平衡树,即左右子树的深度相差不超过1. 我们可以回顾下depth函数其实是Leetcode 104 Maximum Depth of Binary Tree 二叉树 /** * Def ...

  7. 转:MPlayer源代码分析

    一.Mplayer支持的格式 MPlayer是一个LINUX下的视频播放器,它支持相当多的媒体格式,无论在音频播放还是在视频播放方面,可以说它支持的格式是相当全面的. 视频格式支持:MPEG.AVI. ...

  8. GTD中回顾闭环

    一: 回顾的作用 :让事情告一段落 A: 回顾已经完成---->找到成就感 B: 安排未完成----->做到心中有数 2: 让心情告一段落 当事情一天的事情告一段落的时候,内心就会彻底放下 ...

  9. 转connect() to unix:/var/run/php-fpm.sock failed (11: Resource temporarily unavailable)

    网站常出现502 bad gateway,程序没有问题. 根据nginx日志:connect() to unix:/var/run/php-fpm.sock failed (11: Resource ...

  10. [Aaronyang] 写给自己的WPF4.5 笔记19[Visual类图文并茂讲解]

    文章虽小,内容还好,且看且珍惜. aaronyang版权所有,不许转载,违者必究 当界面上使用数千个矢量图形,例如实时统计图,粒子碰撞,比如超级玛丽游戏,图像一直在绘,过量的使用WPF的元素系统和Sh ...