语法

作者: 广州芦苇科技web前端 | 来源:发表于2018-12-14 23:29 被阅读0次

标签: 语法,语句,表达式,you don't know javascript


语句和表达式

  • “语句”和“表达式”在JavaScript中不同的两个概念。

var a = 3 * 6;
var b = a;
b;

表达式:

  1. 第一行 3 * 6
  2. 第二行 a
  3. 第三行 b

语句:
这三行代码叫做包含表达式的语句。

  • 第三行中只有一个表达式b,通常叫做“表达式语句”

语句的结果值

  • 语句都有一个结果值(statement completion value, undefined也算)。
  • 可以在浏览器控制台中输入语句,总是返回的是最后一条语句的结果值。
> var a = 30
< undefined

> a = 40
< 40
  • 声明语句的返回值是undefined。
  • 赋值语句返回的是被赋值变量赋值后的值。

{..}代码块的结果值

  • 代码块的结果值是最后一条语句的结果。
> {
    var b = 10;
    b = 20
  }
< 20
  • 语句的结果值不能通过变量赋值的方式取到
var result = {
  var b = 10;
  b = 20
}
// SyntaxError
  • 可以用eval(..)获得语句的结果值,但是JavaScript编程从来都不推荐使用eval()。
var result = eval(`{
  var b = 10;
  b = 20
}`)

result // 20

表达式的副作用

  • 中文翻译版将effect译为副作用,有点难以理解。
  • 个人理解为,表达式有返回值是表达式的一个重要特性,但是大部分表达式还会有运算作用,他会对程序中的其他部分(变量)产生影响。简单理解为有运算符的表达式就会有effect
var a = 30;

a++; // 30
a; // 31

++a; // 32
a; // 32
  • 副作用产生的时间不同,++a在副作用(a自增)产生之后返回值,而a++在副作用产生之前返回值。

  • delete表达式也有返回值,删除不存在或可配置的属性,返回true,否则返回false或者报错。

赋值运算符

  • 研究赋值运算符的副作用和返回值在连等语句中有重要意义。
var a,b,c

a = b = c = 30;
// c = 30的副作用是将30复制给c,返回值是表达式c = 30的结果值,同样原理左依次执行。
  • 利用表达式的返回值和副作用将语句合并。
function foo (a) {
  return a > 20
}

var num = 30

if (num > 10) {
  var result = foo(num)
  if (result) {
    console.log(result)
  }
}

上面的两个if可以合并成

var result
if (num > 10 && (result = foo(num))) {
  console.log(result)
}

大括号

  • JavaScript中同样的语法在不同情况下会有不同的解释,其中大括号就是典型。

对象字面量

  • 字面量形式定义变量
  var a = {
    foo: 1
  }

代码块

  • 以下代码使用的{}定义代码块并产生了es6中的块级作用域
{
  let a = 10;
  a
}

对象解构

  • 这部分之前学习过,不再重复。
let {a, b} = {a: 10, b: 20}

else if问题

  • ifelse后面的语句只有一句时可以省略{}
if (a) console.log(a)
  • else if不是JavaScript的语法规则,是开发者发明的,很好用,所以极为常见。

  • else if表示else后跟了一个省略{}if代码块。

  • 因不推荐将ifelse后面的{}省略,所以else if在这个层面上讲是不规范的写法。


if (a) {

} else if (b) {

}

// 规范写法
if (a) {

} else {
  if (b) {

  }
}

大括号的“歧义”

  • 这个“歧义”是指开发者难以判断大括号代表的是什么(对象?代码块?),而不是指引擎解析上的歧义。
function foo () {

}

{
foo: foo()
}

上面代码像是创建了一个对象但是没有变量接收,但是实际上是{}代表了一个代码块,而foo:在正常代码中写法显得奇怪但是没有报错,是因为这里有个我们不常用的label代码标签。

  • 上面代码块中的逻辑为“定义了一个名为foo的语句foo()

代码标签在循环中的作用

  • break continue跳出嵌套循环
for (var i = 0; i < 3; i++) {
  for (var j = 0; j < 3; j++) {
    if (i === j) {
      break;
    }
    console.log(i,j)
  }
}

// 1 0
foo: for (var i = 0; i < 2; i++) {
  for (var j = 0; j < 2; j++) {
    if (i === j) {
      break foo; // 表示跳出标签为foo的循环,即外层循环
    }
    console.log(i,j)
  }
}
// 没有打印任何i,j

分号问题

自动分号

  • Automatic Semicolon Insertion,ASI,自动分号插入。
  • JavaScript解析器中发现代码行可能因为缺少分号而导致错误,就会在代码行末尾与换行符之间没有其他内容的情况下(空格和注释除外)自动补上分号。

纠错机制

  • ASI是一种纠错机制,现在有些时候被用于语法简洁。
  • 在之前学习ES6时,有听到一种说法是“es6中建议省略不必要的分号”,于是在学习es6之后,都习惯性的不加分号了。
  • 在了解了这个规范之后,对于加不加分号有了新的认识:这不是一个代码美观问题,而是一个语法规则问题。

异议

json语法在控制台直接输入的报错解释

书中的说法:
以下代码在控制台直接输入会报错,因为{..}被解析成代码块,foo被解析成标签,而标签不能带有引号

> {
  "a": 20
  }

实际的结果:

chrome中会解析成创建了一个对象和{a:20}相同。

以下两种{}的运行结果
报错:

> ;{
    "a": 20
  }

不报错:

> ;{
    a: 20
  }
< 20

强制类型转换的问题

[] + {} // "[object Object]"
{} + [] // 0

{} + [] 中{}被视为代码块,空代码块被强制类型转换后的值怎么确定的不太明确。
但可以测试空代码块的返回值是undefined

> eval("{}")
< undefined

> ;{}
< undefined

往期精彩回顾


叶茂 广州芦苇科技web前端工程师

相关文章

  • GO语言gin框架实战-04-websocket链接

    1. 升级接口 1.1 语法 - 升级接口 语法 语法示例 - 关闭 语法 语法示例 - 接收前端信息 语法 语法...

  • 软帝学院:80道java基础部分面试题(四)

    Java基础部分 基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语法,集...

  • JSON 语法

    JSON 语法是 JavaScript 语法的子集。 JSON 语法规则 JSON 语法是 JavaScript ...

  • art-template模板

    art-template同时支持两种模板语法:标准语法 和 原始语法 标准语法: {{ 数据 }}原始语法: <%...

  • Dart的一些语法糖(持续更新)

    语法糖 ?. 与 ?? dart 语法糖 ?. dart 语法糖 ??

  • dart语法7-泛型

    dart语法1dart语法2-内置类型dart语法3-函数dart语法4-操作符dart语法5-异常dart语法6...

  • dart语法8-库

    dart语法1dart语法2-内置类型dart语法3-函数dart语法4-操作符dart语法5-异常dart语法6...

  • dart语法10-生成器

    dart语法1dart语法2-内置类型dart语法3-函数dart语法4-操作符dart语法5-异常dart语法6...

  • dart语法9-异步

    dart语法1dart语法2-内置类型dart语法3-函数dart语法4-操作符dart语法5-异常dart语法6...

  • dart语法11

    dart语法1dart语法2-内置类型dart语法3-函数dart语法4-操作符dart语法5-异常dart语法6...

网友评论

      本文标题:语法

      本文链接:https://www.haomeiwen.com/subject/abznhqtx.html