• Eloquent JavaScript #08# Bugs and Errors


    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
  • 相关阅读:
    下一代工具链「GitHub 热点速览 v.22.43」
    Vue3学习笔记(五)——路由,Router
    Node.js学习笔记(四)——NodeJS访问MongoDB与MySQL数据库
    Vue3学习笔记(一)——MVC与vue3概要、模板、数据绑定与综合示例
    Node.js学习笔记(二)——Node.js模块化、文件读写、环境变量
    Node.js学习笔记(一)——Node.js概要、NPM与package.json
    TypeScript学习笔记(三)—— 编译选项、声明文件、WebPack打包、Babel转换
    TypeScript学习笔记(四)—— TypeScript提高
    Vue3学习笔记(六)—— 作业
    Vue3学习笔记(二)——组合式API(Composition API)
  • 原文地址:https://www.cnblogs.com/xkxf/p/9568312.html
Copyright © 2020-2023  润新知