mobile wallpaper 1mobile wallpaper 2mobile wallpaper 3mobile wallpaper 4mobile wallpaper 5
5513 字
15 分钟
Javascript Notes

基本#

动态语言

use strict启用严格模式

推荐使用单引号, 以与HTML区分

注释格式#

  1. //
  2. /*...*/

嵌入方式#

  1. <script>...</script>
    • 在遇到此时会立刻开始下载脚本, 阻塞其余解析, 因此应放到</body>
  2. 放到.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两两元素间组合成字符串, 返回字符串

对象#

  • 键值对的无序集合, 关键字称为属性
  • 关键字类型: stringsymbol, 值类型: 任意
  • {prop1: val1, prop2: val2, ...}定义
  • 计算属性名: {[var]: val}根据变量var自动计算属性名
  • 属性名非合法变量名时, 需用引号包围
  • 属性名非字符串时, 会自动转换为字符串
  • obj.propobj[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指向windowsundefined(严格模式)
  • 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)返回第一个符合条件的元素, 未找到返回undefined
  • arr.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结束, valuereturn值或undefined
  • for (let x of func(args))遍历

计划调度#

  • setTimeout(func, delay, arg1, arg2, ...)delay(单位ms)后执行func(arg1, arg2, ...), 返回一个定时器标识符timer
    • setTimeout(func) 0ms延时意为将当前脚本执行完毕后执行
  • clearTimeout(timer)取消调度
  • setInterval(func, delay, arg1, arg2, ...)每隔delay后执行一次, 返回timer
  • setInterval从函数开始调用时开始计时
  • 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对象
      • 只能调用一次resolvereject
    • 创建Promise时自动运行executor
  • 私有属性:

    • state: 初始为"pending", 调用resolve后自动变为"fulfilled", 调用reject变为"rejected"
    • result: 初始为undefined, 调用resolve后变为value, 调用reject变为error
  • promise.then(result => { ... }, error => { ... })注册回调函数

    • 回调函数可改名

    • 第一个参数在resolved后执行, 第二个参数在rejected后执行

    • 第二个参数可以省略

    • 如果两个参数均省略(或传入null), 不执行操作, 称为Promise穿透

    • 返回新的Promise对象

      1. 若回调函数返回值为普通值: statefulfilled, result为返回值

      2. 若回调函数返回值为另一个Promise对象: stateresult跟随另一个Promise

      3. 若回调函数抛出错误: staterejected, resulterror

      4. Promise穿透: stateresult与原先的promise相同

  • promise.catch(error => { ... })相当于.then省略第一个参数

  • promise.finally(() => { ... })无论resolved还是rejected均执行

    • 返回Promise对象
      • stateresult与原先的promise相同, finally传入函数的返回值无效
      • 仅当finally内部函数抛出错误时, staterejected, resulterror
  • 可以进行链式调用promise.then(return ...).then(return ...).catch(...)

    • 多次调用promise.then(...)则非链式调用, 而是彼此独立运行任务
  • 当一个.then报错, 会跳过后面的所有.then直到一个.catch

    • 因此可以只把.catch写在链的末尾
  • 如果存在没有.catcherror, 触发事件unhandledrejection

  • async function f() { ... }构造Promise对象, 其statefulfilled的值由函数内部决定, 与.then的回调函数规则一致

    • 箭头函数async () => { ... }
  • async函数中, let result = await promise让js引擎等待promise完成并返回结果, 等待期间可以同时执行其它任务

    • module中, 可以在顶层写async
  • Promise.all(iterable)接收一个Promise的可迭代对象, 返回一个并行执行各promisePromise对象

模块#

  • <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)弹出带有文本和输入框的窗口, 返回输入, 取消输入时返回null
    • default可选, 指定输入框的初始值
  • confirm(question)弹出一个是否确认窗口, 返回truefalse

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是否匹配str
  • str.split(re)re切分字符串, 返回切分的字符串数组
  • re.exec(str)匹配分组, 返回匹配的字符串数组, 匹配失败返回null
  • /.../gRegExp(..., 'g')全局匹配, 每次re.exec(str)匹配一组, re.lastIndex存储上次匹配的字符串的下一个字符索引
  • i忽略大小写, m多行匹配

URL#

  • let url = new URL(url, [base])创建URL对象

    • 如有base, url为相对路径
  • 获取各部分

    image-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
      1. 为字符串的数组, 只序列化存在于数组中的属性
      2. 为函数function (key, value), 如返回新值, 则替换原值; 如返回undefined, 则删除键值对
    • space: 美化输出
      1. 为数字, 指定缩进的空格数量
      2. 为字符串, 指定用于缩进的字符
    • obj中若定义toJSON方法, 直接调用该方法输出
      • toJSON无参数, 返回一个object
  • JSON.parse(str, *reviver)将JSON字符串转换为对象
    • reviver为字符串的数组, 只反序列化存在于数组中的属性

网络请求#

  • fetch(url, [options])请求访问url并返回结果的Promise

    • options为对象
      • 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对象

    • statusheaders可省略, status默认值200, headers自动猜测
    • 如果contentstringify字符串, 必须写headers: {"Content-Type": "application/json"}
      • Response.json(content)JSON创建Response对象并自动添加statusheaders
  • 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获取当前页面URL
  • location.protocol, host, port, pathname, search, hash获取当前页面URL各部分
  • location.assign(URL)加载新页面
  • location.reload()刷新页面
  • document DOM树的根节点
  • document.title获取当前页面title
  • document.cookie获取当前页面cookie

DOM#

nodeList分为live(自动更新)和static, 均支持下标访问, for...offorEach()

Node包括元素节点, 文本节点, 注释节点等

获取#

  • document.head, document.body访问<head>, <body>
  • elem.children子元素的live NodeList
  • elem.firstElementChild, elem.lastElementChild首尾子元素
  • elem.parentElement父元素
  • elem.previousElementSibling, elem.nextElementSibling兄弟元素
  • elem.contains(elem2)判断是否为后代元素或elem自身
  • table.rows, table.tHeads, table.tBodies <table>元素中<tr>, <thead>, <tbody>NodeList
  • tr.cells <tr>元素中<td>NodeList

查找#

  • document.querySelector(css)根据CSS选择器字符串匹配第一个元素
  • document.querySelectorAll(css)匹配所有元素, 返回static NodeList
  • document.getElementById(id)返回单个元素或null
  • document.getElementsByName(name)根据元素的name属性查找, 返回NodeList
  • elem.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)检查, 添加或移除某个class
  • elem.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: beforebeginnode之前, afterbeginnode首个子元素之前, beforeend在末尾子节点之后, afterendnode之后
  • 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
  • 元素属性

    • 如下图

      img-width-height

      • clientWidth, clientHeight不包括滚动条
      • offsetWidth, offsetHeight包括滚动条和border
      • scrollWidth, 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>

    • 可以使用thisevent
  • 通过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停止冒泡和当前元素其它处理程序
  • 事件委托: 对于处理程序类似的元素且会冒泡的事件, 将处理程序放在共同祖先上

  • 阻止元素事件的浏览器默认行为:

    1. 使用event.preventDefault()
    2. 通过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分别为左/中/右键, 触摸屏上始终为0
  • event.shiftKey, altKey, ctrlKey, metaKey: 在指针事件的同时按下相应键则为true, 多个组合键用&&判断
  • event.clientX, clientY: 鼠标事件相对于视口的坐标
  • event.pageX, pageY: 鼠标事件相对于文档的坐标
  • event.pointerType = mouse, pen, touch: 指针的设备类型
  • 防止鼠标意外选择文本: onpointerdown=""
  • 多点触控:
    • event.pointerId: 触发当前事件的指针的ID
    • event.isPrimary: 第一个指针为true
  • elem.setPointerCapture(pointerId): 将ID指定的指针绑定到elem, 该指针的后续事件均定位到此元素, 直到:
    • pointeruppointerCancel
    • elem从文档移除
    • 调用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: 元素或页面滚动, 对elemwindow均可用

    • 在普通元素上不冒泡, 但在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>的序号和value
  • option.index, option.text: 选项的编号和文本
  • option.selected: 选项是否被选中
  • new Option(text, value, defaultSelected, selected): 方便地创建<option>元素
    • defaultSelectedselected默认为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事件

其它#

  • displaynone转为显示时, 会覆盖其它过渡效果. 其它过渡应设置setTimeout(..., 20)
封面
Sample Song
Sample Artist
封面
Sample Song
Sample Artist
0:00 / 0:00