你不知道的JS(十一):语法

一、语句和表达式

  • 开发人员常常将“语句”和“表达式”混淆,这里先区分一下。
  • 语句相当于句子,完整地表达某个意思的一组词。
  • 表达式相当于短语,运算符则相当于标点符号和连接词。
var a = 3 * 6;
var b = a;
b;
  • 3 * 6是一个表达式,第二行的a和第三行的b也是表达式。a = 3 * 6b =a是赋值表达式
  • 第一行和第二行是声明语句,因为它们声明了变量。第三行是表达式b,同时也是语句,叫做表达式语句

1. 语句的结果值

  • 语句都有一个结果值
var a = 3 * 6;
var b = a; // 结果是赋值给b的值,18
  • 在浏览器开发控制台中输入语句,默认情况下控制台会显示所执行的最后一条语句的结果值。
if (true) {
	b = 4 + 38;
}
  • 代码块也是返回最后一个语句的结果值。

2. 表达式的副作用

最常见的是函数调用

  • a++,先返回变量a的值,再对a的值加1。(还有++aa----a

  • a = b += 2,即b = b + 2,然后a = b

3. 上下文规则

  1. 大括号

对象常量

var obj = {
	a: 1;
}

标签语句

{
	a: 1;
}
  1. 代码块
[] + {}; // "[object Object]",这里的{}为对象
{} + []; // 0,这里的{}为代码块
  1. 对象解构
  • ES6开始,{}也用于解构赋值。
  1. else if和可选代码块
  • 实际上JavaScript没有else if,但ifelse只包含单条语句的时候可以省略代码块的{}
if(a) doSomething(b) // 省略了{}

二、运算符的优先级

  • 表达式中出现两个或两个以上运算符就需要注意运算符的顺序。

参见MDN网站的“优先级表“。

运算符优先级 - JavaScript | MDN (mozilla.org)

这里介绍常见的:

1.短路

  • &&||来说,如果左边的操作能够得出结果,就可以忽略右边的操作数。
a && a.name;
  • a条件的判断如同一道安全保护,如果a未赋值,表达式a.name会出错。

  • 通过短路特性,a条件判断未通过时,a.name不会执行。

2.关联

  • 如果多个相同优先级的运算符同时出现

  • 运算符的关联不是从左到右就是从右到左,这取决于组合式从左开始还是从右开始。

3.使用

  • 适当结合()使用,增强可读性。

三、自动分号

  • 有时JavaScript会自动为代码补上分号,即自动分号插入(ASI)。
  • 如果缺失了必要的分号,代码将无法运行。
var a = 42, b
c;
  • 如果没有分号,c会被作为var语句的一部分来处理。JavaScript会判断后会自动补充。

是否应该完全依赖ASI来编码,这是JavaScript中最具争议的话题之一。

  • 正方认为ASI机制能省掉哪些不必要的分号;

  • 反方认为ASI机制问题太多,尤其是对于缺乏经验的初学者,因为自动插入分号,会无意中改变代码的逻辑。

  • 作者建议在所有需要的地方加上分号,将ASI的依赖降到最低。

四、错误

1. 语法错误

  • 在编译阶段发现的代码错误叫做”早期错误“。语法错误是早期错误的一种。
  • 这种错误无法通过try...catch来捕获,相反,还会导致解析失败。
var a;
42 = a; // 错误

2. 提前使用变量

  • ES6规范定义了一个新的概念,叫做暂性死区。(属于语法错误)
  • 暂性死区是由于代码中的变量还没有初始化而不能被引用的情况。
{
	typeof a; // undefined,这里不会报错
	typeof b; // ReferenceError!
	let b
}

五、函数参数

  • ES6参数默认值或函数不传入参数时,会导致arguments数组和相对应的命名参数之间出现偏差。
function foo(a) {
	a = 42;
	console.log(arguments[0])
}

foo(2); // 42
foo(); // undefined
  • 也就是说,arguments建立传入参数的关联,而且在严格模式下,不会建立关联。

  • 因此,在开发中不要依赖arguments关联机制。

六、try…finally

  • 如果有catch的话是在catch中执行。
  • 但是无论出现什么情况,最后一定会调用finally

七、switch

  • 可以把它看作 if...else if...else if... 的简化版本
var a = "42";
switch (true) { // 匹配true
	case a == 10:
		// ...
		break;
    case a == 42:
    	// ...
    	break;
    default:
    	// 没有匹配则执行这里
}
// 或者
switch (a) { // 匹配a
	case 42:
		// ...
		break;
}
  • 需要注意的是,case的匹配算法和 ===相同,通常是简单值,所以并没有问题。
var a = "hello world";
var b = 10;
switch (true) { // 匹配true
	case (a || b == 10): // 这里的结果是"hello world",不是true
		// ...
		break;
    default:
    	// ...
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值