语句

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. Django MVC simple

  2. Atitit.软件开发提升稳定性总结

    Atitit.软件开发提升稳定性总结 #----影响稳定性几个类别 3 1. 资源和内存泄漏溢出 3 2. 数据库/文件死锁 3 3. 类库冲突 3 4. 热更新热部署(业务可用性 3 5. 程序崩溃 ...

  3. paip.自适应网页设计 跟 响应式 设计方法与工具补充(2)o54

    paip.自适应网页设计 跟 响应式 设计方法与工具补充(2)o54 #-----响应式 设计框架 Bootstrap比较热门. Foundation 号称是世界上最先进的响应式前端框架. #---绝 ...

  4. Leetcode 219 Contains Duplicate II STL

    找出是否存在nums[i]==nums[j],使得 j - i <=k 这是map的一个应用 class Solution { public: bool containsNearbyDuplic ...

  5. 学习Swift,一定不能错过的10大开源项目!

    如果你是位iOS开发者,或者你正想进入该行业,那么Swift为你提供了一个绝佳的机会.Swift的设计非常优雅,较Obj-C更易于学习,当然也非常强大. 为了指导开发者使用Swift进行开发,苹果发布 ...

  6. AYUI4.X即将发布

    AYUI里程碑故事: AYUI 1.x系列:   面向源码的方式开发,客户只有源码才能开发,客户端对接ayui,很不方便,相比上个版本,提供了一些元老控件,文件夹结构比较零散 AYUI 2.x系列: ...

  7. RS开发中的一些小技巧[不定期更新]

    从9月份一直忙到了现在,项目整体的改版工作也完成了十有八九了,有些事情只有你自己真正的做了,你才能明白:哦,原来还可以这个样子,这样做真的好了很多呢,接下来我就分享一些最近遇到的RS开发的一些小技巧, ...

  8. ambari初始化登陆账号/密码假如不是admin/admin

    如题:通常软件初始化密码都是admin: 但是hortonworks就突然傻逼了,居然不这样搞.(可能知道一些开发者不看官网文档,就特意弄成这样.正如我) 我上网搜了5分钟.感觉网上应该没有这样的资料 ...

  9. [转] The program can't start because api-ms-win-crt-runtime-l1-1-0.dll is missing

    https://www.smartftp.com/support/kb/the-program-cant-start-because-api-ms-win-crt-runtime-l1-1-0dll- ...

  10. linux 系统性能指标采样脚本

    以下脚本写于redmine性能排查时,用于定位系统性能瓶颈的采样,源地址为~/performanceLog/collectLog.sh中,计划放入github的代码片段库中. 注: 如果mysql的地 ...