Basic
var a = 10; //
let b = 20; // 作用域以外不可引用,建议尽量用 let
const c = 30;
scope | Hoisting | Re-declaration | |
---|---|---|---|
var |
Function-scoped | Yes, undefined if not initialized |
Yes |
let |
Block-scoped | No, must be declared | No |
const |
Block-scoped | No, must be declared | No |
String
let s = "Hello, world"
// => "ell": the 2nd, 3rd, and 4th characters
s.substring(1,4)
// => "ell": same thing
s.slice(1,4)
// => "rld": last 3 characters
s.slice(-3)
// => ["Hello", "world"]:
s.split(", ")
// => 2: position of first letter l
s.indexOf("l")
// => true: the string starts with these
s.startsWith("Hell")
// => true: s includes substring "or"
s.includes("or")
// => "Heya, world"
s.replace("llo", "ya")
// => "hello, world"
s.toLowerCase()
// => "H": the first character
s.charAt(0)
// => " x": add spaces on the left to a length of 3
"x".padStart(3)
Template
// greeting == "Hello Bill."
let name = "Bill"
let greeting = `Hello ${ name }.`
Pattern Matching
let text = "testing: 1, 2, 3"
let pattern = /\d+/g
pattern.test(text)
text.search(pattern)
text.match(pattern)
text.replace(pattern, "#")
text.split(/\D+/)
类型转换
// Number to string
let n = 17
let s = n.toString()
// String to number
// => 3
parseInt("3 blind mice")
// => 0.1
parseFloat(".1")
// If the value is a string, wrap it in quotes, otherwise, convert
(typeof value === "string") ? "'" + value + "'" : value.toString()
对象
let square = {
area: function() { return this.side * this.side; },
side: 10
};
//等价于
let square = {
area() { return this.side * this.side; },
side: 10
};
数组
// forEach
let data = [1, 2, 3, 4, 5], sum = 0
data.forEach(value => { sum += value; })
// map
let a = [1, 2, 3]
a.map(x => x*x)
// filter
let a = [5, 4, 3, 2, 1]
a.filter(x => x < 3)
// find and findIndex
let a = [1, 2, 3, 4, 5]
a.findIndex(x => x === 3)
a.find(x => x % 5 === 0)
// every and some
a.every(x => x < 10)
a.some(isNaN)
// reduce
a.reduce((x,y) => x+y, 0)
// flat and flatMap
[1, [2, 3]].flat()
let phrases = ["hello world", "the definitive guide"]
let words = phrases.flatMap(phrase => phrase.split(" "))
// concat
let a = [1,2,3];
a.concat(4, 5)
// stack and queue
let stack = []
stack.push(1,2)
stack.pop()
let q = []
q.push(1,2)
q.shift()
// subarrays
let a = [1, 2, 3, 4, 5, 6, 7, 8]
a.slice(0,3)
a.splice(4)
// fill
let a = new Array(5);
a.fill(0)
// indexOf
let a = [0, 1, 2, 1, 0]
a.indexOf(1)
// includes
let a = [1, true, 3, NaN]
a.includes(true)
// sort
let a = ["banana", "cherry", "apple"]
a.sort()
// reverse
a.reverse()
// to string
let a = [1, 2, 3]
a.join(" ")
[1,2,3].toString()
遍历
遍历列表
let arr = ["x", "y", "z"]
for (let i = 0; i < arr.length; i++) {
console.log(arr[i])
}
for (let element of arr) {
console.log(element)
}
遍历对象
let obj = {"x": 1, "y": 2, "z": 3}
for (let key in obj) {
console.log(key, obj[key])
}
for (let key of Object.keys(obj)) {
console.log(key)
}
for (let val of Object.values(obj)) {
console.log(val)
}
for (let [k, v] of Object.entries(obj)) {
console.log(k, v)
}
异步遍历
// Read chunks from an asynchronously iterable stream and print them out
async function printStream(stream) {
for await (let chunk of stream) {
console.log(chunk);
}
}
排序
let unorderObj = {"c":"PHP", "d":"Laravel","b": "Html", "a":"Css"}
let orderObj = Object.keys(unorderObj).sort().reduce(function (r, k) {
(r[k] = o[k], r), {}
})
let unorderArr = [
{"name": "Tom", "age": 46},
{"name": "Aack", "age": 26},
{"name": "Hanson", "age": 16}
],
let orderArr = unorderArr.sort(function(a, b) {
if(a.name < b.name) { return -1; }
if(a.name > b.name) { return 1; }
return 0;
})
对象序列化
let o = {x: 1, y: {z: [false, null, ""]}};
let s = JSON.stringify(o);
let p = JSON.parse(s);
Number and Math
Math object
// power
Math.pow(2,53)
// round
Math.round(.6)
// max
Math.max(x,y,z)
// random
Math.random()
// Pi
Math.PI
Number object
// Infinity
Infinity
Number.POSITIVE_INFINITY
// -Infinity
-Infinity
Number.NEGATIVE_INFINITY
// NaN
NaN
Number.NaN
// parseInt
parseInt()
Number.parseInt()
// parseFloat
parseFloat()
Number.parseFloat()
// isNaN
Number.isNaN(x)
// isFinite
Number.isFinite(x)
// isInteger
Number.isInteger(x)
// isSafeInteger
Number.isSafeInteger(x)
// MIN_SAFE_INTEGER = -(2**53 - 1)
Number.MIN_SAFE_INTEGER
// MAX_SAFE_INTEGER = 2**53 - 1
Number.MAX_SAFE_INTEGER
// EPSILON = 2**-52: smallest difference between numbers
Number.EPSILON
Date
// The current time as a Date object
let now = new Date()
// The current time as a timestamp (a number)
let timestamp = Date.now()
// Convert to a millisecond timestamp
let ms = now.getTime()
// Convert to a string in standard format
let iso = now.toISOString()
Function
function hello () {
return "Hello world!"
}
// with parameters
function hello (name) {
return "Hello " + name + "!"
}
// 匿名函数
function (name) {
return "Hello " + name + "!"
}
// Arrow function
hello = () => { // 等价于 hello = function() {
return "Hello World!";
}
// 省略 `{}` 和 `return`
hello = (name) => "Hello " + name + "!";
hello = (firstName, lastName) => "Hello " + firstName + " " + lastName + "!";
// 只有一个参数时,括号可以省略
hello = name => "Hello " + name + "!";
// 箭头函数并没有 this, 会作为变量一直向上级词法作用域查找,可能导致 bug
P.S.:
- 函数只能有一个返回值,如果需要返回多个值,可以把它们放到对象或数组中返回
异步
Promise
A Promise is an object that represents the result of an asynchronous computation
- 同步函数调用会被放入 Call Stack
- Promise callback function 会被放入 Microtask Queue
setTimeout
,setInterval
等异步 web APIs 会被放入 Task Queue- Event Loop 会一直检查 call stack,当其为空时会将 microtask queue 中的 callback function 放入 call stack,当 call stack 和 microtask queue 均为空时才会处理 task queue
创建 Promise 对象
let myPromise = new Promise((resolve, reject) => {
// do something may not get result immediately
const v = Math.random()
console.log(v)
if ( v > 0.5 ) { // some condition
// case on some condition
// call resolve callback function and pass result data as argument
resolve({ data: 'Here is your data!' })
} else {
// case on other condition
// call reject callback function and pass error as argument
reject(new Error('Network error'))
}
})
console.log("promise defined")
上述代码在 Promise 对象创建时会立即允许里面代码,在调用 resolve(res)/reject(err)
时会改变 Promise 对象的状态,这时 Promise 会进入成功/失败状态
调用 Promise.then
或 Promise.catch
会将里面的 callback 函数放入 microtask queue,等待 Promise 进入成功/失败状态后且 同步代码运行完后调用 callback 函数
// code in the Promise block get executed when created
// code in the `then/catch` block wait until the Promise enter resolved/rejected state
myPromise
.then(result => {
console.log('Data:', result.data)
})
.catch(error => {
console.error('Error:', error.message)
})
定义异步函数
function fetchData() {
return new Promise((resolve, reject) => {
console.log(Date.now() + ": promise start")
const v = Math.random()
if (v > 0.5) {
resolve({ data: "hello" })
} else {
reject(new Error('Network error'))
}
console.log(Date.now() + ": promise end")
})
}
这时 Promise 内部的代码并不是立即执行,而是在调用 fetchData
函数时执行,下面的代码会立即执行 Promise 的内容,并等待 Promise 状态改变后执行传入 then/catch
的回调函数
fetchData()
.then((res) => {
console.log(Date.now() + ": promise resolved")
console.log(res.data)
})
.catch((err) => {
console.log(Date.now() + ": promise rejected")
})
链式调用:传入 .then(callback1)
的回调函数可以返回值,这个值会作为参数被传到下一个 .then(callback2)
的回调函数
let promise = new Promise((resolve, reject) => {
resolve(1)
})
promise
.then(res => {
console.log(res) // 输出 1
return res + 1
})
.then(res => {
console.log(res) // 输出 2
return res + 1
})
.then(res => {
console.log(res) // 输出 3
return res + 1
})
如果回调函数返回了一个 Promise 对象,那么下一个 .then(callback)
同样会等待上一个回调函数的执行
promise
.then(value => {
return new Promise(resolve => {
setTimeout(() => {
resolve(value + 1);
}, 1000);
});
})
.then(value => {
console.log(value); // 输出 2,但是在 1 秒后
});
await/async
是 ES7 中引入的新特性,具体用法如下
async function
关键字定义的函数,自动将返回值包装成一个 Promise,如果正常返回就是 resolved 状态,如果有异常则为 rejected 状态
async function asyncSleep(time) {
setTimeout(() => {
console.log(Date.now() + ": asyncSleep")
}, time * 1000)
}
// 等价于
function sleep(time) {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log(Date.now() + ": sleep")
}, time * 1000)
resolve()
})
}
await
只能用在用 async
定义的函数内部, 用于暂停执行等待某个 async 函数的返回
function sleep(time) {
return new Promise((resolve, reject) => { setTimeout(() => {
console.log(Date.now() + ": sleep")
}, time * 1000)
resolve()
})
}
async function asyncSleep(time) {
console.log(Date.now() + ": asyncSleep start")
await sleep(time)
console.log(Date.now() + ": asyncSleep end")
}
asyncSleep(1)
.then(() => {
console.log(Date.now() + ": asyncSleep resolved")
})
模块
Node.js
Export
// Define all the functions, public and private
const sum = (x, y) => x + y;
const square = x => x * x;
const mean = data => data.reduce(sum)/data.length;
const stddev = d => {
let m = mean(d);
return Math.sqrt(d.map(x => x - m).map(square).reduce(sum)/(d.length-1));
};
// Now export only the public ones
module.exports = { mean, stddev };
Import
// 导入 built-in 包
const fs = require("fs");
const http = require("http");
// 导入第三方包
const express = require("express");
// 导入文件
const stats = require('./stats.js');
const BitSet = require('./utils/bitset.js');
ES6
Export
const PI = Math.PI;
function degreesToRadians(d) { return d * PI / 180; }
class Circle {
constructor(r) { this.r = r; }
area() { return PI * this.r * this.r; }
}
export { Circle, degreesToRadians, PI };
Import
import * as stats from "./stats.js";
// dynamic import
import("./stats.js").then(stats => {
let average = stats.mean(data);
})
async analyzeData(data) {
let stats = await import("./stats.js");
return {
average: stats.mean(data),
stddev: stats.stddev(data)
};
}
注意
null and undefined
null
: a special object value that indicates “no object”
undefined
: the value of variables that have not been initialized and the value you get when you query the value of an object property or array element that does not exist.
==
and ===
===
: strict equality
==
: allow type conversion