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