JS 语法快速参考
本文最后更新于 2021年4月4日 晚上
这篇文章主要是收集 JS 的语法, 以供日后查询, 绝大部分参考的是MDN 有关 JS 的帮助文档里面的内容.
简介
JS 只是一种 ECMA 标准的实现.
语法
- 声明: 使用如下的声明方式
var: 变量声明时使用.
let: 局部变量声明使用
const: 局部常量声明使用.
JS 中在任何函数外部定义的变量就是全局变量, 在函数内就是局部变量.
- 关于
undefined
和null
:
可以使用 undefined
来判断当前变量是否有值. 另外在布尔判断中, 它表示的是 false
的含义.
另外如果在数值表达式中使用 undefined
的变量, 则会产生一个 NaN
结果:
1 |
|
而 null
代表的是 0 值, 并且在数值表达式中使用 null
还会产生计算结果, 我了个擦.
1 |
|
- 关于作用域:
在 ECMA 2015(ECMA 6) 之前, 是没有块作用域的, 不过 ECMA 2015 之后添加了, 故使用 let
在块作用域内定义变量.
- 关于全局变量:
全局变量实际上是一个 全局对象(global object)
的属性, 如果是在网页中, 就是 window
对象的属性, 故实际上全局变量可以通过 window.xxx
来访问 xxx
全局变量.
- 关于常量(const):
常量在运行时无法被改变, 但常量对象的属性不受此限制, 即可以向 const
定义的对象进行添加属性或改变属性的值等操作.
1 |
|
另外数组也不受限制:
1 |
|
- 数据类型和数据结构:
最新的 ECMA 标准定义了七种数据类型, 包括六种标准类型, 还有一种对象类型(Object).
6 种标准类型如下:
- Boolean: true 或者 false
- null: 空类型
- undefined: 未定义
- Number: 数值类型
- String: 字符串类型
- Symbol: ECMA 2015(ES6) 新增, 代表的是可识别的且不可变数据类型.
JS 是一种动态类型的语言, 故变量可以理解可以具有任何上述类型, 故:
1
2
var answer = 42;
answer = 'Thanks for all the fish...';
另外还有一些奇奇怪怪且有趣的自动类型转换:
1
2
'37' - 7 // 30
'37' + 7 // "377"
有两种方式可以从字符串获取数值:
第一种是 `parseInt()` 和 `parseFloat()`.
第二种是在前面添加 `+` 号:
1
2
3
'1.1' + '1.1' // '1.11.1'
(+'1.1') + (+'1.1') // 2.2
// Note: the parentheses are added for clarity, not required.
- 字面量的赋值详见 MDN 的链接: Literals.
主要是 6 种基本类型的字面量, 以及 Object 类型的字面量. 主要是 Object 字面量是 {}
包裹的, 类似字典的写法, 如下所示:
1 |
|
另外就是在 ES 2015(ES6) 中, 对象的支持得到极大增强. 具体内容需要进一步探索.
- 语句块:
1 |
|
在语句块中实际定义了一个块作用域, 在 ES6 之前是没有这个东西的.
在 ES6 之后, let 和 const 量是块作用域的.
- 在 JS 中的流程控制语句和 C 系语言都差不多. 只是要注意, 在 JS 中有许多的值可以表示 false:
false
undefined
null
0
NaN
空字符串
""
而其他所有的值, 包括对象, 用在布尔判断中都表示的 true
值. 另外有一个比较让人抓狂的现实是 true
字面量和以 true
为值的 Boolean
对象并不相等:
1 |
|
另外注意不要把 swift 的 switch
带到这里, 默认是 fallthrough 的.
- 异常处理:
使用 throw
抛出异常, 使用 try...catch
捕捉异常.
可以抛出各种数据类型的异常:
1 |
|
不过最好还是使用 Error
对象来作为错误载体:
1 |
|
- ES6 之后在语言中内置了
Promise
对象, 作为异步操作支持, 是一种 Promise 实现.
下面是一个典型用法:
1 |
|
循环语句在这里可以看到, 有 for-in 语句的, 另外可以使用
for-of
语句来遍历 iterable 量, 比如数组等.函数的参数传递时, 如果是 6 种基本类型, 是按值传递的, 而如果是对象, 则是传递的引用, 比如数组或用户自定义对象.
函数可以定义为函数表达式, 这个时候就没有函数名而已. 当然也可以提供函数名, 这个时候该名字就可以在该函数内部使用, 比如有递归需求的时候:
1 |
|
A closure is an expression (typically a function) that can have free variables together with an environment that binds those variables (that “closes” the expression).
实际就是在描述 closure 可以形成一个上下文环境, 在该上下文中包含其所处的上下文中的变量, 即变量捕捉.
- 在任何函数内都有一个特殊的对象, 就是
arguments
对象, 包含的是所有的参数:
1 |
|
这样就可以在不知道有多少个参数传入的情况下处理参数表了:
1 |
|
- 关于函数参数, 详见函数参数文档. 从 ES6 开始, 可以提供函数参数的默认参数值(如果不提供, 则默认是
undefined
):
1 |
|
- ES6 之后, 还增加了
rest parameter
, 即不定数量的参数表达:
1 |
|
ES6 新增了
=>
的语法, 和 C# 或 Dart 中都类似, 是一种函数表达.限制模式: 启用方法是在脚本文件开头的位置添加如下内容:
1 |
|
关于在限制模式中进行的改变可以看限制模式改变文档.
- 在函数中, 默认还存在一个
this
指针, 指向的就是该函数, 实际上这个函数也形成了一个类定义, 但如果是嵌套函数则会存在问题, 故可以使用如下方式避免:
1 |
|
另外在箭头表达式中不存在 this 指针:
1 |
|
下面是一些比较有趣的内容:
- 解构:
1
2
3
4
5
6
7
8
9
var foo = ['one', 'two', 'three'];
// without destructuring
var one = foo[0];
var two = foo[1];
var three = foo[2];
// with destructuring
var [one, two, three] = foo;
和 swift 一样, 也有
==
和===
, 后者表示严格相等, 具体含义详见文档.次方操作符:
**
, 比如2 ** 3
结果是8
.位操作符也有.
delete
操作符会将对象或对象属性删除, 删除对象后, 指向该对象的变量就变成了undefined
值, 删除属性也是同理, 如果删除成功的话, 会返回 true.
1
2
3
4
delete objectName;
delete objectName.property;
delete objectName[index];
delete property; // legal only within a with statement
如果在数组上使用 `delete`, 则会将对应下标变为 `undefined`, 而不是减少一个元素这么简单.
typeof
会返回某个类型的字符串表示, 如下所示:
1
2
3
4
5
6
7
8
9
10
11
var myFun = new Function('5 + 2');
var shape = 'round';
var size = 1;
var foo = ['Apple', 'Mango', 'Orange'];
var today = new Date();
typeof myFun; // returns "function"
typeof shape; // returns "string"
typeof size; // returns "number"
typeof foo; // returns "object"
typeof today; // returns "object"
typeof doesntExist; // returns "undefined"
有两个特殊情况:
1
2
typeof true; // returns "boolean"
typeof null; // returns "object"
void
在 js 中是作为一种操作符存在的, 用于表示某个表达式没有返回值, 即undefined
的返回值.in
操作符用于判断某个属性名是否在对象中:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// where propNameOrNumber is a string, numeric, or symbol expression representing a property name or array index, and objectName is the name of an object.
propNameOrNumber in objectName
// 另外还有一些有趣的用法:
// Arrays
var trees = ['redwood', 'bay', 'cedar', 'oak', 'maple'];
0 in trees; // returns true
3 in trees; // returns true
6 in trees; // returns false
'bay' in trees; // returns false (you must specify the index number,
// not the value at that index)
'length' in trees; // returns true (length is an Array property)
// built-in objects
'PI' in Math; // returns true
var myString = new String('coral');
'length' in myString; // returns true
// Custom objects
var mycar = { make: 'Honda', model: 'Accord', year: 1998 };
'make' in mycar; // returns true
'model' in mycar; // returns true
instanceof
用于判断是否是某个类型对象:
1
2
3
4
var theDay = new Date(1995, 12, 17);
if (theDay instanceof Date) {
// statements to execute
}
1 |
|
Math
对象: 数学计算相关.Date
对象: 使用Date
对象进行和日期有关的操作.JS 中的字符串.
Date and time formatting: 日期和时间的转换.
带有类型的数组(Typed Arrays), 在某些网络操作中, 比如 WebSocket 中很常用, 详见文档.
字典类型(Map), 详见文档.
哈希表(Set), 详见文档.
JS 中的对象模型非常简单, 无论是语法上还是概念上, 看下面这段:
1 |
|
定义时可以使用函数或 Object
来.
在 js 中的所有对象都继承自至少一个另外的对象, 被继承的对象称为 prototype
, 详见文档.
在 JS 中仍然有 setter 和 getter 可以定义, 详见文档.
关于对象模型的相关细节, 详见文档, 这里就引出了对基于 Class
和基于 prototype
的面向对象语言的差别的讨论, 一句话来说, 在基于 prototype 的语言中, 没有类的概念, 只有对象, 而 类
实际上就是作为 prototype
的对象的描述而已.
在这个文档中 通过 JS 实现了一个 employee
的对象体系.
当对象被实例化后, 就会自动拥有一个 __proto__
属性, 除了 Object
对象外, 每个对象都有一个 __proto__
属性, 这个属性指向的是该对象的 prototype
对象, 可以理解位指向的父对象.
比如通过 __proto__
属性, 可以自己实现一个 instanceOf
函数:
1 |
|
在 JS 中没有多继承.
JS 中的 Promise 文档, 可以参考一下, 这个是万物之源啊. 另外就是错误传递可以看这个文档.
在 ECMA 2017 中引入了
async/await
可以极大方便异步编程, 并且可以使用 await 来等待 promise.在 JS 中可以使用
yield
懒生产序列.JS 中从 ECMA 2015 (ES6) 开始, 也引入了元编程和反射, 详见文档.
虽然说是基于 prototype 的语言, 但在 ES6 中引入了一种 class 语法, 这样可以极大方便从其他语言转过来的开发者, 不过要注意, 这里只是一种语法, 实际上底层还是基于 prototype 的, 而非类, 详见文档.
关于 JSON, 这个才是正宗的 JSON 介绍!