首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >重学JS基础-词法和语法

重学JS基础-词法和语法

作者头像
Jou
发布2022-08-10 20:56:39
发布2022-08-10 20:56:39
1.4K00
代码可运行
举报
文章被收录于专栏:前端技术归纳前端技术归纳
运行总次数:0
代码可运行

1.JS的词法定义

JavaScript 源代码中的输入可以这样分类:

  • WhiteSpace 空白字符
  • LineTerminator 换行符
  • Comment 注释
  • Token 词
    • IdentifierName 标识符名称,典型案例是我们使用的变量名,注意这里关键字也包含在内了。
    • Punctuator 符号,我们使用的运算符和大括号等符号。
    • NumericLiteral 数字直接量,就是我们写的数字。
    • StringLiteral 字符串直接量,就是我们用单引号或者双引号引起来的直接量。
    • Template 字符串模板,用反引号` 括起来的直接量。
空白字符
  • (或称) 是 U+0009,是缩进 TAB 符,也就是字符串中写的 \t
  • 是 U+000B,也就是垂直方向的 TAB 符
  • 是 U+0020,就是最普通的空格了。
  • 是 U+00A0,非断行空格,在文字排版中,可以避免因为空格在此处发生断行,其它方面和普通空格完全一样。多数的 JavaScript 编辑环境都会把它当做普通空格(。HTML 中,很多人喜欢用的 最后生成的就是它了。
  • (旧称) 是 U+FEFF,这是 ES5 新加入的空白符,是 Unicode 中的零宽非断行空格,即字符的length长度为0
换行符
  • 是 U+000A,就是最正常换行符,在字符串中的\n。
  • 是 U+000D,这个字符真正意义上的“回车”,在字符串中是\r,在一部分 Windows 风格文本编辑器中,换行是两个字符\r\n。
标识符名称

注意和是 ES5 新加入的两个格式控制字符,它们都是 0 宽的。即length长度为0,也称为0宽非连接符和0宽连接符

数字直接量

十进制的 Number 可以带小数,小数点前后部分都可以省略,但是不能同时省略

代码语言:javascript
代码运行次数:0
运行
复制
.01
12.
12.01

以上的写法都是正确的,所以来看下一个问题

代码语言:javascript
代码运行次数:0
运行
复制
12.toString()

这个句代码在运行时会报错,因为12.会被看成一个带小数的整体。

正确的写法应该是

代码语言:javascript
代码运行次数:0
运行
复制
12..toString()

12 .toString()

(12).toString()

数字还支持科学计数法,注意E和e后面只能接整数

代码语言:javascript
代码运行次数:0
运行
复制
10.24E+2
10.24e-2
10.24e2

2.JS的语法定义

语法规则:分号自动补全

JS有一个no LineTerminator here 规则 :表示所在结构的此处不能插入换行符,假如此处插入了换行符,那么系统在编译的时候会自动补上分号

带换行的注释会被认为是换行符,系统会默认加上分号,所以返回undefined,下面看几个例子

代码语言:javascript
代码运行次数:0
运行
复制
function f(){
return/*
    This is a return value.
*/1;
}
f();

上面得方法将返回undefined,因为return后面会自动补全一个分号。

代码语言:javascript
代码运行次数:0
运行
复制
var a = 1, b = 1, c = 1;
a
++
b
++
c	

a,b,c后面会被加上分号,所以a还是为1,bc都为2

代码语言:javascript
代码运行次数:0
运行
复制
(function(){
console.log("a");
})()
(function(){
console.log("b");
})()

这里会报错 ,因为不会默认加分号 ,第三组括号会被理解成传参。

代码语言:javascript
代码运行次数:0
运行
复制
var a = [[]]/*这里没有被自动插入分号*/
[3, 2, 1, 0].forEach(e => console.log(e))

这里本来原本是想遍历数组,但是由于上面没有添加分号,并且不会自动补全分号,所以后面得数组变成得前面数组得下标和逗号表达式。

代码语言:javascript
代码运行次数:0
运行
复制
var x = 1, g = { test: () => 0 }, b = 1/*这里没有被自动插入分号*/
    / (a) / g.test("abc")
console.log(RegExp.$1)

这里由于没有自动补全分号,所以正则表达式得意思全部变了

总之不写分号可能会有问题,写分号一定没问题

语法规则:脚本和模块

脚本是可以由浏览器或者 node 环境引入执行的,而模块只能由 JavaScript 代码用 import 引入执行。

现代浏览器可以支持用 script 标签引入模块或者脚本,如果要引入模块,必须给 script 标签添加 type=“module”。如果引入脚本,则不需要 type。

3.JS语句的分类

  • 普通语句:声明语句,表达式语句,空语句,debugger语句等
  • 控制型语句:if,try,while等
  • 带标签的语句:在JS语句前加上标签(比如: "inner:" ),用于跳转
  • 语句块:用大括号括起来的一组语句
JS语句执行机制

Completion Record( 用于描述异常、跳出等语句执行过程)。

Completion Record 表示一个语句执行完之后的结果,它有三个字段:

  • [[type]] 表示完成的类型,有 break continue return throw 和 normal 几种类型;
  • [[value]] 表示语句的返回值,如果语句没有,则是 empty;
  • [[target]] 表示语句的目标,通常是一个 JavaScript 标签
普通语句的执行

普通语句执行后,会得到 [[type]] 为 normal 的 Completion Record,JavaScript 引擎遇到这样的 Completion Record,会继续执行下一条语句。

这些语句中,只有表达式语句会产生 [[value]],当然,从引擎控制的角度,这个 value 并没有什么用处。

如果你经常使用 Chrome 自带的调试工具,可以知道,输入一个表达式,在控制台可以得到结果,但是在前面加上 var,就变成了 undefined,因为语句从表达式语句变成了声明语句。

Chrome 控制台显示的正是语句的 Completion Record 的[[value]]。

语句块

语句块本身并不复杂,我们需要注意的是语句块内部的语句的 Completion Record 的[[type]] 如果不为 normal,会打断语句块后续的语句执行。

假如我们在正常 block 中插入了一条 return 语句,产生了一个非 normal 记录,那么整个 block 会成为非 normal。这个结构就保证了非 normal 的完成类型可以穿透复杂的语句嵌套结构,产生控制效果。

最简单的例子就是函数中的语句执行道return之后就不会再往后继续执行。

控制语句

控制类语句分成两部分

  • 一类是对其内部造成影响,如 if、switch、while/for、try。
  • 一类是对外部造成影响如break、continue、return、throw,这两类语句的配合,会产生控制代码执行顺序和执行逻辑的效果,这也是我们编程的主要工作。

一般来说, for/while - break/continue 和 try - throw 这样比较符合逻辑的组合,是大家比较熟悉的,但是,实际上,我们需要控制语句跟 break 、continue 、return 、throw 四种类型与控制语句两两组合产生的效果。

一个例子
代码语言:javascript
代码运行次数:0
运行
复制
function foo(){
  try{
    return 0;
  } catch(err) {

  } finally {
    console.log("a")
  }
}

console.log(foo());

这里会在执行完finally之后再返回0,就是因为reutn会让try变成非normal的类型,但是也必须执行finally

或者:把try.catch.finally看做整体,会返回一个completion record, try return 0, finally console, 则输出console,接着返回这个completion record的vlaue。

在finally中也return一次

代码语言:javascript
代码运行次数:0
运行
复制
function foo(){
  try{
    return 0;
  } catch(err) {

  } finally {
    return 1;
  }
}

console.log(foo());

最终答案会输出1,因为finally 执行也得到了非 normal 记录,则会使 finally 中的记录作为整个 try 结构的结果。

3.表达式语句

普通的表达式规则这里就不再赘述,主要列出几个比较特殊的。

乘方表达式
代码语言:javascript
代码运行次数:0
运行
复制
++i ** 30
2 ** 30 //正确
-2 ** 30 //报错

这里我们需要注意一下结合性,** 运算是右结合的,这跟其它正常的运算符(也就是左结合运算符)都不一样。

代码语言:javascript
代码运行次数:0
运行
复制
10 ** 20 **30
//相当于 10 ** (20 ** 30)
移位表达式

移位表达式由加法表达式构成,移位是一种位运算,分成三种:

  • :<< 向左移位
  • :>> 向右移位
  • :>>> 无符号向右移位

移位运算把操作数看做二进制表示的整数,然后移动特定位数。

所以左移 n 位相当于乘以 2 的 n 次方,右移 n 位相当于除以2取整次。

普通移位会保持正负数。无符号移位会把减号视为符号位 1,同时参与移位:-1 >>> 1这个会得到 2147483647,也就是 2 的 31 次方,跟负数的二进制表示法相关(复数的二进制使用补码表示)。在 JavaScript 中,二进制操作整数并不能提高性能

位运算表达式

按位与表达式 & :

按位与表达式把操作数视为二进制整数,然后把两个操作数按位做与运算。

代码语言:javascript
代码运行次数:0
运行
复制
10 & 3 = 2
10 & 5 = 0

按位异或 ^ :

按位异或表达式把操作数视为二进制整数,然后把两个操作数按位做异或运算。异或两位相同时得 0,两位不同时得 1。

代码语言:javascript
代码运行次数:0
运行
复制
10 & 3 = 9
10 & 5 = 15
文章参考:极客时间-重学前端
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2021-07-28,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1.JS的词法定义
    • 空白字符
    • 换行符
    • 标识符名称
    • 数字直接量
  • 2.JS的语法定义
    • 语法规则:分号自动补全
    • 语法规则:脚本和模块
  • 3.JS语句的分类
    • JS语句执行机制
    • 普通语句的执行
    • 语句块
    • 控制语句
    • 一个例子
  • 3.表达式语句
    • 乘方表达式
    • 移位表达式
    • 位运算表达式
    • 文章参考:极客时间-重学前端
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档