Notes

1、strict mode

strict mode优势:更严格的检查、删除了一些有问题的语言特性。

把 "use strict" 放在文件顶部(必须是文件顶部,放在其它地方就被当成字符串了)或者函数顶部开启js strict模式。

示例1:没启用strict模式,js就会给你悄摸摸地加一个let上去...

function canYouSpotTheProblem() {
"use strict";
for (counter = 0; counter < 10; counter++) {
console.log("Happy happy");
}
} canYouSpotTheProblem();
// → ReferenceError: counter is not defined

示例2:没启用strict模式,name被悄悄地绑定到一个全局对象上而没报错。

function Person(name) { this.name = name; }
let ferdinand = Person("Ferdinand"); // oops
console.log(name);
// → Ferdinand
console.log(window.name);
// → Ferdinand // - -- - --修改↓分割线------------------------------------ "use strict";
function Person(name) { this.name = name; }
let ferdinand = Person("Ferdinand"); // forgot new
// → TypeError: Cannot set property 'name' of undefined

PS. 上述情况,用class定义类具有和采用strict模式一样的效果,所以尽量用class定义类。

2、js类型

js在在运行时才会涉及到类型。许多语言在编译期就考虑类型了。

为了减少js类型带来的一些问题,有两个简单的解决方案:

① 注释

// (VillageState, Array) → {direction: string, memory: Array}
function goalOrientedRobot(state, memory) {
// ...
}

② TypeScript

可以进行类型检查,并编译成js

3、js测试

采用第三方测试套件或者如下所示:

function test(label, body) {
if (!body()) console.log(`Failed: ${label}`);
} test("convert Latin text to uppercase", () => {
return "hello".toUpperCase() == "HELLO";
});
test("convert Greek text to uppercase", () => {
return "Χαίρετε".toUpperCase() == "ΧΑΊΡΕΤΕ";
});
test("don't convert case-less characters", () => {
return "مرحبا".toUpperCase() == "مرحبا";
});

4、Debugging

console.log或者debugger关键字:

function add(a, b) {
console.log(`add ${a} and ${b}`);
return a + b;
} debugger; // 从这一行开始进入浏览器debug模式 let x = add(1, 3);
prompt("只有在开发者模式下,debug模式才生效");

5、Exceptions

异常的一大优势:几乎无耦合地在多个函数中(调用栈)传递,中间函数什么都不需要知道,仅在最外层处理就行了。

function promptDirection(question) {
let result = prompt(question);
if (result.toLowerCase() == "left") return "L";
if (result.toLowerCase() == "right") return "R";
throw new Error("Invalid direction: " + result);
} function look() {
if (promptDirection("Which way?") == "L") {
return "a house";
} else {
return "two angry bears";
}
} try {
console.log("You see", look());
} catch (error) {
console.log("Something went wrong: " + error);
}

6、finally

function transfer(from, amount) {
if (accounts[from] < amount) return;
let progress = 0;
try {
accounts[from] -= amount;
progress = 1;
accounts[getAccount()] += amount;
progress = 2;
} finally {
if (progress == 1) {
accounts[from] += amount;
}
}
} //Writing programs that operate reliably
//even when exceptions pop up in unexpected places
//is hard. Many people simply don’t bother,
//and because exceptions are typically reserved
//for exceptional circumstances, the problem may
//occur so rarely that it is never even noticed.
//Whether that is a good thing or a really bad thing
//depends on how much damage the software will do when it fails.

7、异常分支

js不支持catch分支,而在try-catch的时候,同样会捕获undefined.call等造成的异常。

有些人可能会想只要比对e里面的信息就可以知道哪儿出现问题了,但是异常信息不是一个稳定的东西,一旦抛出的异常信息的表达改变,程序就不会正常工作,更可靠的解决方案如下(自定义空异常,只为了利用class区分,不加任何东西):

class InputError extends Error {}

function promptDirection(question) {
let result = prompt(question);
if (result.toLowerCase() == "left") return "L";
if (result.toLowerCase() == "right") return "R";
throw new InputError("Invalid direction: " + result);
} for (;;) {
try {
let dir = promptDirection("Where?");
console.log("You chose ", dir);
break;
} catch (e) {
if (e instanceof InputError) {
console.log("Not a valid direction. Try again.");
} else {
throw e;
}
}
}

Exercises

① Retry

class MultiplicatorUnitFailure extends Error {}

function primitiveMultiply(a, b) {
if(Math.random() < 0.2) {
return a * b;
} else {
throw new MultiplicatorUnitFailure("Klunk");
}
} function reliableMultiply(a, b) {
let result = undefined;
for (; result == undefined;) {
try {
result = primitiveMultiply(a, b);
} catch(e) {
if (e instanceof MultiplicatorUnitFailure) {
} else {
throw e;
}
}
}
return result;
} console.log(reliableMultiply(8, 8));
// → 64

————-- - ---  -- - -  -------—-- - -—-- - -

② The locked box

const box = {
locked: true,
unlock() { this.locked = false; },
lock() { this.locked = true; },
_content: [],
get content() {
if (this.locked) throw new Error("Locked!");
return this._content;
}
}; function withBoxUnlocked(body) {
let locked = box.locked;
if (!locked) {
return body();
} box.unlock();
try {
return body();
} finally {
box.lock();
}
} withBoxUnlocked(function() {
box.content.push("gold piece");
}); try {
withBoxUnlocked(function() {
throw new Error("Pirates on the horizon! Abort!");
});
} catch (e) {
console.log("Error raised:", e);
} console.log(box.locked);
// → true

Eloquent JavaScript #08# Bugs and Errors的更多相关文章

  1. Eloquent JavaScript #13# HTTP and Forms

    索引 Notes fetch form focus Disabled fields form’s elements property 阻止提交 快速插入单词 实时统计字数 监听checkbox和rad ...

  2. Eloquent JavaScript #11# The Document Object Model

    索引 Notes js与html DOM 在DOM树中移动 在DOM中寻找元素 改变Document 创建节点 html元素属性 布局 style CSS选择器 动画 Exercises Build ...

  3. Eloquent JavaScript #10# Modules

    索引 Notes 背景问题 模块Modules 软件包Packages 简易模块 Evaluating data as code CommonJS modules ECMAScript modules ...

  4. Eloquent JavaScript #04# Objects and Arrays

    要点索引: JSON More ... 练习 1.补:js字符串的表达方式有三种: "" 和 '' 没什么区别,唯一区别在于 "" 中写 "要转义字符 ...

  5. Eloquent JavaScript #03# functions

    索引: let VS. var 定义函数的几种方式 more... 1.作者反复用的side effect side effect就是对世界造成的改变,例如说打印某些东西到屏幕,或者以某种方式改变机器 ...

  6. Eloquent JavaScript #02# program_structure

    第一章中作者介绍了各种值,但是这些独立的值是没有意义的,只有当值放在更大的框架的时候才会彰显它们的价值.所以第二章开始介绍程序结构. 1.var VS. let 以及 const 作者推荐用 let ...

  7. Eloquent JavaScript #01# values

    When action grows unprofitable, gather information; when information grows unprofitable, sleep.      ...

  8. Eloquent JavaScript #12# Handling Events

    索引 Notes onclick removeEventListener Event objects stopPropagation event.target Default actions Key ...

  9. Eloquent JavaScript #09# Regular Expressions

    索引 Notes js创建正则表达式的两种方式 js正则匹配方式(1) 字符集合 重复匹配 分组(子表达式) js正则匹配方式(2) The Date class 匹配整个字符串 Choice pat ...

随机推荐

  1. abap函数返回结构体类型

    1: 定义一个结构体 T-CODE   se11 2: 选择 structure 3:输入相应的字段 4:激活 5:创建一个function module zfm_return_table,返回类型为 ...

  2. Ajax与跨域Ajax

    Ajax 对于WEB应用程序:用户浏览器发送请求,服务器接收并处理请求,然后返回结果,往往返回就是字符串(HTML),浏览器将字符串(HTML)渲染并显示浏览器上.对于传统的Web应用,一个简单操作需 ...

  3. Java获取环境变量

    Java 获取环境变量Java 获取环境变量的方式很简单: System.getEnv()  得到所有的环境变量System.getEnv(key) 得到某个环境变量的值 Map map = Syst ...

  4. 模仿以太坊 ERC20 规范的 Hyperledger Fabric 实现 Token 通证

    合约: package main /* -------------------------------------------------- Author: netkiller <netkill ...

  5. Python socketserver模块解析

    参考:https://blog.csdn.net/qq_33733970/article/details/79153938 1.功能简介 socketserver模块是对socket模块的再封装,用于 ...

  6. 读取Request body方法

    一:传统方法 StringBuilder stringBuilder = new StringBuilder(); BufferedReader bufferedReader = null; try ...

  7. c#中取整和取余

    "%"为取余. "/"号整型运算是取整,浮点运算时为除法运算.如54/10结果为5,54.0/10.0结果为5.4.而且取整时不进行四舍五入只取整数部分,如54 ...

  8. nginx 长连接keeplive

    发现后台日志打印太多 FD打开太多的日志. 处理思路: 修改nginx upstream的长连接 http://blog.csdn.net/gzh0222/article/details/852363 ...

  9. 时间序列模式(ARIMA)---Python实现

    时间序列分析的主要目的是根据已有的历史数据对未来进行预测.如餐饮销售预测可以看做是基于时间序列的短期数据预测, 预测的对象时具体菜品的销售量. 1.时间序列算法: 常见的时间序列模型; ​ 2.时序模 ...

  10. 深入理解Java虚拟机2-chap3-斗之气9段

    一.GC需要完成三件事 哪些内存需要回收:找出不需要使用的对象 什么时候回收:JVM空闲/堆内存紧张 如何回收:回收垃圾的策略 二.寻找已死对象:第一件事 判断对象是否存活算法 1.引用计数算法 原理 ...