DOM、BOM、Window、Document
DOM 是操作文档的 API,Document 是其一个对象。
BOM 是操作浏览器的 API,Window 是其一个对象。
function component(s) {
const element = document.createElement('div');
element.innerHTML = s;
return element;
}
document.body.appendChild(component("hello"));
SSR vs CSR
服务器渲染和客户端渲染。
ES5、ES6、ES2021
两个等号与三个等号的区别
严格相等:===,非严格相等:==。
-
使用
==时,如果两边的类型不一样,会先进行类型转换。 -
===是直接进行比较,不会进行类型转换。
一般不推荐使用 == 了,几乎没有场景适用,比较 null 或 undefined 的话可以直接显式比较,用了 == 还会被人怀疑使用的正确性,增加阅读负担。但是大于等于和小于等于仍然是 >= 和 <=。
变量声明
let
let low = 0;
let low = 0, high = nums.length - 1;
var 和 let
var 在全局级别(函数外部)进行声明会自动变成 Window对象的一个属性:
var name = "John";
window.name === name // true
let 或者 const 则不会:
let name = "John";
window.name === name // false
var 存在变量提升现象:闭包或函数内部重新声明后会对外部相同变量进行覆盖。
const
解构赋值
解构赋值语法是一种 Javascript 表达式。通过解构赋值可以将 属性/值 从 对象/数组 中取出,赋值给其他变量。
function main() {
l = [1, 2, 3];
let [a, b, ...rest] = l;
d = { hello: "world", foo: "bar", other: "other" };
let { hello, foo, ...other } = d;
console.log(a);
console.log(b);
console.log(rest);
console.log(hello);
console.log(foo);
console.log(other);
}
/*
1
2
[ 3 ]
world
bar
{ other: 'other' }
*/
注意通过 map 的 set() 方法赋值的不能进行解构,会得到 undefined。
正则表达式
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Guide/Regular_Expressions
var re = /ab+c/;
// 等价于
var re = new RegExp("ab+c");
循环控制
JS 支持传统的 for 语法,此外还有以下 for 的用法
for … of
for (const element of ['a', 'b', 'c']) {
console.log(element);
}
for … in
for...in 是为遍历对象属性而构建的,不建议与数组一起使用,数组可以用 for...of
for...in 得到的是属性名称。
var obj = {a:1, b:2, c:3};
for (var prop in obj) {
console.log("obj." + prop + " = " + obj[prop]);
}
// Output:
// "obj.a = 1"
// "obj.b = 2"
// "obj.c = 3"
do…while
function main(params) {
let i = 0
do {
console.log(i)
i += 1
} while (i < 10);
}
statement 执行至少一次,并在每次 condition 值为真时重新执行。
while
程序控制
条件判断
需要注意数组越界的问题,不会报错,只会返回 undefined,然后 if 得到的结果就永远是 false。
a = [1]
if(1 < a[-1]) {
console.log("1 < a[-1]");
} else {
console.log("1 > a[-1]");
}
// 1 > a[-1]
console.log(1 < a[-1]);
console.log(1 > a[-1]);
// false
// false
with
严格模式下不允许使用 with 语句,否则将视为语法错误(所以能看懂就行了,尽量别用。。)
var obj = {
host: "https://yindongliang.com",
url: "posts",
};
with (obj) {
host = "https://github.com";
url = "repos";
a = "global";
}
console.log(host); // undefined
console.log(url); // undefined
console.log(a); // global
注意:当 with 的 obj 没有某个属性却在作用域里重新声明的时候,该属性会被泄露到全局变量里。
switch
这里有坑:省略 break 关键字会执行下一个 case
switch (expression) {
case value: statement
break;
case value: statement
break;
case value: statement
break;
default:
...
try…throw…catch…finally
function myFunction() {
var message, x;
message = document.getElementById("p01");
message.innerHTML = "";
x = document.getElementById("demo").value;
try {
if(x == "") throw "值是空的";
if(isNaN(x)) throw "值不是一个数字";
x = Number(x);
if(x > 10) throw "太大";
if(x < 5) throw "太小";
}
catch(err) {
message.innerHTML = "错误: " + err + ".";
}
finally {
document.getElementById("demo").value = "";
}
}
关键字
void 运算符
void 运算符 对给定的表达式进行求值,然后返回 undefined。
void (async function () {
console.log('hello void')
})();
typeof
typeof 的对象一般是对象。
instanceof
instanceof 运算符用于检测构造函数的 prototype 属性是否出现在某个实例对象的原型链上。
扩展运算符 ...
运算符 ~~
~~ 将数据转化为 Number 类型
~~3.141592654 // 3
delete
用于删除对象的某个属性。
const Employee = {
firstname: 'John',
lastname: 'Doe'
};
console.log(Employee.firstname);// expected output: "John"
delete Employee.firstname;
console.log(Employee.firstname);// expected output: undefined
函数
普通函数
function showMessage() {
alert( 'Hello everyone!' );
}
showMessage(); // 函数调用
匿名函数
function main(params) {
params = {hello: "world"}
return function f() {
console.log("hello", params)
}
}
箭头函数
在 js 中区分函数的引用和函数的执行,箭头函数返回的是函数的引用,而不是函数的执行结果。
箭头函数中 this 指的是外部的 this,因为箭头函数没有 this,匿名函数则是内部的 this。
- 箭头函数没有 this
- 箭头函数没有 arguments 变量
- 不能用 new
- 不能用 super
生成器函数
调用一个生成器函数并不会马上执行它里面的语句,而是返回一个这个生成器的 迭代器 ( iterator )对象。当这个迭代器的 next() 方法被首次(后续)调用时,其内的语句会执行到第一个(后续)出现 yield 的位置为止,yield 后紧跟迭代器要返回的值。或者如果用的是 yield*(多了个星号),则表示将执行权移交给另一个生成器函数(当前生成器暂停执行)。
严格模式
- 针对整个脚本文件
在脚本文件的第一行添加
"use strict";
- 针对单个函数
将”use strict”放在函数体的第一行,则整个函数以”严格模式”运行。
function strict(){
"use strict";
return "这是严格模式。";
}
- 将整个脚本文件放在一个立即执行的匿名函数之中。
(function (){
"use strict";
// some code here
})();
类(class)
ES6 引入了面向对象的概念(class)
static
extends
getter 和 setter
get 语法将对象属性绑定到查询该属性时将被调用的函数。
const obj = {
log: ['a', 'b', 'c'],
get latest() {
if (this.log.length === 0) {
return undefined;
}
return this.log[this.log.length - 1];
},
set latest(value) {
console.log(value)
}
};
console.log(obj.latest);
// expected output: "c"
obj.latest = 1
// expected output: 1
constructor
Symbol
如果我们要在对象字面量 {...} 中使用 symbol,则需要使用方括号把它括起来。
let id = Symbol("id");
let user = {
name: "John",
[id]: 123 // 而不是 "id":123
};
这是因为我们需要变量 id 的值作为键,而不是字符串 “id”。
https://zh.javascript.info/symbol#dui-xiang-zi-mian-liang-zhong-de-symbol
this 作用域
Promise,async/await
let promise = new Promise(function(resolve, reject) {
// executor(生产者代码)
});
Promise
由 new Promise 构造器返回的 promise 对象具有以下内部属性:
state— 最初是"pending",然后在resolve被调用时变为"fulfilled",或者在reject被调用时变为"rejected"。result— 最初是undefined,然后在resolve(value)被调用时变为value,或者在reject(error)被调用时变为error。
与最初的 “pending” promise 相反,一个 resolved 或 rejected 的 promise 都会被称为 “settled”。
then/catch/finally
async/await
async function f() {
return 1;
}
在函数前面的 “async” 这个单词表达了一个简单的事情:即这个函数总是返回一个 promise。其他值将自动被包装在一个 resolved 的 promise 中。
await 只在 async 函数内工作。await 实际上会暂停函数的执行,直到 promise 状态变为 settled,然后以 promise 的结果继续执行。这个行为不会耗费任何 CPU 资源,因为 JavaScript 引擎可以同时处理其他任务:执行其他脚本,处理事件等。相比于 promise.then,它只是获取 promise 的结果的一个更优雅的语法,同时也更易于读写。
module 模块
export+import (ES6)
- 命名导出(每个模块包含任意数量)
- 默认导出(每个模块包含一个)
export
// 命名导出
export function hello (s) {
return `hello, ${s}`;
}
import xxx from ‘xxx’
<!doctype html>
<script type="module">
import {hello} from './hello.js'
alert(hello("js"));
</script>
<script nomodule>
alert("no module");
</script>
也可以
import * as hello from './hello.js'
nomodule
旧时的浏览器不理解 type="module", 会运行nomodule的代码块,支持 module 的浏览器不会运行该代码块。
与 Node.js 中 exports 和 required 区别
module.exports+require (node.js)
通过 module.exports 导出:
const car = {
brand: 'Ford',
model: 'Fiesta'
}
module.exports = car
在另一个文件中使用 require:
const car = require('./car')
内存管理
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Memory_Management
参考
- 现代 JavaScript 教程 https://zh.javascript.info/
- ES6 入门教程 https://es6.ruanyifeng.com/
- JavaScript - MDN https://developer.mozilla.org/zh-CN/docs/learn/JavaScript