单挑JavaScript系列——流程控制与错误处理

1,258 阅读5分钟

一个信息:由于重学是一个长期过程,目前待完成(todo)的概念既是今后需要持续理解的东西,入门阶段只是intro。

语句块

{statement_1;statement_2;statement_3} //so as you know

在ECMAScript 6标准之前,Javascript没有块作用域。在一个块中引入的变量的作用域是包含函数或脚本,并且设置它们的效果会延续到块之外。换句话说,块语句不定义范围。JavaScript中的“独立”块会产生与C或Java中完全不同的结果。

var x = 1;
{
  var x = 2;
}
alert(x); // 输出的结果为 2

这段代码的输出是2,这是因为块级作用域中的 var x变量声明与之前的声明在同一个作用域内。在C语言或是Java语言中,同样的代码输出的结果是1。 从 ECMAScript 2015 开始,使用 let 和const变量是块作用域的。 更多信息请参考 let 和 const。 而var没有这个问题,不存在块作用域。

image.png

条件判断语句

  • if...else 语句

错误的值,下面这些值将被计算出 false (就是俗称的Falsy):

  • false
  • undefined
  • null
  • 0
  • NaN
  • 空字符串("")

var b = new Boolean(false);//是一个对象Boolean {false}

  • switch语句
switch (expression) {
   case label_1:
      statements_1
      [break;]
   case label_2:
      statements_2
      [break;]
   ...
   default:
      statements_def
      [break;]
}

程序首先查找一个与 expression 匹配的 case 语句,然后将控制权转移到该子句,执行相关的语句。如果没有匹配值, 程序会去找 default 语句,如果找到了,控制权转移到该子句,执行相关的语句。如果没有找到 default,程序会继续执行 switch 语句后面的语句。default 语句通常出现在switch语句里的最后面,当然这不是必须的。

可选的 break 语句与每个 case 语句相关联, 保证在匹配的语句被执行后程序可以跳出 switch 并且继续执行 switch 后面的语句。如果break被忽略,则程序将继续执行switch语句中的下一条语句。

switch语句的执行逻辑大概的了解一下,还是有益滴

异常处理语句

  • 理解throw语句

你可以用 throw 语句抛出一个异常并且用 try...catch 语句捕获处理它。 不try catch的话就是抓不到的意思,console.log //Uncaught expression

异常类型 JavaScript 可以抛出任意对象。然而,不是所有对象能产生相同的结果。尽管抛出数值或者字母串作为错误信息十分常见,但是通常用下列其中一种异常类型来创建目标更为高效: (todo)

  • ECMAScript exceptions
  • DOMException and DOMError

throw 语句

  • 使用throw语句抛出一个异常。当你抛出异常,你规定一个含有值的表达式要被抛出。 throw expression; 注意:你可以在抛出异常时声明一个对象。那你就可以在catch块中查询到对象的属性。
// Create an object type UserException
function UserException (message){
  this.message=message;
  this.name="UserException";
}

// Make the exception convert to a pretty string when used as
// a string (e.g. by the error console)
UserException.prototype.toString = function (){
  return this.name + ': "' + this.message + '"';
}

// Create an instance of the object type and throw it
throw new UserException("Value too high");

try...catch 语句

  • try...catch 语句标记一块待尝试的语句,并规定一个以上的响应应该有一个异常被抛出。如果我们抛出一个异常,try...catch语句就捕获它。

  • 执行逻辑

try...catch 语句有一个包含一条或者多条语句的try代码块,0个或1个的catch代码块,catch代码块中的语句会在try代码块中抛出异常时执行。 换句话说,如果你在try代码块中的代码如果没有执行成功,那么你希望将执行流程转入catch代码块。如果try代码块中的语句(或者try 代码块中调用的方法)一旦抛出了异常,那么执行流程会立即进入catch 代码块。如果try代码块没有抛出异常,catch代码块就会被跳过。finally 代码块总会紧跟在try和catch代码块之后执行,但会在try和catch代码块之后的其他代码之前执行。

  • finally块 finally块包含了在try和catch块完成后、下面接着try...catch的语句之前执行的语句。finally块无论是否抛出异常都会执行。如果抛出了一个异常,就算没有异常处理,finally块里的语句也会执行。

你可以用finally块来令你的脚本在异常发生时优雅地退出;举个例子,你可能需要在绑定的脚本中释放资源。接下来的例子用文件处理语句打开了一个文件(服务端的JavaScript允许你进入文件)。如果在文件打开时一个异常抛出,finally块会在脚本错误之前关闭文件。

  • 使用Error对象

根据错误类型,你也许可以用'name'和'message'获取更精炼的信息。'name'提供了常规的错误类(如 'DOMException' 或 'Error'),而'message'通常提供了一条从错误对象转换成字符串的简明信息。

在抛出你个人所为的异常时,为了充分利用那些属性(比如你的catch块不能分辨是你个人所为的异常还是系统的异常时),你可以使用 Error 构造函数。比如:

function doSomethingErrorProne () {
  if (ourCodeMakesAMistake()) {
    throw (new Error('The message'));
  } else {
    doSomethingToGetAJavascriptError();
  }
}
....
try {
  doSomethingErrorProne();
}
catch (e) {
  console.log(e.name); // logs 'Error'
  console.log(e.message); // logs 'The message' or a JavaScript error message)
}

Promises

(todo)

从 ECMAScript 6 开始,JavaScript 增加了对 Promise 对象的支持,它允许你对延时和异步操作流进行控制。

Promise 对象有以下几种状态:

  • pending:初始的状态,即正在执行,不处于 fulfilled 或 rejected 状态。
  • fulfilled:成功的完成了操作。
  • rejected:失败,没有完成操作。
  • settled:Promise 处于 fulfilled 或 rejected 二者中的任意一个状态, 不会是 pending。

image.png

  • 通过 XHR 加载图片 (todo)

你可以在 MDN GitHub promise-test 中找到这个简单的例子,它使用了 Promise 和 XMLHttpRequest 来加载一张图片,你也可以直接在这个页面查看他的效果。同时为了让你更清楚的了解 Promise 和 XHR 的结构,代码中每一个步骤后都附带了注释。

  • MDN示例,Promise的工作流
function imgLoad(url) {
  return new Promise(function(resolve, reject) {
    var request = new XMLHttpRequest();
    request.open('GET', url);
    request.responseType = 'blob';
    request.onload = function() {
      if (request.status === 200) {
        resolve(request.response);
      } else {
        reject(Error('Image didn\'t load successfully; error code:'
                     + request.statusText));
      }
    };
    request.onerror = function() {
      reject(Error('There was a network error.'));
    };
    request.send();
  });
}