基本
动态语言
use strict启用严格模式
推荐使用单引号, 以与HTML区分
注释格式
///*...*/
嵌入方式
<script>...</script>- 在遇到此时会立刻开始下载脚本, 阻塞其余解析, 因此应放到
</body>前
- 在遇到此时会立刻开始下载脚本, 阻塞其余解析, 因此应放到
- 放到
.js文件,<script type="module" src="..." ?defer ?async></script>defer: 异步下载, 在HTML解析完成后执行, 适用于大部分脚本async: 异步下载, 下载完成立即执行, 阻塞HTML解析, 适用于独立模块
数据类型
- Number
- 不区分整数, 浮点数
Nan,isNaN()判断是否为`NaN“- “Infinity
: 超过Number.MAX_SAFE_INTEGER(2^53-1)`时
- Boolean
true,false
- String
- BigInt
- null, undefined
- Array
- Object
- Map
- Set
变量
-
变量名可以包含英文, 数字,
$,_, 不能以数字开头 -
let x = ...;声明变量- 可以先声明再赋值
-
const x = ...;声明常量 -
全局变量为
window的属性 -
解构赋值:
let [x, y, z] = [a, b, c];-
可忽略元素:
let [, , z] = [a, b, c] -
可嵌套:
let [x, [y, z]] = [a, [b, c]] -
中括号或花括号需要与源数据对应
-
对对象解构赋值:
- 变量名与对应属性名相同, 不存在则赋值为
undefined - 使用
let {x:a} = {a: val};将a属性值赋给x - 使用默认值:
let {x=default} = {x: val};
- 变量名与对应属性名相同, 不存在则赋值为
-
已声明的变量解构赋值时, 需要将赋值语句用
()包裹 -
[x, y] = [y, x]交换变量 -
解构赋值语句左侧可作为函数形参, 接收一个对象并自动解构绑定:
function func({x, y, z}) { ... }
-
-
parseInt(), parseFloat()将任意类型转换为number -
String()将任意类型转换为string -
判断变量是否存在:
x === undefined -
原始类型(number, string, boolean)的复制为拷贝, 对象的复制为引用
运算符
-
+, -, *, /, %, **, ++, -- -
=, +=, -=, *=, /=, **= -
==, !=, ===, !==, >, <, >=, <===会自动转换数据类型并比较, 不使用, 只使用===
-
&&, ||, !, ? :, ??a ?? b, 如果a不为null/undefined, 则返回a, 否则返回b
-
typeof, instanceof -
., ?.a?.b, 如果a不为null/undefined, 则返回a.b,否则返回undefined- 可以链式调用
a?.b?.c a?.()调用可能存在的函数a(),b?.[key]读取属性
字符串
''或""\转义- 多行字符串用反引号
+连接字符串- 模板字符串
`${arg}`进行格式化 (反引号) str.length获取字符串长度[x]下标访问- [ES2022]
str.at(x)访问, 支持负数索引 - 字符串不可变
- rawstring使用
String.raw`...`
字符串方法
str.toUpperCase(), str.toLowerCase()str.indexOf(substr)返回字符或子串位置索引str.substring(pos1, pos2=end)返回子串str.split(str2)按str2切分字符串, 返回切分的字符串数组
数组
[]或new Array()定义- 数组元素类型不唯一
[x]下标访问, 赋值- 为超出长度的索引赋值合法, 未赋值的元素为
undefined
- 为超出长度的索引赋值合法, 未赋值的元素为
arr.length获取数组长度- 可以给
arr.length重新赋值, 改变后在末尾减少或添加新元素undefined
- 可以给
- [ES2022]
arr.at(x)访问, 支持负数索引
数组方法
arr.indexOf(x)搜索, 返回元素索引arr.slice(pos1, pos2=end)切片, 返回子数组let arr2 = arr1.slice()复制数组
arr.push(val1, val2, ...)在末尾添加若干元素, 返回添加后数组长度arr.pop()删除末尾元素, 返回被删元素arr.unshift(val1, val2, ...), arr.shift()向头部添加或删除arr.sort()排序, 直接修改原数组arr.reverse()反转, 直接修改原数组arr.splice(pos, len, val1, val2, ...)从pos开始删除len个元素, 然后在此处添加val1, val2, ..., 直接修改原数组arr.concat(args)在数组末尾连接另一个数组, 返回新数组args为任意数量元素或数组, 自动拆分合并为一个数组
arr.join(str)将str插入到arr两两元素间组合成字符串, 返回字符串
对象
- 键值对的无序集合, 关键字称为属性
- 关键字类型:
string或symbol, 值类型: 任意 {prop1: val1, prop2: val2, ...}定义- 计算属性名:
{[var]: val}根据变量var自动计算属性名 - 属性名非合法变量名时, 需用引号包围
- 属性名非字符串时, 会自动转换为字符串
obj.prop或obj[prop]访问, 修改值- 属性名非合法变量名时, 只能用
obj[prop]
- 属性名非合法变量名时, 只能用
- 属性名和值为上文变量时, 可省略值, 自动获取上文变量值
let x = 1; let obj = {x, y: 2}; // obj.x === 1 - 访问不存在的属性返回
undefined - 可以直接添加和
delete删除属性 prop in obj判断是否具有属性, 包括继承属性obj.hasOwnProperty(prop)判断自身是否拥有属性, 不包括继承- 遍历时有顺序, 整数属性名升序排列, 其余按添加顺序
Object.assign(dest, src1, src2, ...)将对象src中的属性拷贝到dest对象中Object.values(obj)返回一个obj中所有值的数组
Map
- 任意类型关键字的键值对的有序集合
new Map([[key1, val1], [key2, val2], ...])定义map.get(key)获取值map.set(key, val)设置值, 可以添加不存在的关键字map.has(key)返回是否存在关键字map.delete(key)删除关键字
Set
- 关键字的无序集合
new Set([key1, key2, ...])set.add(key)set.has(key)set.delete(key)
语句
条件判断
if else语句与C语言一致
switch语句与C语言一致, 用===进行比较
0, '', NaN, null, undefined均为false
循环
三段式for循环, while循环, do while循环与C语言一致
for (let prop in ...) 遍历一个对象的所有属性名
for (let x of ...) 遍历一个iterable对象 (包括Array, String, Map, Set)
for (let [key, value] of ...)遍历map
函数
function func(args) { ... }定义函数let func = function (args) { ... };定义匿名函数- 无
return语句时返回undefined - 调用时允许传入任意个参数, 超出或少于要求依然合法
- 少于时接收
undefined, 可能导致返回NaN - 因此需要检查参数
- 少于时接收
- 将
iterable传入函数时可用...iterable展开 - 函数内部变量
arguments, 为传入参数的Array-like对象,arguments.length获取参数数量, 可下标访问 - 剩余参数: 捕获所有未被形参绑定的传入参数, 为数组
function func(a, b, ...rest)定义, 可自定义名字- 若无多余参数, 为空数组
方法
-
作为对象属性的值, 预先定义或以匿名函数定义:
{func: function() { ... }}- 简写:
{func() { ... }}
- 简写:
-
方法内部
this变量指向对象自身this在运行时计算- 方法内部定义的函数中,
this指向windows或undefined(严格模式)
-
以
obj.func()调用时,this指向obj; 单独调用func(),this指向window -
func.apply(obj, [args])手动指定作为this的对象, 参数放入数组, 无参数时为空数组- 非方法时,
obj传入null
- 非方法时,
-
func.call(obj, args)参数不放入数组
数组高阶函数
arr.map(func)返回新数组arr.forEach(func)直接修改原数组arr.reduce(func)返回新数组arr.filter(func)返回新数组arr.sort(func)直接修改原数组func满足a<b时返回负值,a=b时返回0,a>b时返回正值
arr.every(func)判断是否所有元素均满足条件arr.find(func)返回第一个符合条件的元素, 未找到返回undefinedarr.findIndex(func)返回第一个符合条件元素的索引, 未找到返回-1
闭包
可储存内部变量状态, 冻结定义时使用的变量
实现装饰器:
function decorator(func) { return function (...args) { // ...Before calling... const result = func(...args); // ...After calling... return result; } }
let decorated = decorator(myFunc);箭头函数
- 单行:
x => x * x - 多行:
x => { ... return x * x;}return不可省略 - 多个参数:
(x, y, ...rest) => ... - 无参数:
() => ... - 箭头函数中
this由词法作用域决定, 继承自外部最近一层非箭头函数的this值, 一直追溯到全局作用域
标签函数
对于接收字符串插值的函数调用的简化方式
函数func(string, ...values)接收模板字符串和一系列插值表达式, 调用方法为func`...${value}...`;
生成器
- 包含
yield关键字, 结尾为return语句 let gen = func(args)创建生成器对象,gen.next()迭代, 返回对象{value: x, done: true/false}.done===true时表示yield结束,value为return值或undefined- 用
for (let x of func(args))遍历
计划调度
setTimeout(func, delay, arg1, arg2, ...)在delay(单位ms)后执行func(arg1, arg2, ...), 返回一个定时器标识符timersetTimeout(func)0ms延时意为将当前脚本执行完毕后执行
clearTimeout(timer)取消调度setInterval(func, delay, arg1, arg2, ...)每隔delay后执行一次, 返回timersetInterval从函数开始调用时开始计时clearInterval(timer)取消调度
类
class MyClass { constructor() { ... } method() { ... }}定义new调用constructor()构造器, 内部使用this.prop = val设置属性- 类实质为函数
- 类方法不可枚举
- 类自动使用
use strict - 类可以作为变量值, 或创建匿名类
- 类字段
class MyClass { x = val; }- 使用
func = () => { ... }定义函数, 传递时不会丢失this
- 使用
static关键字定义静态方法和属性class Class1 extends Class2 {}继承类class MyClass extends func(args) {}通过返回类的函数func生成类
super(args)调用父类的构造器- 子类重写构造器时, 必须在构造器开头调用
super()
- 子类重写构造器时, 必须在构造器开头调用
super.method(args)调用父类方法method
错误处理
try { ... } catch (e) { ... } finally { ... }err为捕获的Error对象, 属性:name,message,stack调用栈字符串- 可以省略
(e)
- 可以省略
if (err instance of ErrorType)判断异常类型- 计划调度的函数无法被捕获
throw new Error(message)抛出异常try...finally用于不捕获异常, 但始终执行finally语句windows.onerror全局catch, 捕获所有未捕获的异常
异步
-
new Promise((resolve, reject) => { ... })构造Promise对象- 传入
executor函数,resolve,reject为js自身提供的函数, 直接使用- 如果任务完成, 应调用
resolve(value),value为期望的返回值 - 如果出现错误, 应调用
reject(error),error为要抛出的Error对象 - 只能调用一次
resolve和reject
- 如果任务完成, 应调用
- 创建
Promise时自动运行executor
- 传入
-
私有属性:
state: 初始为"pending", 调用resolve后自动变为"fulfilled", 调用reject变为"rejected"result: 初始为undefined, 调用resolve后变为value, 调用reject变为error
-
promise.then(result => { ... }, error => { ... })注册回调函数-
回调函数可改名
-
第一个参数在
resolved后执行, 第二个参数在rejected后执行 -
第二个参数可以省略
-
如果两个参数均省略(或传入null), 不执行操作, 称为Promise穿透
-
返回新的
Promise对象-
若回调函数返回值为普通值:
state为fulfilled,result为返回值 -
若回调函数返回值为另一个
Promise对象:state和result跟随另一个Promise -
若回调函数抛出错误:
state为rejected,result为error -
Promise穿透:
state和result与原先的promise相同
-
-
-
promise.catch(error => { ... })相当于.then省略第一个参数 -
promise.finally(() => { ... })无论resolved还是rejected均执行- 返回
Promise对象state和result与原先的promise相同,finally传入函数的返回值无效- 仅当
finally内部函数抛出错误时,state为rejected,result为error
- 返回
-
可以进行链式调用
promise.then(return ...).then(return ...).catch(...)- 多次调用
promise.then(...)则非链式调用, 而是彼此独立运行任务
- 多次调用
-
当一个
.then报错, 会跳过后面的所有.then直到一个.catch- 因此可以只把
.catch写在链的末尾
- 因此可以只把
-
如果存在没有
.catch的error, 触发事件unhandledrejection -
async function f() { ... }构造Promise对象, 其state和fulfilled的值由函数内部决定, 与.then的回调函数规则一致- 箭头函数
async () => { ... }
- 箭头函数
-
在
async函数中,let result = await promise让js引擎等待promise完成并返回结果, 等待期间可以同时执行其它任务- 在
module中, 可以在顶层写async
- 在
-
Promise.all(iterable)接收一个Promise的可迭代对象, 返回一个并行执行各promise的Promise对象
模块
<script type="module">标明脚本为模块- 模块始终在严格模式下运行
- 模块脚本延迟加载
- 模块只在第一次导入时解析
- 导出:
- 在任何声明前加
export关键字以导出变量/函数/类, 之后该模块可以在外部被访问 - 也可使用
export {varA, classB}导出 export {varA as a, classB as b}对导出内容重命名
- 在任何声明前加
- 导入:
import {varA, classB} from '.../module.js'导入模块的内容import * as obj from ...导入所有内容为obj对象的属性, 以obj.xx使用import {varA as a, classB as b} from ...对导入内容重命名
- 对于只存放单个实体的模块, 在声明前使用
export default, 此时在导入时不加花括号import classA from ...
弹窗
alert(message)弹出一条信息prompt(title, *default)弹出带有文本和输入框的窗口, 返回输入, 取消输入时返回nulldefault可选, 指定输入框的初始值
confirm(question)弹出一个是否确认窗口, 返回true或false
Date
let now = new Date()获取当前时间let date = new Date(YYYY, MM, DD, hh, mm, ss)或Date(timestampInt)创建指定时间date.getFullYear()四位数年份, getMonth(), getDate()日, getDay()星期几, getHours(), getMinutes(), getSeconds(), getMilliseconds(), getTime()时间戳int- 月份从0开始计数
RegExp
- 通过
let re = /.../;或let re = new RegExp('...');定义- 第一种写法不需考虑
\\转义
- 第一种写法不需考虑
re.test(str)判断re是否匹配strstr.split(re)按re切分字符串, 返回切分的字符串数组re.exec(str)匹配分组, 返回匹配的字符串数组, 匹配失败返回null/.../g或RegExp(..., 'g')全局匹配, 每次re.exec(str)匹配一组,re.lastIndex存储上次匹配的字符串的下一个字符索引i忽略大小写,m多行匹配
URL
-
let url = new URL(url, [base])创建URL对象- 如有
base,url为相对路径
- 如有
-
获取各部分

-
?...搜索参数:url.searchParams下的方法:append(name, value)添加参数set(name, value)设置参数, 移除重复值delete(name)移除参数get(name)获取参数getAll(name)获取相同命名的参数has(name)参数是否存在的布尔值- 可按
map方式迭代
JSON
- 数据类型:
number, boolean, string, array, null, object - 字符串使用
"" JSON.stringify(obj, *replacer, *space)将对象序列化, 返回JSON格式字符串replacer- 为字符串的数组, 只序列化存在于数组中的属性
- 为函数
function (key, value), 如返回新值, 则替换原值; 如返回undefined, 则删除键值对
space: 美化输出- 为数字, 指定缩进的空格数量
- 为字符串, 指定用于缩进的字符
obj中若定义toJSON方法, 直接调用该方法输出toJSON无参数, 返回一个object
JSON.parse(str, *reviver)将JSON字符串转换为对象reviver为字符串的数组, 只反序列化存在于数组中的属性
网络请求
-
fetch(url, [options])请求访问url并返回结果的Promiseoptions为对象method: 'GET', 'POST', ...指定请求方法headers: {'Authentication': 'secret', ...}指定请求头, 值为对象body要发送的数据, 值为JSON字符串,FormData,blob等
-
new Request(url, {method: ..., headers: ..., body: ...})手动创建Request对象 -
let response = await fetch(...)下载响应头并得到Response对象 -
new Response(content[, {status: ..., headers: ...}])手动创建Response对象status和headers可省略,status默认值200,headers自动猜测- 如果
content为stringify字符串, 必须写headers: {"Content-Type": "application/json"}Response.json(content)为JSON创建Response对象并自动添加status和headers
-
response.status请求的HTTP状态码 -
response.ok布尔值, 当status为200~299为true -
response.headers获取响应头response.headers.get(name)按name字符串获取一个header并返回for (let [key, value] of response.headers)遍历
-
响应体读取方法(均返回
Promise, 使用await下载响应体并获得结果):response.text()纯文本格式response.json()JSON对象response.formData()FormData对象- 同一
reponse只能使用一种读取方法
FormData
let formData = new FormData(form)创建FormData对象,form为表单元素formData.append(name, value)添加表单字段, 会重复添加formData.set(name, value)设置表单字段, 重复的会清除formData.delete(name)删除字段formData.get(name)获取字段值formData.has(name)返回给定字段是否存在的布尔值
实践
-
获取数据:
async function getData() {try {const response = await fetch("/api/data");return await response.json();} catch (e) {return Response.json({success: false,error: e.message},{status: 500});}}async function operation() {const data = await getData();// Operations here...} -
手动提交表单
form.addEventListener('submit', async () => {event.preventDefault();const formData = new formData(form);const response = await fetch(url, {method: 'POST',body: formData});})
BOM
navigator.userAgent, language, platform获取浏览器信息screen.width, screen.height, screen.colorDepth获取客户端显示器屏幕的宽度, 高度, 颜色位数location.href获取当前页面URLlocation.protocol, host, port, pathname, search, hash获取当前页面URL各部分location.assign(URL)加载新页面location.reload()刷新页面documentDOM树的根节点document.title获取当前页面titledocument.cookie获取当前页面cookie
DOM
nodeList分为live(自动更新)和static, 均支持下标访问, for...of和forEach()
Node包括元素节点, 文本节点, 注释节点等
获取
document.head, document.body访问<head>, <body>elem.children子元素的live NodeListelem.firstElementChild, elem.lastElementChild首尾子元素elem.parentElement父元素elem.previousElementSibling, elem.nextElementSibling兄弟元素elem.contains(elem2)判断是否为后代元素或elem自身table.rows, table.tHeads, table.tBodies<table>元素中<tr>, <thead>, <tbody>的NodeListtr.cells<tr>元素中<td>的NodeList
查找
document.querySelector(css)根据CSS选择器字符串匹配第一个元素document.querySelectorAll(css)匹配所有元素, 返回static NodeListdocument.getElementById(id)返回单个元素或nulldocument.getElementsByName(name)根据元素的name属性查找, 返回NodeListelem.matches(css)判断元素是否匹配选择器elem.closest(css)查找匹配选择器的最近的祖先或自身
属性和修改
elem.tagName获取元素标签名elem.textContent获取或设置元素及所有后代元素的纯文本elem.innerHTML获取或设置元素内部的完整HTML标记elem.outerHTML获取或设置包括元素自身的完整HTML标记elem.src, elem.id等获取或设置HTML属性elem.setAttribute(name, val), getAttribute(name), removeAttribute(name)修改HTML属性elem.dataset.<attr>获取和修改自定义特性, 特性名转换为小驼峰elem.classList.contains(className), add(className), remove(className)检查, 添加或移除某个classelem.className获取或修改整个class字符串elem.classList.toggle(className)如果在某个class中, 则将其移除, 反之添加elem.style.border, elem.style.fontSize获取或设置内联CSS属性, 属性名转换为小驼峰, 无法获取样式表let computed = getComputedStype(elem, ?pseudo)获取计算后的最终样式- 随后使用
computed.prop获取值 elem.style.removeProperty(prop)删除style
插入
document.createElement(tagname)返回创建新元素node.cloneNode(deep)返回当前节点的复制deep: true表示复制所有后代
node.append(nodes or string), prepend()在node子节点末尾或开头插入元素或字符串- 如果已经在其中, 则从原位置移除并移动到新位置
node.before(nodes or string), after()在node之前或之后插入node.replaceWith(nodes or strings)将node替换为节点或字符串node.insertAdjacentHTML(position, text)解析HTML字符串, 在position指定的位置插入HTML结构position:beforebegin在node之前,afterbegin在node首个子元素之前,beforeend在末尾子节点之后,afterend在node之后
elem.innerHTML可快速添加元素, 但须防范注入攻击(比如只用来创建空元素)document.createDocumentFragment()创建文档片段, 不直接在DOM中操作以增加性能- 对
fragment与对元素的操作一致 - 最后将
fragment插入DOM中, 原fragment会自动清空
- 对
删除
elem.remove()删除节点elem.innerHTML = ''删除所有子节点
尺寸与坐标
-
window属性window.innerWidth, window.innerHeight获取浏览器窗口内部宽高(去除菜单栏, 工具栏等) (包括滚动条)window.outerWidth, window.outerHeight获取浏览器外部宽高window.scrollX, scrollY获取文档已滚动的距离, 相当于document.documentElement.scrollTop, scrollLeft
-
元素属性
-
如下图

clientWidth, clientHeight不包括滚动条offsetWidth, offsetHeight包括滚动条和borderscrollWidth, scrollHeight为总宽高, 包括未显示部分scrollLeft, scrollTop为已滚动的距离offsetLeft, offsetTop为偏移父元素的距离
-
document.documentElement.prop用于获取文档作为元素的属性 -
elem.getBoundingClientRect()返回相对于窗口的DOMRect对象(只读)x, y矩形左上角相对于窗口内部的坐标width, height矩形的宽高left, right, top, bottom各边界的坐标
-
-
document.elementFromPoint(x, y)获取坐标处最上层的元素 -
window.scrollTo(x, y), window.scrollBy(x, y)将文档滚动到绝对坐标或相对坐标- 或使用对象作为参数
windows.scrollTo({left: x, top: y, behavior: 'smooth'})实现平滑滚动
- 或使用对象作为参数
-
elem.scrollIntoView(top)滚动文档使elem可见top=true(default)时,elem定位在窗口顶部, 反之在底部
事件
-
通过HTML元素
on<event>="function()"属性添加,function()定义在<script>中- 可以使用
this和event
- 可以使用
-
通过
elem.on<event> = function() { ... }添加- 如需捕获事件属性, 应添加形参
event
- 如需捕获事件属性, 应添加形参
-
通过
elem.addEventListener(event, handler, options)event: 事件名, 如"click"handler:- 为函数: 处理程序
- 为
object或类实例: 调用对象中的handleEvent方法
options:- 为
object:{capture: false, once: false, passive: false, signal: null}capture: 是否在捕获阶段处理事件once: 是否在调用后自动移除监听器passive: 是否不调用event.preventDefault()- 用于优化滚动
signal:AbortSignal对象, 当关联的AbortController调用abort()时移除监听器
- 为
boolean: 对应capture属性
- 为
-
elem.removeEventListener(event, handler, options): 移除监听器, 参数需与添加时完全相同.handler需为同一函数的引用, 因此需要命名函数
处理程序
-
冒泡: 事件首先运行该元素上的处理程序, 然后依次运行父元素的处理程序
-
小部分事件不冒泡
- 后文若不注明则默认冒泡
-
处理程序中
this = event.currentTarget表示冒泡到的当前元素 -
event.Target: 引发事件的元素 -
event.stopPropagation(): 停止冒泡, 继续当前元素其它处理程序event.stopImmediatePropagation停止冒泡和当前元素其它处理程序
-
事件委托: 对于处理程序类似的元素且会冒泡的事件, 将处理程序放在共同祖先上
-
阻止元素事件的浏览器默认行为:
- 使用
event.preventDefault() - 通过
on<event>分配处理程序中返回false. 否则函数结束后继续执行默认行为
- 使用
-
event.defaultPrevented: 默认行为阻止时为true
鼠标事件
pointer事件对鼠标/触摸屏均有效, 旧版为mouse事件- 事件类型:
pointerdown, pointerup: 在元素上点击/松开指针pointerover, pointerout: 将指针移入/移出元素event.target: 对应元素event.relatedTarget: 另一个元素, 或为null- 快速移动时元素可能会被略过
- 移入后代视为移出父元素
- 会冒泡
pointerenter, pointerleave: 忽略后代间的移动- 不会冒泡
pointermove: 鼠标在元素上的所有移动click, dblclick: 单击/双击(松开时记录)contextmenu: 右键或其它方式打开上下文菜单pointercancel: 指针交互被中断
event.button: 获取按键, 鼠标上0, 1, 2分别为左/中/右键, 触摸屏上始终为0event.shiftKey, altKey, ctrlKey, metaKey: 在指针事件的同时按下相应键则为true, 多个组合键用&&判断event.clientX, clientY: 鼠标事件相对于视口的坐标event.pageX, pageY: 鼠标事件相对于文档的坐标event.pointerType = mouse, pen, touch: 指针的设备类型- 防止鼠标意外选择文本:
onpointerdown="" - 多点触控:
event.pointerId: 触发当前事件的指针的IDevent.isPrimary: 第一个指针为true
elem.setPointerCapture(pointerId): 将ID指定的指针绑定到elem, 该指针的后续事件均定位到此元素, 直到:pointerup或pointerCancelelem从文档移除- 调用
elem.releasePointerCapture(pointerId)
键盘事件
keydown, keyup: 键盘按下(或不松手自动重复)和抬起event.key: 按下的字符内容, 受键盘布局和功能键的影响- 大小写字母值不同
A, a, ... - 主键盘和小数字键盘值相同
1, 2, ..., - 功能键左右不分开
Shift, Capslock, Backspace, ArrowUp, ... - 空格为
" "
- 大小写字母值不同
event.code: 按键的物理位置, 同一位置按键的code唯一- 字母键始终为
KeyA, KeyB, ... - 数字键
Digit1, Digit2, ...小键盘Numpad1, NumpadEnter... - 功能键
ShiftLeft, ControlRight, ...其余与event.key相同 - 空格为
Space - 不同布局的键盘在同一位置上的按键可能不同
- 字母键始终为
event.repeat: 当keydown事件为自动重复引起时为true
其它事件
-
scroll: 元素或页面滚动, 对elem和window均可用- 在普通元素上不冒泡, 但在
window上能捕获
- 在普通元素上不冒泡, 但在
-
beforeunload: 在window对象上, 当用户试图离开页面时触发(关闭, 点击外部链接, 刷新等)-
使离开时确认:
window.addEventListener('beforeunload', (event) => {event.preventDefault();event.returnValue = ''; // 兼容性return ''; // 兼容性});
-
-
unload: 在window对象上, 离开页面时触发
表单
获取和更改
- 所有
<form>元素存放在document.forms类数组对象. 获取form元素方式:- 序号下标
["name"](<form>的name属性).name(IDE可能报错)
form.name: 表单中name=name的元素- 多个元素
name相同时, 返回一个类数组对象
- 多个元素
- 获取
<fieldset>中元素与<form>的操作类似 elem.form: 反向获取表单元素对应的表单input.value, textarea.value: 输入框的值input.checked: 选项的布尔值select.options: 返回<select>中<option>的类数组对象select.selectedIndex, select.value: 当前所选择的<option>的序号和valueoption.index, option.text: 选项的编号和文本option.selected: 选项是否被选中new Option(text, value, defaultSelected, selected): 方便地创建<option>元素defaultSelected和selected默认为false, 设置时应同时设为true
事件
- 聚焦
focus: 表单元素获得聚焦(点击或Tab选中)- 不冒泡
blur: 表单元素失去焦点(点击其它元素, Tab导航下一个元素, 元素从DOM中移除)- 不冒泡
focusin, focusout会冒泡alert会将焦点从元素移动到自身, 对话框取消后回到原元素elem.focus(), elem.blur(): 手动设置或移除焦点- 定义
tabindex特性的元素也具有聚焦事件
input: 元素值更改. 每次值改变时触发, 包括粘贴/撤销event.data: 本次输入的数据- 无法用
preventDefault()阻止
change: 元素更改完成. 对于文本框, 更改后失去焦点时触发; 其它立即触发cut, copy: 在元素上剪切/复制preventDefault()+event.clipboardData.setData(format, data)此时向剪切板写入内容format:"text/plain": 纯文本"text/html": 包含HTML标签
event.clipboardData.clearData(): 清空剪切板数据
paste: 在元素上粘贴event.clipboardData.getData(format): 此时读取剪切板内容
submit: 提交表单(点击<input type="sumbit"/"image">或在<input>元素上按下Enter)- 按Enter提交表单时, 会触发
click事件 form.submit(): 手动提交表单, 不触发submit事件
- 按Enter提交表单时, 会触发
其它
display从none转为显示时, 会覆盖其它过渡效果. 其它过渡应设置setTimeout(..., 20)



