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. Github安全开源工具集合

    Scanners-Box是来自github平台的开源扫描仪的集合,包括子域枚举,数据库漏洞扫描程序,弱密码或信息泄漏扫描仪,端口扫描仪,指纹扫描仪和其他大型扫描仪,模块化扫描仪等.对于其他众所周知的扫 ...

  2. sap QG3搜索

    先创建一个QG3系统,创建一个用户. 1: 进入搜索模板 2: 选择软件组件,点击执行 3: 设置过滤条件. 4: 选择在哪一列 设置过滤条件. 5: 定义搜索值 6: 设置值 可以将搜索的结果删除. ...

  3. PHP数组和字符串的处理函数汇总

    大部分数组处理函数array_chunk — 将一个数组分割成多个array_column — 返回数组中指定的一列array_combine — 创建一个数组,用一个数组的值作为其键名,另一个数组的 ...

  4. keras实例学习-双向LSTM进行imdb情感分类

    源码:https://github.com/keras-team/keras/blob/master/examples/imdb_bidirectional_lstm.py 及keras中文文档 1. ...

  5. 【Java】-NO.16.EBook.4.Java.1.012-【疯狂Java讲义第3版 李刚】- JDBC

    1.0.0 Summary Tittle:[Java]-NO.16.EBook.4.Java.1.012-[疯狂Java讲义第3版 李刚]-  JDBC Style:EBook Series:Java ...

  6. 动态添加class的一种方法

    外面可以写一层class再用:class 绑定新的clss进去  而且可以用三目运算.爽歪歪

  7. Mac上安装PHP、Apache、MySQL

    Mac自带php5.6版本,要升级到php7.3 步骤如下 1,brew 安装php ,如果没有安装,访问https://brew.sh/index_zh-cn安装在终端输入以下内容,不用指定安装ph ...

  8. linux 执行远程linux上的shell脚本或者命令以及scp 上传文件到ftp--免密码登陆

    场景:在linux A 上执行Linux B上的shell脚本和命令 步骤1.设置ssh免登陆 1.SSH无密码登录 # 本地服务器执行(A机器):生成密钥对 ssh-keygen -t dsa -P ...

  9. 备份软件 FreeFileSync 怎么用

    现在,学会使用备份软件对电脑中的重要资料定期进行备份,已经成为许多办公一族的“必修课”.其中,FreeFileSync 作为一款由国外开源社区开发的免费备份软件,由于其支持跨平台(Windows.Li ...

  10. IdentityServer4:IdentityServer4+API+Client+User实践OAuth2.0密码模式(2)

    一.密码模式实操 仍然使用第一节的代码:做如下改动: 1.授权服务端 前面我们使用项目:Practice.IdentityServer作为授权服务器 修改项目的Config.cs类: 添加测试用户,并 ...