Introduction

本系列文章为You Don't Know JS的读书笔记。

书籍地址:https://github.com/getify/You-Dont-Know-JS

Scope From Functions

一个非常普遍的观点是,Javascript的作用域是基于函数的,这个观点其实并不是那么正确,不过,让我们来先看一下函数级别的作用域。

function foo(a) {
var b = 2;
// some code
function bar() {
// ...
}
// more code
var c = 3;
}

foo函数中有4个标识符,a、b、c、bar。这些标识符在什么位置定义并不重要,变量或者是函数,都将归属于当前的作用域。

bar()也有与之对应的作用域,全局作用域也是如此(仅有一个表示符foo与它关联)。

a,b,c,bar都隶属于foo(..)作用域,在foo(..)的外部,是无法操作到它们的。在全局作用域下写如下代码:会抛出ReferenceError

bar(); // fails
console.log( a, b, c ); // all 3 fail

Functions As Scopes

使用函数作为代码的封装,有一些细节上的问题:我们使用foo(..)封装代码时,foo本身也污染了作用域。如果我们只是为了隐藏细节,不是为了抽象代码逻辑,那么,这是一个解决方案:

(function foo(){
// Coding here
})();

这样做,foo是污染不了全局作用域的(也许我们更愿意在这种情况下采用匿名版本)。

(function (){
// Coding here
})();

这里说一下使用匿名函数的两个坏处:无法在stack traces中识别到他们、低代码可读性。

所以除了较短的逻辑,尽量不要用匿名函数。

Invoking Function Expressions Immediately

刚才我们通过把函数包装在(..)中,再立即调用,被称为Immediately Invoked Function Expression,简称为IIFE,为了避免匿名函数的坏处,IIFE可以这样命名

var a = 2;
(function IIFE(){ var a = 3;
console.log( a ); // 3 })();
console.log( a ); // 2

关于客户端的IIEF,经常可以看到这样的代码,传window,做些事情。

var a = 2;
(function IIFE( global ){ var a = 3;
console.log( a ); // 3
console.log( global.a ); // 2
})( window );

还有这样的,比较暗黑的做法(防止某变量被外界覆盖,比如undefined):

undefined = true; // setting a land-mine for other code! avoid!

(function IIFE( undefined ){
var a;
if (a === undefined) {
console.log( "Undefined is safe here!" );
}
})();

Blocks As Scopes

for (var i=0; i<10; i++) {
console.log( i );
}
console.log(i);

很多从其它语言切换切换到js,不能理解以上的代码居然可以输出10。

其它语言常用到的块级作用域,在js上似乎没有,其实不然。

try/catch

try {
undefined(); // illegal operation to force an exception!
}
catch (err) {
console.log( err ); // works!
}
console.log( err ); // ReferenceError: `err` not found

注意到没有,catch是能拿到err,但是log却拿不到。

虽然这是ES3的规范,但是很多语法验证工具会在有多个try/catch,且catch的形参都为err或者其它相同的名字时,会报re-definition的warning,不用管。

let

ES6提供了新的关键字let。

var foo = true;
if (foo) {
let bar = foo * 2;
bar = something( bar );
console.log( bar );
}
console.log( bar ); // ReferenceError

块级风格。

for (let i=0; i<10; i++) {
console.log( i );
}
console.log( i ); // ReferenceError

需要注意的是,如果使用let

{
console.log( bar ); // ReferenceError!
let bar = 2;
}

在这一点上,和var是不一样的。

const

const也是ES6提供的新关键字,除了定义出的变量初始化后不可更改外,其它与let一致。

YDKJ 读书笔记 01 Function vs. Block Scope的更多相关文章

  1. 《The Linux Command Line》 读书笔记01 基本命令介绍

    <The Linux Command Line> 读书笔记01 基本命令介绍 1. What is the Shell? The Shell is a program that takes ...

  2. 硬盘和显卡的访问与控制(一)——《x86汇编语言:从实模式到保护模式》读书笔记01

    本文是<x86汇编语言:从实模式到保护模式>(电子工业出版社)的读书实验笔记. 这篇文章我们先不分析代码,而是说一下在Bochs环境下如何看到实验结果. 需要的源码文件 第一个文件是加载程 ...

  3. Android开发艺术探索读书笔记——01 Activity的生命周期

    http://www.cnblogs.com/csonezp/p/5121142.html 新买了一本书,<Android开发艺术探索>.这本书算是一本进阶书籍,适合有一定安卓开发基础,做 ...

  4. ANTLR3完全参考指南读书笔记[01]

    引用 Terence Parr. The Definitive ANTLR Reference, Building Domain Specific Languages(antlr3 version). ...

  5. [读书笔记]SQLSERVER企业级平台管理实践读书笔记01

    1. SQLSERVER信息收集 SQLDIAG 使用界面 C:\Users\Administrator>sqldiag2018/01/02 08:13:26.10 SQLDIAG Collec ...

  6. 读书笔记(01) - JSON - JavaScript高级程序设计

    JSON与JavaScript对象 JSON是一种表示结构化数据的存储格式,语法格式上与JavasScript对象有些类似. TIPS: 与JavaScript对象的格式区别 不支持变量.函数或对象实 ...

  7. 『TCP/IP详解——卷一:协议』读书笔记——01

    从今日起开始认真研读TCP/IP详解这本经典制作,一是巩固我薄弱的计算机网络知识,二来提高我的假期的时间利用率.将心得与思考记录下来,防止白看-哦耶 2013-08-14 18:47:06 第一章 概 ...

  8. PHP开发圣经读书笔记01

    从今天开始,以“圣经”这本书为教材,系统的温习一下php,之前都是看视频学的. 1.访问表单变量--php变量名称必须与表单域的名称一致 例:$_POST['uname'];  //表示把表单域中na ...

  9. <EffectiveJava>读书笔记--01继承的使用注意

    1, 父类的构造器方法中不能调用能够被子类重写的方法. 分析: 当初始化一个子类时, 首先要初始化父类, 即调用父类的构造方法; 如果父类的构造方法中调用了可被重写的其它方法, 那么此时调用的其实是该 ...

随机推荐

  1. 「USACO06FEB」「LuoguP2858」奶牛零食Treats for the Cows(区间dp

    题目描述 FJ has purchased N (1 <= N <= 2000) yummy treats for the cows who get money for giving va ...

  2. php之创建jsonp接口调数据

    jsonp跨域访问数据 首先在php内写jsonp调用接口 <?php//设置头部文件类型为json header('Content-type: application/json'); //将r ...

  3. 截图工具,更改系统默认快捷键,系统配置实用程序,以管理员身份运行cmd(win7)

    截图工具: 开始--附件--右键发送到桌面快捷方式---桌面截图工具右键属性--快捷方式 更改系统默认快捷键: 控制面板--外观和个性化--调整屏幕分辨率--高级设置---英特尔图形和媒体控制面板-- ...

  4. inline关键字的用法详解

    1. 引入inline关键字的原因 在c/c++中,为了解决一些频繁调用的小函数大量消耗栈空间(栈内存)的问题,特别的引入了inline修饰符,表示为内联函数. 栈空间就是指放置程序的局部数据(也就是 ...

  5. JavaScript-Tool:jquery.qrcode.js

    ylbtech-JavaScript-Tool:jquery.qrcode.js 1.返回顶部 1. 插件描述:jquery.qrcode.js 是一个能够在客户端生成矩阵二维码QRCode 的jqu ...

  6. c++中stl----map

    1 map的本质 (1)关联式容器,键值对应 (2)增加和删除节点对迭代器的影响很小. (3)对于迭代器来说不可以修改键值,只能修改对应的实值. (4)map内部数据的祖居是自建一颗红黑树(或者说是平 ...

  7. Laravel中的模板引擎Blade

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  8. 一个IP绑定多个域名的实现方法

    方案一: 文字叙述: 具体步骤如下:比如讲apache服务器127.0.0.1 配置成 www.sohu.com 首先在http.conf文件中 做如下处理: ①关闭默认的 #DocumentRoot ...

  9. CodeForces 496D Tennis Game (暴力枚举)

    题意:进行若干场比赛,每次比赛两人对决,赢的人得到1分,输的人不得分,先得到t分的人获胜,开始下场比赛,某个人率先赢下s场比赛时, 游戏结束.现在给出n次对决的记录,问可能的s和t有多少种,并按s递增 ...

  10. JavaScript Symbol

    创建: 2019/02/26 完成: 2019/02/26  生成  每次生成的值都不一样(===, ==都是) var sym = Symbol(); // 可以有参数, 是对symbol的说明 v ...