首先强烈安利《你不知道的JavaScript》,JS初学者进阶必读。

对于从C++、Java等静态语言转向JavaScript的初学者(比如我)来说,JS一些与众不同而又十分要紧的特性使得它显得十分诡异而难以捉摸,为此必须下一番大力气,一边啃书一边实践将这些概念彻底搞懂,然后才谈得上进一步学习前端姿势。(注:本文里的JS以ECMAScript 5(ES5)为准,ES6的新特性我也是刚刚接触,希望今后能与大家一起学习探讨。)

熟悉Java的童鞋在初学JS时,必须要牢记一点:

JS中没有块级作用域!

{
var test=10;
}
console.log(test); // 控制台输出:10

纳尼?是不是看着很别扭?还有更坑爹的:

var obj={
test:10,
myFunc:function(){
console.log(test);
}
};
obj.myfunc(); // 出错,或者IDE直接报警了

同一个对象,自己的函数都不认自己的属性了?

还真是。

对于初学者而言,可以这样认为:除了全局作用域之外,JS只有一种作用域,即函数作用域。(try catch{}语句也可以定义作用域,不过目前为止我还没实际用过)

也就是说,写在函数体内的变量,只要不是嵌套在更深层的函数里,就是处在同一作用域的,“互相可见”;而其他的花括号,不管是for后跟的,if后跟的,还是对象字面量的,一概“不作数”,起不到定义作用域的效果,变量声明写在那些花括号的里面或外面都一样。

那位于嵌套的函数里的作用域呢?它们享有“单向透明”的特权,即:在较内层次的作用域内可以访问较外层次作用域里的变量,反之则不行。

function outerFunc(){
for(var i=0;i<10;i++){doSomething;}
console.log(i); // 控制台输出10,因为i位于outerFunc的作用域
var outer = 10;
function innerFunc(){
var inner = outer; // 内层作用域可以访问外层作用域里的变量
}
console.log(inner); // 报错,外层作用域访问不到内层作用域里的变量
}

再来分析上一个例子。我们试图在myFunc的作用域内部访问test,然而test并不是一个“与myFunc位于同一个对象作用域”的变量,事实上根本不存在“对象作用域”这回事,test是obj的一个属性,不是一个“独立”的变量,要访问test只能通过点运算符obj.test或obj["test"],哪怕是在myFunc内部。当然,myFunc内部可以访问到obj这个位于外层作用域的变量,没有问题。于是将代码改写如下:

var obj={
test:10,
myFunc:function(){
console.log(obj.test);
}
};
obj.myfunc(); //

既然在内层作用域里可以访问外层作用域,那么就产生了一个有趣的现象,叫做“闭包”。制造一个闭包只需要两步:

1.在内层函数里引用外层函数的变量

2.将内层函数作为外层函数的返回值返回出去

function outer(){
var test = 10;
var inner = function(){
console.log(test++);
};
return inner;
} var myFunc = outer(); // 将outer的返回值(inner函数)赋给myFunc
myFunc(); //
myFunc(); //
myFunc(); //

这个被返回的inner函数就是一个闭包。虽然outer函数运行结束了,但它的内部变量test因为被闭包引用,所以并没有被销毁,而是被保存了起来,并且可以通过闭包继续操作。当然,外界永远无法访问test这个变量,它成了inner(以及myFunc)所指向的函数的“私有变量”。

JavaScript中的作用域和闭包的更多相关文章

  1. Javascript中关于作用域和闭包和域解释的面试题

    <script type="text/javascript"> function fn() { var i = 10; return function (n) { co ...

  2. 认识javascript中的作用域和上下文

    javascript中的作用域(scope)和上下文(context)是这门语言的独到之处,这部分归功于他们带来的灵活性.每个函数有不同的变量上下文和作用域.这些概念是javascript中一些强大的 ...

  3. 深入理解JavaScript中的作用域和上下文

    介绍 JavaScript中有一个被称为作用域(Scope)的特性.虽然对于许多新手开发者来说,作用域的概念并不是很容易理解,我会尽我所能用最简单的方式来解释作用域.理解作用域将使你的代码脱颖而出,减 ...

  4. JavaScript中的作用域

    很多(JavaScript)开发者都在讨论"作用域",但它是什么?它们在JavaScript中的任何地方!我发现很多年轻的开发者不知道作用域是什么.他们中大多数人可以用jQuery ...

  5. 前端学习 第六弹: javascript中的函数与闭包

    前端学习 第六弹:  javascript中的函数与闭包 当function里嵌套function时,内部的function可以访问外部function里的变量 function foo(x) {   ...

  6. 【翻译】JavaScript中的作用域和声明提前

    原文:http://www.adequatelygood.com/JavaScript-Scoping-and-Hoisting.html ===翻译开始=== 你知道下面的JavaScript脚本执 ...

  7. JavaScript中的作用域和声明提前

    [翻译]JavaScript中的作用域和声明提前 原文:http://www.adequatelygood.com/JavaScript-Scoping-and-Hoisting.html ===翻译 ...

  8. javascript(面向对象,作用域,闭包,设计模式等)

    javascript(面向对象,作用域,闭包,设计模式等) 1. 常用js类定义的方法有哪些? 参考答案:主要有构造函数原型和对象创建两种方法.原型法是通用老方法,对象创建是ES5推荐使用的方法.目前 ...

  9. 漫谈JavaScript中的作用域(scope)

    什么是作用域 程序的执行,离不开作用域,也必须在作用域中才能将代码正确的执行. 所以作用域到底是什么,通俗的说,可以这样理解:作用域就是定义变量的位置,是变量和函数的可访问范围,控制着变量和函数的可见 ...

随机推荐

  1. 算法 python实现(二) 冒泡排序

    首先说一下 冒泡排序 是怎么做的: 总体的想法是,把小的轻的浮上前面去,把大的重的沉到后面去. 这样设置两个指针,i j, 1. i标识每一趟循环.这一趟的目的是把后面那些未排序的数列中最小的浮上前面 ...

  2. 数据库分库分表(sharding)系列【转】

    原文地址:http://www.uml.org.cn/sjjm/201211212.asp数据库分库分表(sharding)系列 目录; (一) 拆分实施策略和示例演示 (二) 全局主键生成策略 (三 ...

  3. 神经网络原理及其c++实现

    1引言 数字识别是模式识别领域 中的一个重要分支,数字识别一般通过特征匹配及特征判别的传统方法进行处理.特征匹配通常适用于规范化的印刷体字符的识别,而 特征判别多用于手写字符识别,这些方法还处于探索阶 ...

  4. Cogs 309. [USACO 3.2] 香甜的黄油 dijkstra,堆,最短路,floyd

    题目:http://cojs.tk/cogs/problem/problem.php?pid=309 309. [USACO 3.2] 香甜的黄油 ★★   输入文件:butter.in   输出文件 ...

  5. 关于vim打开中文文件出现乱码问题

    中文字符编码问题. 在你的vi配置文件(~/.vimrc)里面添加一行: set fileencodings=ucs-bom,utf-8,cp936,gb18030,latin1 意思是让vim从 这 ...

  6. hdoj 4738 Caocao's Bridges【双连通分量求桥】

    Caocao's Bridges Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) ...

  7. SSH架构

    说说项目架构整个变化过程吧 拿用户注册来举例: 数据库里面有一张User表 需要把注册信息存储到User表中 1.   最开始是两层架构 就是cliect   +  jsp    +   DB 就是在 ...

  8. OGG问题 ORA-01403的处理办法

    认识logdump分析工具及常用命令:http://book.51cto.com/art/201202/319253.htm http://www.killdb.com/2012/09/01/gold ...

  9. linux 入侵检查转载

    转载 本文给大家收集整理了一些审查Linux系统是否被入侵的方法,这些方法可以添加到你运维例行巡检中. 1. 检查帐户 代码如下: # less /etc/passwd # grep :0: /etc ...

  10. java 图片压缩 剪切 水印 转换 黑白 缩放

    专注java已6年,欢迎加入java核心技术QQ群:135138817,每周五晚有群主进行技术讲座. import java.awt.AlphaComposite; import java.awt.C ...