0


图解JS你必须拿捏的名词【很长哦】

📜个人简介

⭐个人主页:龙哥手记 🙋
🍑博客领域:编程基础,Java
🍎写作风格:干货,干货,还是tmd的干货
🌸精选专栏:【图解JavaScript】
🚀支持龙哥:点赞 👍,收藏 ⭐,留言 📪

好久不见,甚是想念!
大家好!我是龙哥
芜湖,起飞🚀

开始之前

先送你一朵小红花吧哈哈

在这里插入图片描述

脉络如下

🏆 一 必须拿捏的名词

什么是作用域?

变量存在的范围。

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

不要怕举例子

  1. var color ='blue';functionchangeColor(){if(color ==="blue"){
  2. color ="red";}else{
  3. color ="blue";}}changeColor();alert("Color is now "+ color);

在这个简单的例子中,函数 changeColor() 的作用域包含两个对象:它

  1. 自己的变量对象

(里面定义着 arguments 对象)和

  1. 全局环境的变量对象

。可以在函数内部去访问变量 color, 就是因为可以它在这个作用域链上能够去找到它。

1
此外,

  1. 局部作用域中定义的变量

可以在局部环境与

  1. 全局变量

互换来用,如下面这个例子这样

  1. var color ="blue";functionchangeColor(){var anotherColor ="red";functionswapColors(){var tempColor = anotherColor;
  2. anotherColor = color;
  3. color = tempColor;//这里访问 color, anotherColor 和 tempColor}//这里可以访问 color 和 anotherColor, 但不能访问 tempColor swapColors();}// 这里只能访问 colorchangeColor();

下图的矩形代表特定的执行环境。其中,内部环境可以用作用域链访问所有的外部环境,但外部环境它不能访问内部环境中的任何变量和函数。

  1. 说白了环境之间的联系是顺序的哈

。每个环境都可以向上搜索作用域链,来查询变量和函数名;但任何环境都不能通过向下搜索作用域链而进入另一个执行环境,这是万万不可以的哈。
在这里插入图片描述
对于这个例子中的 swapColors()来说,其作用域链中包含 3 个对象

  • swapColors()的变量对象
  • changeColor()的变量对象
  • 全局变量对象

swapColors() 的局部环境开始时候会先在自己的变量对象里面去搜变量和函数名,如果搜不到则再搜上一级作用域链。也就是 changeColor()的作用域链。

changeColor() 里面只有两个对象:它自己的变量对象和全局变量对象。这也就是说,

  1. 前面说过环境之间是有顺序的,它不能访问 swapColors() 的环境

什么是闭包?

能够

  1. 读取其他函数内部变量的函数

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

有啥用:

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

还是整个例子想

我们在一个函数内部创建

  1. createComparisonFunction()

为例,请你注意注释的两行的代码。

  1. functioncreateComperisonFunction(propertyName){returnfunction(object1, object2){var value1 = object1[propertyName];//注释var value2 = object2[propertyName];//注释if(value1 < value2){return-1;}elseif(value1 > value2){return1;}else{return0;}};}

在这个例子里面,我注释的那两行是内部函数的代码,而且仔细看它还是一个匿名函数是吧。明显函数中的变量是propertyName。及时这个内部行数被返回了,在其他地方可以访问变量 propertyName, 之所以能够访问这个变量,是因为内部函数的作用域链中包含createComparisonFunction()的作用域。

闭包只能取得包含函数中任何变量的最后一个值。别忘了

  1. 闭包所保存的是整个变量对象,而不是某个特殊的变量

示意图看下
在这里插入图片描述

由于闭包会携带包含它的函数的作用域,因此会比其他函数占用更多的内存。过度使用闭包可能会导致内存占用过多,我们建议读者只在绝对必要时再考虑使用闭包。

什么是构造函数?

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

其实可以把构造函数当作函数

构造函数与其他函数的唯一区别,就在于调用它们的方式不同。不过,构造函数它毕竟也是函数,不
存在定义构造函数的特殊语法。

  1. 任何函数,只要通过 new 操作符来调用,那它就可以作为构造函数;而 任何函数,如果不通过 new 操作符来调用,那它跟普通函数也不会有什么两样


在这里插入图片描述

例如,前面例子中定义的 Person()函数可以通过下列任何一种方式来调用。

  1. // 当作构造函数使用var person =newPerson("Nicholas",29,"Software Engineer");
  2. person.sayName();//"Nicholas" // 作为普通函数调用Person("Greg",27,"Doctor");// 添加到 window
  3. window.sayName();//"Greg" // 在另一个对象的作用域中调用var o =newObject();
  4. Person.call(o,"Kristen",25,"Nurse");
  5. o.sayName();//"Kristen"

这个例子中的前两行代码展示了构造函数的典型用法,即使用 new 操作符来创建一个新对象。接下来的两行代码展示了不使用new操作符调用Person()会出现什么结果:属性和方法都被添加给window对象了。

有读者可能还记得,当在全局作用域中调用一个函数时,this 对象总是指向 Global 对象(在浏览器中就是 window 对象)。因此,在调用完函数之后,可以通过 window 对象来调用 sayName()方法,并且还返回了"Greg"。最后,也可以使用 call()(或者 apply())在某个特殊对象的作用域中调用Person()函数。这里是在对象o 的作用域中调用的,因此调用后o 就拥有了所有属性和sayName()方法。

什么是实例对象?

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

什么是this?

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

什么是原型?

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

什么是原型链?

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

最顶层的原型是Object.prototype。

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

什么是constructor?

prototype原型对象都有一个constructor属性,默认指向prototype对象所在的构造函数。
2
RegExp 构造函数包含一些属性(这些属性在其他语言中被看成是静态属性),而

  1. 这些属性就是constructor属性,它适用于作用 域中的所有正则表达式,并且基于所执行的最近一次正则表达式操作而变化

。关于这些属性的另一个独
特之处,就是可以通过两种方式访问它们。换句话说,这些属性分别有一个长属性名和一个短属性名(Opera 是例外,它不支持短属性名)。

什么是包装对象?

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

🎨 二 数据类型的转换

1、强制(手动)转换

强制转换主要指使用

  1. Number()

  1. String()

  1. Boolean()

三个函数,手动将各种类型的值,分别转换成数字、字符串、布尔值

Number()

  1. // 数值:转换后还是原来的值Number(324)// 324// 字符串:如果可以被解析为数值,则转换为相应的数值Number('324')// 324// 字符串:如果不可以被解析为数值,返回 NaNNumber('324abc')// NaN// 空字符串转为0Number('')// 0// 布尔值:true 转成 1,false 转成 0Number(true)// 1Number(false)// 0// undefined:转成 NaNNumber(undefined)// NaN// null:转成0Number(null)// 0Number({a:1})// NaNNumber([1,2,3])// NaNNumber([5])// 5Number([])// 0//使用parseInt()转数组parseInt([1,2,3])// 1

String()

  1. // 原始类型的转换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(){}"

Boolean()

  1. // 除了这五个为false,其他都为trueBoolean(undefined)// falseBoolean(null)// falseBoolean(0)// falseBoolean(NaN)// falseBoolean('')// false//trueBoolean({})// trueBoolean([])// trueBoolean(newBoolean(false))// trueBoolean(1)// trueBoolean(' ')// true // 注意字符串内有个空格

2、这是自动转换

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

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

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

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

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

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

第三种情况,**对非数值类型的值使用一元运算符(即

  1. +

  1. -

)**。

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

自动转换的规则是这样的

预期什么类型的值,就调用该类型的转换函数。比如,某个位置预期为字符串,就调用

  1. String

函数进行转换。如果该位置即可以是字符串,也可能是数值,那么默认转为数值。

由于自动转换具有不确定性,而且不易除错,建议在预期为布尔值、数值、字符串的地方,全部使用

  1. Boolean

  1. Number

  1. String

函数进行显式转换。

自动转换为布尔值(Boolean)

JavaScript 遇到预期为布尔值的地方(比如

  1. if

语句的条件部分),就会将非布尔值的参数自动转换为布尔值。系统内部会自动调用

  1. Boolean

函数。

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

  1. true

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

下面这个例子中,条件部分的每个值都相当于

  1. false

,使用否定运算符后,就变成了

  1. true

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

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

  1. Boolean

函数。

  1. // 三元运算符
  2. expression ?true:false// 取反运算符!! expression

自动转换为字符串(String)

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

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

在这里插入图片描述

所有类型的值与字符串相加都会变成字符串

  1. '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. var obj ={
  2. width:'100'};
  3. obj.width +20// "10020"parerInt(obj.width)+20// 120

上面代码中,开发者可能期望返回

  1. 120

,但是由于自动转换,实际上返回了一个字符

  1. 10020

。正确做法是先把字符串转成数字。

自动转换为数值(Number)

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

  1. Number

函数。

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

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

注意:

  1. null

转为数值时为

  1. 0

,而

  1. undefined

转为数值时为

  1. NaN

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

  1. 5+true// 65+false// 55+null//5

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

  1. +'abc'// NaN-'abc'// NaN+true// 1-false// 0

🛶 三 错误处理机制

1、Error实例对象

JavaScript 解析或运行时,一旦发生错误,引擎就会抛出一个错误对象。JavaScript 原生提供

  1. Error

构造函数,所有抛出的错误都是这个构造函数的实例。

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

上面代码中,我们调用

  1. Error

构造函数,生成一个实例对象

  1. err

  1. Error

构造函数接受一个参数,表示错误提示,可以从实例的

  1. message

属性读到这个参数。**抛出

  1. Error

实例对象以后,整个程序就中断在发生错误的地方,不再往下执行**。

JavaScript 语言标准只提到,

  1. Error

实例对象必须有

  1. message

属性,表示出错时的提示信息,没有提到其他属性。大多数 JavaScript 引擎,对

  1. Error

实例还提供

  1. name

  1. stack

属性,分别表示错误的名称和错误的堆栈,但它们是非标准的,不是每种实现都有。

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

使用

  1. name

  1. message

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

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

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

  1. functionthrowit(){thrownewError('');}functioncatchit(){try{throwit();}catch(e){
  2. 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. throwit

函数,然后是

  1. catchit

函数,最后是函数的运行环境。

2、原生错误类型

  1. Error

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

  1. Error

的6个派生对象。

SyntaxError 对象(语法错误)

  1. SyntaxError

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

  1. // 变量名错误var1a;// Uncaught SyntaxError: Invalid or unexpected token// 语法错误:无效或意外的标记符号// 缺少括号
  2. console.log 'hello');// Uncaught SyntaxError: Unexpected string// 语法错误:意外的字符串

上面代码的错误,都是在语法解析阶段就可以发现,所以会抛出

  1. SyntaxError

。第一个错误提示是“token 非法”,第二个错误提示是字符串不符合要求。
在这里插入图片描述

ReferenceError 对象(引用错误)

  1. ReferenceError

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

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

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

  1. this

赋值。

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

上面代码对函数

  1. console.log

的运行结果和

  1. this

赋值,结果都引发了

  1. ReferenceError

错误。

RangeError 对象(范围错误)

  1. RangeError

对象是一个值超出有效范围时发生的错误。主要有几种情况,一是数组长度为负数,二是

  1. Number

对象的方法参数超出范围,以及函数堆栈超过最大值。

  1. // 数组长度不得为负数newArray(-1)// Uncaught RangeError: Invalid array length// 范围错误:无效的数组长度

TypeError 对象(类型错误)

  1. TypeError

对象是变量或参数不是预期类型时发生的错误。比如,对字符串、布尔值、数值等原始类型的值使用

  1. new

命令,就会抛出这种错误,因为

  1. new

命令的参数应该是一个构造函数。

  1. new123// Uncaught TypeError: number is not a function// 类型错误: 数字不是一个函数var obj ={};
  2. obj.unknownMethod()// Uncaught TypeError: obj.unknownMethod is not a function// 类型错误:obj.unknownMethod 不是一个函数

上面代码的第二种情况,调用对象不存在的方法,也会抛出

  1. TypeError

错误,因为

  1. obj.unknownMethod

的值是

  1. undefined

,而不是一个函数。

URIError 对象 (URI错误)

  1. URIError

对象是 URI 相关函数的参数不正确时抛出的错误,主要涉及

  1. encodeURI()

  1. decodeURI()

  1. encodeURIComponent()

  1. decodeURIComponent()

  1. escape()

  1. unescape()

这六个函数。

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

EvalError 对象 (eval错误)

  1. eval

函数没有被正确执行时,会抛出

  1. EvalError

错误。该错误类型已经不再使用了,只是为了保证与以前代码兼容,才继续保留。

总结(开发者手动使用)

以上这6种派生错误,连同原始的

  1. Error

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

  1. var err1 =newError('出错了!');var err2 =newRangeError('出错了,变量超出有效范围!');var err3 =newTypeError('出错了,变量类型无效!');
  2. err1.message // "出错了!"
  3. err2.message // "出错了,变量超出有效范围!"
  4. err3.message // "出错了,变量类型无效!"

3、自定义错误

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

  1. functionUserError(message){this.message = message ||'默认信息';this.name ='UserError';}
  2. UserError.prototype =newError();// 原型继承 Error对象
  3. UserError.prototype.constructor = UserError;// 使用newUserError('这是自定义的错误!');

上面代码自定义一个错误对象

  1. UserError

,让它继承

  1. Error

对象。然后,就可以生成这种自定义类型的错误了。

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

  1. throw

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

  1. var x =0;if(x <=0){thrownewError('x 必须为正数');}// Uncaught Error: x 必须为正数

上面代码中,如果变量

  1. x

小于等于

  1. 0

,就手动抛出一个错误,告诉用户

  1. x

的值不正确,整个程序就会在这里中断执行。可以看到,

  1. throw

抛出的错误就是它的参数,这里是一个

  1. Error

实例。

  1. functionUserError(message){this.message = message ||'默认信息';this.name ='UserError';}thrownewUserError('出错了!');// Uncaught UserError {message: "出错了!", name: "UserError"}

上面代码中,

  1. throw

抛出的是一个

  1. UserError

实例。

实际上,

  1. throw

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

  1. // 抛出一个字符串throw'Error!';// Uncaught Error!// 抛出一个数值throw42;// Uncaught 42// 抛出一个布尔值throwtrue;// Uncaught true// 抛出一个对象throw{
  2. toString:function(){return'Error!';}};// Uncaught {toString: ƒ}

对于 JavaScript 引擎来说,**遇到

  1. throw

语句,程序就挂了。引擎会接收到

  1. throw

抛出的信息,可能是一个错误实例,也可能是其他类型的值。

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

一旦发生错误,程序就中止执行了。JavaScript 提供了

  1. try...catch

结构,允许对错误进行处理,选择是否往下执行。

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

上面代码中,

  1. try

代码块抛出错误(上例用的是

  1. throw

语句),JavaScript 引擎就立即把代码的执行,转到

  1. catch

代码块,或者说错误被

  1. catch

代码块捕获了。

  1. catch

接受一个参数,表示

  1. try

代码块抛出的值。

如果你不确定某些代码是否会报错,就可以把它们放在

  1. try...catch

代码块之中,便于进一步对错误进行处理。

  1. try{f();}catch(e){// 处理错误}

上面代码中,如果函数

  1. f

执行报错,就会进行

  1. catch

代码块,接着对错误进行处理。

  1. catch

代码块捕获错误之后,程序不会中断,会按照正常流程继续执行下去。
在这里插入图片描述

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

上面代码中,

  1. try

代码块抛出的错误,被

  1. catch

代码块捕获后,程序会继续向下执行。

  1. catch

代码块之中,还可以再抛出错误,甚至使用嵌套的

  1. try...catch

结构。

  1. var n =100;try{throw n;}catch(e){if(e <=50){// ...}else{throw e;}}// Uncaught 100

上面代码中,

  1. catch

代码之中又抛出了一个错误。

为了捕捉不同类型的错误

  1. catch

代码块之中可以加入判断语句。

  1. try{
  2. foo.bar();}catch(e){if(e instanceofEvalError){
  3. console.log(e.name +": "+ e.message);}elseif(e instanceofRangeError){
  4. console.log(e.name +": "+ e.message);}// ...}

上面代码中,

  1. catch

捕获错误之后,会判断错误类型(

  1. EvalError

还是

  1. RangeError

),进行不同的处理。

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

  1. try...catch

结构允许在最后添加一个

  1. finally

代码块,表示不管是否出现错误,都必需在最后运行的语句

  1. functioncleansUp(){try{thrownewError('出错了……');
  2. console.log('此行不会执行');}finally{// 不管有没有出错都会执行finally
  3. console.log('完成清理工作');}
  4. console.log('此行不会执行');}cleansUp()// 完成清理工作// Uncaught Error: 出错了…… // at cleansUp (<anonymous>:3:11)// at <anonymous>:10:1// 由于没有catch语句,所以会打印出错误信息,并中断除finally以外的代码。// 如果有catch语句则会执行catch内的代码块,而不会打印错误信息。且不会中断代码。

上面代码中,由于没有

  1. catch

语句块,一旦发生错误,代码就会中断执行。中断执行之前,会先执行

  1. finally

代码块,然后再向用户提示报错信息。

  1. functionidle(x){try{
  2. console.log(x);return'result';}finally{
  3. console.log('FINALLY');}}idle('hello')// hello// FINALLY

上面代码中,

  1. try

代码块没有发生错误,而且里面还包括

  1. return

语句,但是

  1. finally

代码块依然会执行。而且,这个函数的返回值还是

  1. result

下面的例子说明,

  1. return

语句的执行是排在

  1. finally

代码之前,只是等

  1. finally

代码执行完毕后才返回。

  1. var count =0;functioncountUp(){try{return count;}finally{
  2. count++;}}countUp()// 0
  3. count
  4. // 1

上面代码说明,

  1. return

语句里面的

  1. count

的值,是在

  1. finally

代码块运行之前就获取了。

下面是

  1. finally

代码块用法的典型场景

  1. openFile();// 打开文件try{writeFile(Data);// 写入文件}catch(e){handleError(e);// 如果写入出错这处理错误}finally{closeFile();// 不管是否出错都会执行关闭文件}

上面代码首先打开一个文件,然后在

  1. try

代码块中写入文件,如果没有发生错误,则运行

  1. finally

代码块关闭文件;一旦发生错误,则先使用

  1. catch

代码块处理错误,再使用

  1. finally

代码块关闭文件。

下面的例子充分反映了

  1. try...catch...finally

这三者之间的执行顺序

  1. functionf(){try{
  2. console.log(0);throw'bug';}catch(e){
  3. console.log(1);returntrue;// 这句原本会延迟到 finally 代码块结束再执行
  4. console.log(2);// 不会运行}finally{
  5. console.log(3);returnfalse;// 这句会覆盖掉前面那句 return
  6. console.log(4);// 不会运行}
  7. console.log(5);// 不会运行}var result =f();// 0// 1// 3
  8. result
  9. // false

上面代码中,

  1. catch

代码块结束执行之前,会先执行

  1. finally

代码块。

  1. catch

代码块之中,触发转入

  1. finally

代码块的标志,不仅有

  1. return

语句,还有

  1. throw

语句。

  1. functionf(){try{throw'出错了!';}catch(e){
  2. console.log('捕捉到内部错误');throw e;// 这句原本会等到finally结束再执行}finally{returnfalse;// 直接返回}}try{f();// 接收到返回值false,并没有接收到错误}catch(e){// 此处不会执行
  3. console.log('caught outer "bogus"');}// 捕捉到内部错误

上面代码中,进入

  1. catch

代码块之后,一遇到

  1. throw

语句,就会去执行

  1. finally

代码块,其中有

  1. return false

语句,因此就直接返回了,不再会回去执行

  1. catch

代码块剩下的部分了。

  1. try

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

  1. try

代码块。

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

上面代码中,

  1. try

里面还有一个

  1. try

。内层的

  1. try

报错(

  1. console

拼错了),这时会执行内层的

  1. finally

代码块,然后抛出错误,被外层的

  1. catch

捕获。

四、console对象

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

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

  1. console.time('Array initialize');
  2. var array= new Array(1000000);
  3. for (var i = array.length - 1; i >= 0; i--) {
  4. array[i] = new Object();
  5. };
  6. console.timeEnd('Array initialize');
  7. // Array initialize: 1914.481ms
  1. time

方法表示计时开始,

  1. timeEnd

方法表示计时结束。它们的参数是计时器的名称。调用

  1. timeEnd

方法之后,控制台会显示“计时器名称: 所耗费的时间”。

🎯 五 文档

更多干货请公众号:龙哥手记 点击「加群进阶」, 进龙歌唯一的读者群。
如果有错误或者不严谨的地方,请务必得出指正,非常感谢。如果喜欢或者 有所启发,欢迎star, 对作者也是一种鼓励。
跟着龙哥一起掉亿点点秀发吧~, `别忘给我点赞 大帅比大漂亮们再走啊!!!

专家讲了这个能长寿的😘

在这里插入图片描述

JS程序设计-读书笔记-第1天打卡-龙哥手记

记录来源于【JavaScript高级程序设计】第三版

标签: java jvm 后端

本文转载自: https://blog.csdn.net/weixin_45817252/article/details/123335175
版权归原作者 龙哥手记 所有, 如有侵权,请联系我们删除。

“图解JS你必须拿捏的名词【很长哦】”的评论:

还没有评论