Wang's blog Wang's blog
首页
  • 前端文章

    • HTML教程
    • CSS
    • JavaScript
  • 前端框架

    • Vue
    • React
    • VuePress
    • Electron
  • 后端技术

    • Npm
    • Node
    • TypeScript
  • 编程规范

    • 规范
  • 我的笔记
  • Git
  • GitHub
  • VSCode
  • Mac工具
  • 数据库
  • Google
  • 服务器
  • Python爬虫
  • 前端教程
更多
收藏
关于
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

Wang Mings

跟随大神,成为大神!
首页
  • 前端文章

    • HTML教程
    • CSS
    • JavaScript
  • 前端框架

    • Vue
    • React
    • VuePress
    • Electron
  • 后端技术

    • Npm
    • Node
    • TypeScript
  • 编程规范

    • 规范
  • 我的笔记
  • Git
  • GitHub
  • VSCode
  • Mac工具
  • 数据库
  • Google
  • 服务器
  • Python爬虫
  • 前端教程
更多
收藏
关于
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • CSS

  • Npm

  • Vue

  • HTML

  • Node

  • Yaml

  • React

  • 框架

  • 规范

  • Electron

  • JS演示

  • VuePress

  • JavaScript

    • DOM
    • 事件
    • 实用API
    • 作用域
    • 基础篇
      • 一、JS的一些名词概念
        • 什么是作用域?
        • 什么是闭包?
        • 什么是构造函数?
        • 什么是实例对象?
        • 什么是this?
        • 什么是原型?
        • 什么是原型链?
        • 什么是constructor?
        • 什么是包装对象?
      • 二、数据类型的转换
        • 1、强制(手动)转换
        • Number()
        • String()
        • Boolean()
        • 2、自动转换
        • 自动转换为布尔值(Boolean)
        • 自动转换为字符串(String)
        • 所有类型的值与字符串相加都会变成字符串
        • 自动转换为数值(Number)
        • 除加号与字符串运行会转成字符串外,其他运行基本都会自动转成数值
      • 三、错误处理机制
        • 1、Error实例对象
        • 2、原生错误类型
        • SyntaxError 对象(语法错误)
        • ReferenceError 对象(引用错误)
        • RangeError 对象(范围错误)
        • TypeError 对象(类型错误)
        • URIError 对象 (URI错误)
        • EvalError 对象 (eval错误)
        • 总结(开发者手动使用)
        • 3、自定义错误
        • 4、throw 语句 (中断程序并抛出错误)
        • 5、try...catch 结构(捕获错误,对错误进行处理,不中断)
        • 6、finally 代码块(在try..catch最后,必执行的)
      • 四、console对象
        • console.time(),console.timeEnd() (用于计算程序的用时)
      • 文档
    • 定时器
    • 内存管理
    • 异步操作
    • 日期处理
    • 点击约束
    • 防抖节流
    • this的学习
    • ES面向对象
    • JS事件详解
    • new命令原理
    • 内置对象篇
    • 函数柯里化
    • 正则表达式
    • 浏览器模型
    • 事件订阅发布
    • 获取页面高度
    • 面向对象编程
    • JS随机打乱数组
    • js各种开发技巧
    • 函数的深入浅出
    • 防抖与节流函数
    • 模块化的使用总结
    • JS获取和修改url参数
    • JS设计模式总结笔记
    • fetch拦截和封装使用
    • 浏览器渲染原理流程
    • JavaScript对象从浅入深
    • JavaScript高级程序设计
    • Promise使用和实现方法
    • JS的种打断点调试方式
    • js深浅拷贝详解与实现
    • 九种跨域方式实现原理
    • 多种数组去重性能对比
    • 闭包原理以及使用场景
    • 判断是否为移动端浏览器
    • 比typeof运算符更准确的类型判断
    • 搞清事件循环、宏任务、微任务
    • 将一维数组按指定长度转为二维数组
  • TypeScript

  • 微信小程序

  • TypeScript-axios

  • 前端
  • JavaScript
wangmings
2022-07-19
目录
一、JS的一些名词概念
什么是作用域?
什么是闭包?
什么是构造函数?
什么是实例对象?
什么是this?
什么是原型?
什么是原型链?
什么是constructor?
什么是包装对象?
二、数据类型的转换
1、强制(手动)转换
Number()
String()
Boolean()
2、自动转换
自动转换为布尔值(Boolean)
自动转换为字符串(String)
所有类型的值与字符串相加都会变成字符串
自动转换为数值(Number)
除加号与字符串运行会转成字符串外,其他运行基本都会自动转成数值
三、错误处理机制
1、Error实例对象
2、原生错误类型
SyntaxError 对象(语法错误)
ReferenceError 对象(引用错误)
RangeError 对象(范围错误)
TypeError 对象(类型错误)
URIError 对象 (URI错误)
EvalError 对象 (eval错误)
总结(开发者手动使用)
3、自定义错误
4、throw 语句 (中断程序并抛出错误)
5、try...catch 结构(捕获错误,对错误进行处理,不中断)
6、finally 代码块(在try..catch最后,必执行的)
四、console对象
console.time(),console.timeEnd() (用于计算程序的用时)
文档

基础篇

说明:本章内容为博主在原教程基础上添加自己的学习笔记,来源https://wangdoc.com/javascript/ (opens new window),教程版权归原作者所有。

# 基础篇

# 一、JS的一些名词概念

# 什么是作用域?

变量存在的范围。

可分为全局作用域和函数作用域,ES6新增块级作用域。

# 什么是闭包?

闭包就是能够读取其他函数内部变量的函数。

  • 闭包的形式:函数内部定义函数
  • 本质上闭包就是将函数内部和外部连接起来的一座桥梁

闭包的作用:

  • 可以读取函数内部变量
  • 让这些变量始终保持在内存中,即闭包可以使得它诞生的环境一直存在。
  • 封装对象的私有属性和私有方法

# 什么是构造函数?

用于构造(生成)实例的一个函数,使实例拥有构造函数内定于的属性和方法。

# 什么是实例对象?

实例对象就是通过new 构造函数生成的,拥有构造函数内定于的属性和方法的一个对象。

# 什么是this?

就是属性或方法当前所在的对象,指向当前运行环境(对象)

# 什么是原型?

每个函数都有一个prototype属性,指向一个对象,该对象称为原型对象。

# 什么是原型链?

所有对象都有自己的原型对象,由于原型对象也是对象,因此它也有自己的原型,这就会形成一个原型链。

最顶层的原型是Object.prototype。

读取对象属性时,JS会先在对象自身上找,找到就直接返回,如果找不到,会到原型上找,如果还是找不到,就会去原型的原型上找,最终会到最顶层的Object.prototype上找,还是找不到就会返回undefined。

# 什么是constructor?

prototype原型对象都有一个constructor属性,默认指向prototype对象所在的构造函数。

# 什么是包装对象?

包装对象指的是将原始类型(数字、字符串、布尔值)进行实例化。

# 二、数据类型的转换

# 1、强制(手动)转换

强制转换主要指使用Number()、String()和Boolean()三个函数,手动将各种类型的值,分别转换成数字、字符串、布尔值。

# Number()

// 数值:转换后还是原来的值
Number(324) // 324

// 字符串:如果可以被解析为数值,则转换为相应的数值
Number('324') // 324

// 字符串:如果不可以被解析为数值,返回 NaN
Number('324abc') // NaN

// 空字符串转为0
Number('') // 0

// 布尔值:true 转成 1,false 转成 0
Number(true) // 1
Number(false) // 0

// undefined:转成 NaN
Number(undefined) // NaN

// null:转成0
Number(null) // 0

Number({a: 1}) // NaN
Number([1, 2, 3]) // NaN
Number([5]) // 5
Number([]) // 0

//使用parseInt()转数组
parseInt([1, 2, 3]) // 1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

# String()

// 原始类型的转换
String(123) // "123"
String('abc') // "abc"
String(true) // "true"
String(undefined) // "undefined"
String(null) // "null"

// 对象的转换
String({a: 1}) // "[object Object]"
String([1, 2, 3]) // "1,2,3"
String([]) // ""  空字符串
String(function(){}) // "function(){}"
1
2
3
4
5
6
7
8
9
10
11
12

# Boolean()

// 除了这五个为false,其他都为true
Boolean(undefined) // false
Boolean(null) // false
Boolean(0) // false
Boolean(NaN) // false
Boolean('') // false

//true
Boolean({}) // true
Boolean([]) // true
Boolean(new Boolean(false)) // true

Boolean(1) // true
Boolean(' ') // true // 注意字符串内有个空格
1
2
3
4
5
6
7
8
9
10
11
12
13
14

# 2、自动转换

下面介绍自动转换,它是以强制转换为基础的。

遇到以下三种情况时,JavaScript 会自动转换数据类型,即转换是自动完成的,用户不可见。

第一种情况,不同类型的数据互相运算。

123 + 'abc' // "123abc"
1

第二种情况,对非布尔值类型的数据求布尔值。

if ('abc') {
  console.log('hello')
}  // "hello"
1
2
3

第三种情况,对非数值类型的值使用一元运算符(即+和-)。

+ {foo: 'bar'} // NaN
- [1, 2, 3] // NaN
1
2

自动转换的规则是这样的:预期什么类型的值,就调用该类型的转换函数。比如,某个位置预期为字符串,就调用String函数进行转换。如果该位置即可以是字符串,也可能是数值,那么默认转为数值。

由于自动转换具有不确定性,而且不易除错,建议在预期为布尔值、数值、字符串的地方,全部使用Boolean、Number和String函数进行显式转换。

# 自动转换为布尔值(Boolean)

JavaScript 遇到预期为布尔值的地方(比如if语句的条件部分),就会将非布尔值的参数自动转换为布尔值。系统内部会自动调用Boolean函数。

因此除了以下五个值,其他都是自动转为true。

  • undefined
  • null
  • +0或-0
  • NaN
  • ''(空字符串)

下面这个例子中,条件部分的每个值都相当于false,使用否定运算符后,就变成了true。

if ( !undefined
  && !null
  && !0
  && !NaN
  && !''
) {
  console.log('true');
} // true
1
2
3
4
5
6
7
8

下面两种写法,有时也用于将一个表达式转为布尔值。它们内部调用的也是Boolean函数。

// 三元运算符
expression ? true : false

// 取反运算符
!! expression
1
2
3
4
5

# 自动转换为字符串(String)

JavaScript 遇到预期为字符串的地方,就会将非字符串的值自动转为字符串。具体规则是,先将复合类型的值转为原始类型的值,再将原始类型的值转为字符串。

字符串的自动转换,主要发生在字符串的加法运算时。当一个值为字符串,另一个值为非字符串,则后者转为字符串。

# 所有类型的值与字符串相加都会变成字符串
'5' + 1 // '51'
 1  + '5' // '15'
'5' + true // "5true"
'5' + false // "5false"
'5' + {} // "5[object Object]"
 5 + {} // "5[object Object]"
'5' + [] // "5"
 5 + [] // "5"
'5' + function (){} // "5function (){}"
'5' + undefined // "5undefined"
'5' + null // "5null"
1
2
3
4
5
6
7
8
9
10
11
#

这种自动转换不注意的话很容易出错。

var obj = {
  width: '100'
};

obj.width + 20 // "10020"
parerInt(obj.width) + 20 // 120
1
2
3
4
5
6

上面代码中,开发者可能期望返回120,但是由于自动转换,实际上返回了一个字符10020。正确做法是先把字符串转成数字。

# 自动转换为数值(Number)

JavaScript 遇到预期为数值的地方,就会将参数值自动转换为数值。系统内部会自动调用Number函数。

# 除加号与字符串运行会转成字符串外,其他运行基本都会自动转成数值
'5' - '2' // 3
'5' * '2' // 10
true - 1  // 0
false - 1 // -1
'1' - 1   // 0
'5' * []    // 0
false / '5' // 0
'abc' - 1   // NaN
null + 1 // 1
undefined + 1 // NaN

true+true // 2
1
2
3
4
5
6
7
8
9
10
11
12

上面代码中,运算符两侧的运算子,都被转成了数值。

注意:null转为数值时为0,而undefined转为数值时为NaN。

数值与布尔值、null也会转为数值

5+true // 6
5+false // 5
5+null //5
1
2
3

一元运算符也会把运算子转成数值。

+'abc' // NaN
-'abc' // NaN
+true // 1
-false // 0
1
2
3
4

# 三、错误处理机制

# 1、Error实例对象

JavaScript 解析或运行时,一旦发生错误,引擎就会抛出一个错误对象。JavaScript 原生提供Error构造函数,所有抛出的错误都是这个构造函数的实例。

var err = new Error('出错了');
err.message // "出错了"
1
2

上面代码中,我们调用Error构造函数,生成一个实例对象err。Error构造函数接受一个参数,表示错误提示,可以从实例的message属性读到这个参数。抛出Error实例对象以后,整个程序就中断在发生错误的地方,不再往下执行。

JavaScript 语言标准只提到,Error实例对象必须有message属性,表示出错时的提示信息,没有提到其他属性。大多数 JavaScript 引擎,对Error实例还提供name和stack属性,分别表示错误的名称和错误的堆栈,但它们是非标准的,不是每种实现都有。

  • message:错误提示信息
  • name:错误名称(非标准属性)
  • stack:错误的堆栈(非标准属性)

使用name和message这两个属性,可以对发生什么错误有一个大概的了解。

var err = new Error('出错了');
if (err.name) {
  console.log(err.name + ': ' + err.message); // Error: 出错了
}
1
2
3
4

stack属性用来查看错误发生时的堆栈。

function throwit() {
  throw new Error('');
}

function catchit() {
  try {
    throwit();
  } catch(e) {
    console.log(e.stack); // print stack trace
  }
}

catchit()
// Error
//    at throwit (~/examples/throwcatch.js:9:11) // 堆栈的最内层throwit函数
//    at catchit (~/examples/throwcatch.js:3:9) // 向外一层catchit函数
//    at repl:1:5 // 函数的运行环境


// 堆栈信息说明
// Error 错误
//    at throwit 在throwit方法 (~/examples/throwcatch.js:9:11) 文件名:第几行:第几个字符
//    at catchit 在catchit方法 (~/examples/throwcatch.js:3:9) 文件名:第几行:第几个字符
//    at repl:1:5 // 函数的运行环境
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

上面代码中,错误堆栈的最内层是throwit函数,然后是catchit函数,最后是函数的运行环境。

# 2、原生错误类型

Error实例对象是最一般的错误类型,在它的基础上,JavaScript 还定义了其他6种错误对象。也就是说,存在Error的6个派生对象。

# SyntaxError 对象(语法错误)

SyntaxError对象是解析代码时发生的语法错误。

// 变量名错误
var 1a;
// Uncaught SyntaxError: Invalid or unexpected token
// 语法错误:无效或意外的标记符号

// 缺少括号
console.log 'hello');
// Uncaught SyntaxError: Unexpected string
// 语法错误:意外的字符串
1
2
3
4
5
6
7
8
9

上面代码的错误,都是在语法解析阶段就可以发现,所以会抛出SyntaxError。第一个错误提示是“token 非法”,第二个错误提示是“字符串不符合要求”。

# ReferenceError 对象(引用错误)

ReferenceError对象是引用一个不存在的变量时发生的错误。

// 使用一个不存在的变量
unknownVariable
// Uncaught ReferenceError: unknownVariable is not defined
// 引用错误: unknownVariable 没有定义
1
2
3
4

另一种触发场景是,将一个值分配给无法分配的对象,比如对函数的运行结果或者this赋值。

// 等号左侧不是变量
console.log() = 1
// Uncaught ReferenceError: Invalid left-hand side in assignment
// 引用错误: 赋值中左边是无效的

// this 对象不能手动赋值
this = 1
// ReferenceError: Invalid left-hand side in assignment
// 引用错误:  赋值中左边是无效的
1
2
3
4
5
6
7
8
9

上面代码对函数console.log的运行结果和this赋值,结果都引发了ReferenceError错误。

# RangeError 对象(范围错误)

RangeError对象是一个值超出有效范围时发生的错误。主要有几种情况,一是数组长度为负数,二是Number对象的方法参数超出范围,以及函数堆栈超过最大值。

// 数组长度不得为负数
new Array(-1)
// Uncaught RangeError: Invalid array length
// 范围错误:无效的数组长度
1
2
3
4

# TypeError 对象(类型错误)

TypeError对象是变量或参数不是预期类型时发生的错误。比如,对字符串、布尔值、数值等原始类型的值使用new命令,就会抛出这种错误,因为new命令的参数应该是一个构造函数。

new 123
// Uncaught TypeError: number is not a function
// 类型错误: 数字不是一个函数

var obj = {};
obj.unknownMethod()
// Uncaught TypeError: obj.unknownMethod is not a function
// 类型错误:obj.unknownMethod 不是一个函数
1
2
3
4
5
6
7
8

上面代码的第二种情况,调用对象不存在的方法,也会抛出TypeError错误,因为obj.unknownMethod的值是undefined,而不是一个函数。

# URIError 对象 (URI错误)

URIError对象是 URI 相关函数的参数不正确时抛出的错误,主要涉及encodeURI()、decodeURI()、encodeURIComponent()、decodeURIComponent()、escape()和unescape()这六个函数。

decodeURI('%2')
// URIError: URI malformed
1
2

# EvalError 对象 (eval错误)

eval函数没有被正确执行时,会抛出EvalError错误。该错误类型已经不再使用了,只是为了保证与以前代码兼容,才继续保留。

# 总结(开发者手动使用)

以上这6种派生错误,连同原始的Error对象,都是构造函数。开发者可以使用它们,手动生成错误对象的实例。这些构造函数都接受一个参数,代表错误提示信息(message)。

var err1 = new Error('出错了!');
var err2 = new RangeError('出错了,变量超出有效范围!');
var err3 = new TypeError('出错了,变量类型无效!');

err1.message // "出错了!"
err2.message // "出错了,变量超出有效范围!"
err3.message // "出错了,变量类型无效!"
1
2
3
4
5
6
7

# 3、自定义错误

除了 JavaScript 原生提供的七种错误对象,还可以定义自己的错误对象。

function UserError(message) {
  this.message = message || '默认信息';
  this.name = 'UserError';
}

UserError.prototype = new Error(); // 原型继承 Error对象
UserError.prototype.constructor = UserError;

// 使用
new UserError('这是自定义的错误!');
1
2
3
4
5
6
7
8
9
10

上面代码自定义一个错误对象UserError,让它继承Error对象。然后,就可以生成这种自定义类型的错误了。

# 4、throw 语句 (中断程序并抛出错误)

throw语句的作用是手动中断程序执行,抛出一个错误。

var x = 0;
if (x <= 0) {
  throw new Error('x 必须为正数');
}
// Uncaught Error: x 必须为正数
1
2
3
4
5

上面代码中,如果变量x小于等于0,就手动抛出一个错误,告诉用户x的值不正确,整个程序就会在这里中断执行。可以看到,throw抛出的错误就是它的参数,这里是一个Error实例。

function UserError(message) {
  this.message = message || '默认信息';
  this.name = 'UserError';
}

throw new UserError('出错了!');
// Uncaught UserError {message: "出错了!", name: "UserError"}
1
2
3
4
5
6
7

上面代码中,throw抛出的是一个UserError实例。

实际上,throw可以抛出任何类型的值。也就是说,它的参数可以是任何值。

// 抛出一个字符串
throw 'Error!';
// Uncaught Error!

// 抛出一个数值
throw 42;
// Uncaught 42

// 抛出一个布尔值
throw true;
// Uncaught true

// 抛出一个对象
throw {
  toString: function () {
    return 'Error!';
  }
};
// Uncaught {toString: ƒ}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

对于 JavaScript 引擎来说,遇到throw语句,程序就中止了。引擎会接收到throw抛出的信息,可能是一个错误实例,也可能是其他类型的值。

# 5、try...catch 结构(捕获错误,对错误进行处理,不中断)

一旦发生错误,程序就中止执行了。JavaScript 提供了try...catch结构,允许对错误进行处理,选择是否往下执行。

try {
  throw new Error('出错了!');
} catch (e) {
  console.log(e.name + ": " + e.message);
  console.log(e.stack);
}
// Error: 出错了!
//   at <anonymous>:3:9
//   ...
1
2
3
4
5
6
7
8
9

上面代码中,try代码块抛出错误(上例用的是throw语句),JavaScript 引擎就立即把代码的执行,转到catch代码块,或者说错误被catch代码块捕获了。catch接受一个参数,表示try代码块抛出的值。

如果你不确定某些代码是否会报错,就可以把它们放在try...catch代码块之中,便于进一步对错误进行处理。

try {
  f();
} catch(e) {
  // 处理错误
}
1
2
3
4
5

上面代码中,如果函数f执行报错,就会进行catch代码块,接着对错误进行处理。

catch代码块捕获错误之后,程序不会中断,会按照正常流程继续执行下去。

try {
  throw "出错了";
} catch (e) {
  console.log(111);
}
console.log(222);
// 111
// 222
1
2
3
4
5
6
7
8

上面代码中,try代码块抛出的错误,被catch代码块捕获后,程序会继续向下执行。

catch代码块之中,还可以再抛出错误,甚至使用嵌套的try...catch结构。

var n = 100;

try {
  throw n;
} catch (e) {
  if (e <= 50) {
    // ...
  } else {
    throw e;
  }
}
// Uncaught 100
1
2
3
4
5
6
7
8
9
10
11
12

上面代码中,catch代码之中又抛出了一个错误。

为了捕捉不同类型的错误,catch代码块之中可以加入判断语句。

try {
  foo.bar();
} catch (e) {
  if (e instanceof EvalError) {
    console.log(e.name + ": " + e.message);
  } else if (e instanceof RangeError) {
    console.log(e.name + ": " + e.message);
  }
  // ...
}
1
2
3
4
5
6
7
8
9
10

上面代码中,catch捕获错误之后,会判断错误类型(EvalError还是RangeError),进行不同的处理。

# 6、finally 代码块(在try..catch最后,必执行的)

try...catch结构允许在最后添加一个finally代码块,表示不管是否出现错误,都必需在最后运行的语句。

function cleansUp() {
  try {
    throw new Error('出错了……');
    console.log('此行不会执行');
  } finally { // 不管有没有出错都会执行finally
    console.log('完成清理工作');
  }
  console.log('此行不会执行');
}

cleansUp()
// 完成清理工作
// Uncaught Error: 出错了……
//    at cleansUp (<anonymous>:3:11)
//    at <anonymous>:10:1

// 由于没有catch语句,所以会打印出错误信息,并中断除finally以外的代码。
// 如果有catch语句则会执行catch内的代码块,而不会打印错误信息。且不会中断代码。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

上面代码中,由于没有catch语句块,一旦发生错误,代码就会中断执行。中断执行之前,会先执行finally代码块,然后再向用户提示报错信息。

function idle(x) {
  try {
    console.log(x);
    return 'result';
  } finally {
    console.log('FINALLY');
  }
}

idle('hello')
// hello
// FINALLY
1
2
3
4
5
6
7
8
9
10
11
12

上面代码中,try代码块没有发生错误,而且里面还包括return语句,但是finally代码块依然会执行。而且,这个函数的返回值还是result。

下面的例子说明,return语句的执行是排在finally代码之前,只是等finally代码执行完毕后才返回。

var count = 0;
function countUp() {
  try {
    return count;
  } finally {
    count++;
  }
}

countUp()
// 0
count
// 1
1
2
3
4
5
6
7
8
9
10
11
12
13

上面代码说明,return语句里面的count的值,是在finally代码块运行之前就获取了。

下面是finally代码块用法的典型场景。

openFile(); // 打开文件

try {
  writeFile(Data); // 写入文件
} catch(e) {
  handleError(e); // 如果写入出错这处理错误
} finally {
  closeFile();// 不管是否出错都会执行关闭文件
}
1
2
3
4
5
6
7
8
9

上面代码首先打开一个文件,然后在try代码块中写入文件,如果没有发生错误,则运行finally代码块关闭文件;一旦发生错误,则先使用catch代码块处理错误,再使用finally代码块关闭文件。

下面的例子充分反映了try...catch...finally这三者之间的执行顺序。

function f() {
  try {
    console.log(0);
    throw 'bug';
  } catch(e) {
    console.log(1);
    return true; // 这句原本会延迟到 finally 代码块结束再执行
    console.log(2); // 不会运行
  } finally {
    console.log(3);
    return false; // 这句会覆盖掉前面那句 return
    console.log(4); // 不会运行
  }

  console.log(5); // 不会运行
}

var result = f();
// 0
// 1
// 3

result
// false
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

上面代码中,catch代码块结束执行之前,会先执行finally代码块。

catch代码块之中,触发转入finally代码块的标志,不仅有return语句,还有throw语句。

function f() {
  try {
    throw '出错了!';
  } catch(e) {
    console.log('捕捉到内部错误');
    throw e; // 这句原本会等到finally结束再执行
  } finally {
    return false; // 直接返回
  }
}

try {
  f(); // 接收到返回值false,并没有接收到错误
} catch(e) {
  // 此处不会执行
  console.log('caught outer "bogus"');
}

//  捕捉到内部错误
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

上面代码中,进入catch代码块之后,一遇到throw语句,就会去执行finally代码块,其中有return false语句,因此就直接返回了,不再会回去执行catch代码块剩下的部分了。

try代码块内部,还可以再使用try代码块。

try {
  try {
    consle.log('Hello world!'); // 报错,console拼错
  }
  finally {
    console.log('Finally');
  }
  console.log('Will I run?');
} catch(error) {
  console.error(error.message);
}
// Finally
// consle is not defined
1
2
3
4
5
6
7
8
9
10
11
12
13

上面代码中,try里面还有一个try。内层的try报错(console拼错了),这时会执行内层的finally代码块,然后抛出错误,被外层的catch捕获。

# 四、console对象

# console.time(),console.timeEnd() (用于计算程序的用时)

这两个方法用于计时,可以算出一个操作所花费的准确时间。

console.time('Array initialize');

var array= new Array(1000000);
for (var i = array.length - 1; i >= 0; i--) {
  array[i] = new Object();
};

console.timeEnd('Array initialize');
// Array initialize: 1914.481ms
1
2
3
4
5
6
7
8
9

time方法表示计时开始,timeEnd方法表示计时结束。它们的参数是计时器的名称。调用timeEnd方法之后,控制台会显示“计时器名称: 所耗费的时间”。

# 文档

学习文档:https://wangdoc.com/javascript/ (opens new window)

编辑 (opens new window)
作用域
定时器

← 作用域 定时器→

最近更新
01
theme-vdoing-blog博客静态编译问题
09-16
02
搜索引擎
07-19
03
友情链接
07-19
更多文章>
Theme by Vdoing | Copyright © 2019-2025 Evan Xu | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式
  • 主题模式