用 Python 眼光看Nodejs(三),Nodejs灵性语法整理(保持更新)

说到语法,翻一翻熟悉的js菜鸟教程,变量,if语句,函数定义啥的,都是老生长谈的东西,一看就能明白。但还是和Python有点偏差,比如分号啊括号啊,变量定义啊什么的,而且唰唰唰往下看了都懂,等真正自己写起来的时候,都忘得差不多了,还是要回头翻。但是仅仅能看懂语法也是有好处的,比如新学一个模块或者框架的时候,你能看得懂代码然后依葫芦画瓢照着写,遇到不懂得语法(比如箭头函数)就去找,学习量也比较少,能更容易接受,达到慢慢积累的效果。这对于自己写代码也有一定帮助,看的语法少,那就稳稳当当码代码,不搞花里胡哨的写法。

ES6、ES7、ES8特性一锅炖,这里是Js近几年来的新特性,其实新特性对于初学者还是很有好的,相关用法只用看新的就行,老的完全摒弃不闻不问,多清净。

1. 箭头函数

类似于Python的匿名函数,lambda表达式,但又有一些不一样。lambda只能是一条单独的表达式,而箭头函数却可以有多个表达式,中间用分好隔开,我认为两者差异的原因很大程度上在于,匿名函数本身就是为回调函数量身定做的,而Js中回调用法真的是家常便饭,要是像Python那样仅仅是单行表达式,那真的是太不方便了。

1.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
30
31
32
33
34
35
36
37
(参数1, 参数2, …, 参数N) => { 函数声明 }

//相当于:(参数1, 参数2, …, 参数N) =>{ return 表达式; }
(参数1, 参数2, …, 参数N) => 表达式(单一)

// 当只有一个参数时,圆括号是可选的:
(单一参数) => {函数声明}
单一参数 => {函数声明}

// 没有参数的函数应该写成一对圆括号。
() => {函数声明}```

### 1.2 高级用法
```js
//加括号的函数体返回对象字面表达式:
参数=> ({foo: bar})

//支持剩余参数和默认参数
(参数1, 参数2, ...rest) => {函数声明}
(参数1 = 默认值1,参数2, …, 参数N = 默认值N) => {函数声明}

//同样支持参数列表解构
let f = ([a, b] = [1, 2], {x: c} = {x: a + b}) => a + b + c;
f(); // 6 ```

当然官方不太可能单单因为这一个简单的功能:**更短的函数** 而把它搬到新特性里来,看这边[箭头函数与普通函数区别](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Functions/Arrow_functions)


## 2. 数组的迭代到数组的常用用法
例子正好用到上面的箭头函数:
```js
var array1 = ['a', 'b', 'c'];
array1.forEach((value,index,array) =>{console.log(value,index,array)})
//除了value,其他的参数是可选的

//可用for of代替,类似于Python中for... in
for (value of array1) {console.log(value)}

大概浏览下array数组的语法一览,array的方法很多,基本上结合了Python中的list的内置函数以及itertools模块中的函数(包含过滤,映射,合并,元素拓展,重新排列等功能。当然,js语法中也有迭代器跟生成器的概念,这里不拓展。

3. 解构

刚看到结构的语法,有些懵逼,实在想不到跟Python的哪种语法相关。后来一看是将序列分解为单独变量,以及从任意长度的可迭代对象中分解元素

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
//解构数组
var a, b, rest;
[a, b] = [10, 20];
// 用三个点,python中是*
[a, b, ...rest] = [10, 20, 30, 40, 50];
console.log(rest);
// expected output: [30,40,50]
//使用扩展运算符(...)拷贝数组
const itemsCopy = [...items];

///解构对象,这个是python没有的,通过dict.values()然后再分解
var a, b;
({a, b} = {a: 1, b: 2});
//给新的变量赋值
var o = {p: 42, q: true};
var {p: foo, q: bar} = o;
console.log(foo); // 42
console.log(bar); // true
// 提供默认值
var {a = 10, b = 5} = {a: 3};
console.log(a); // 3
console.log(b); // 5
// 给新的变量命名并提供默认值
var {a:aa = 10, b:bb = 5} = {a: 3};
console.log(aa); // 3
console.log(bb); // 5

4. 模板字符串

静态字符串一律使用单引号或反引号,不使用双引号。动态字符串使用反引号。
const a = 'foobar'; const b = `foo${a}bar`;

打印字符串这种常用到语法,一定需要个优雅的写法,才有动力让程序员代码继续搞下去。跟神一样的python的format语法差不多,不过好像不能在格式化字符串的同时对传入变量进行一些转换操作,比如进制,小数点转换等。
还有种更高级的用法:带标签的模板字符串,不展开。

4.1 拓展:条件运算符

条件(三元)运算符是 JavaScript 仅有的使用三个操作数的运算符。本运算符经常作为if语句的简短形式来使用。
condition ? expr1 : expr2

1
2
3
4
5
6
7
8
9
10
var age = 26;
var canDrinkAlcohol = (age > 21) ? "True, over 21" : "False, under 21";
console.log(canDrinkAlcohol); // "True, over 21"

// 三元运算符能够很好地用在函数返回值的表达式中,此时不需要 if/else 语句
function canDrinkAlcohol(age) {
return (age > 21) ? "True, over 21" : "False, under 21";
}
var output = canDrinkAlcohol(26);
console.log(output); // "True, over 21"

在Python中不存在三元表达式,可以用简洁版的if/else语句canDrinkAlcohol = "True, over 21" if age>21 else "False, under 21",可以达到同样效果。

5. let与const

Python是强类型 + 动态类型 , JS是弱类型 + 动态类型
动态/静态类型,指的是声明一个变量之后,它是否可以存储(指向)不同类型的变量。隐式类型转换,只可能发生在弱类型语言中
关于更多这方面的了解可以看这个链接:JS是动态弱类型语言的理解

虽同为动态类型语言,但js还是有点小不同,要用var,let,const之类的。浅谈var、let和const区别这里已经说得很清楚了,编程对此的建议是:

let完全可以取代var,因为两者语义相同,而且let没有副作用,在let和const之间,建议优先使用const,尤其是在全局环境,不应该设置变量,只应设置常量。

6. this用法

关于this,见到的比较少,但对这个语法也是模糊不清,等真正接触到了在写心得。具体用法参考官网手册

7. async与await

有必要简单讲一下javascript的异步发展历程,异步主要经历了这么几个过程:
Es6之前:

  • 回调函数(callback)

Es6

  • Promise对象
  • Generator函数

Es7

  • async/await语法

async用于声明一个function是异步的,await只能出现在用async修饰的function中

这是个头疼的语法,无论是在Python还是js中。不过殊途同归,异步协程的语法在一系列更改迭代之后,从yield到了await,这才是真正的光明大陆,抛弃内部实现,直接用同步语法写异步吧,美滋滋。

在Python中异步编程更多的体验是在高效率,替换多线程的作用,而在nodejs中,本身函数的异步性,我感觉这个语法的核心在于取代回调函数的地狱,重在更好代码书写方式,即用同步方式写异步编程 ; promise与future含义接近,都代表未来会完成的事物,尽量不要对它们进行手动实例化,很多都是内部实现的,我们做的只是理解异步,然后用专家们定义的“async”与“await”就好

8. 杂谈

作为一门语言,繁多的语法是免不了的,真的很多,js中还看到了Python中见过的但是不怎么熟悉用不到的语法的影子,都是一一对应。对于这些,不可能一口吃成胖子,任重而道远。碰到新语法就先去揣测它的意思然后去翻阅官方手册更容易去记住它~