(蓝桥杯)Web前端考纲知识点总结
HTML5新特性
语义标签
标签 | 描述 |
---|---|
<header> | 定义了文档的头部区域 |
<footer> | 定义了文档的尾部区域 |
<nav> | 定义文档的导航 |
<section> | 定义文档中的节 |
<article> | 定义文章 |
<aside> | 定义页面以外的内容 |
<details> | 定义用户可以看到或者隐藏的额外细节 |
<summary> | 标签包含details元素的标题 |
<dialog> | 定义对话框 |
<figure> | 定义自包含内容,如图表 |
<main> | 定义文档主内容 |
<mark> | 定义文档的主内容 |
<time> | 定义日期/时间 |
增强表单
html5修改一些新的input输入特性,改善更好的输入控制和验证
输入类型 | 描述 |
---|---|
color | 主要用于选取颜色 |
date | 选取日期 |
datetime | 选取日期(UTC时间) |
datetime-local | 选取日期(无时区) |
month | 选择一个月份 |
week | 选择周和年 |
time | 选择一个时间 |
包含e-mail地址的输入域 | |
number | 数值的输入域 |
url | url地址的输入域 |
tel | 定义输入电话号码和字段 |
search | 用于搜索域 |
range | 一个范围内数字值的输入域 |
html5新增了五个表单元素
<datalist> | 用户会在他们输入数据时看到域定义选项的下拉列表 |
---|---|
<progress> | 进度条,展示连接/下载进度 |
<meter> | 刻度值,用于某些计量,例如温度、重量等 |
<keygen> | 提供一种验证用户的可靠方法生成一个公钥和私钥 |
<output> | 用于不同类型的输出比如尖酸或脚本输出 |
html5新增表单属性
属性 | 描述 |
---|---|
placehoder | 输入框默认提示文字 |
required | 要求输入的内容是否可为空 |
pattern | 描述一个正则表达式验证输入的值 |
min/max | 设置元素最小/最大值 |
step | 为输入域规定合法的数字间隔 |
height/wdith | 用于image类型<input> 标签图像高度/宽度 |
autofocus | 规定在页面加载时,域自动获得焦点 |
multiple | 规定<input> 元素中可选择多个值 |
视频和音频
视频播放:
1 | <video src=""><video> |
查看视频的所有属性、方法、事件:
1 | console.log(videoBirds); |
音频播放:
1 | <audio src=""></audio> |
查看视频的所有属性、方法、事件:
1 | console.log(bgMusic); |
Canvas绘图
SVG绘图
什么是SVG?
SVG指可伸缩矢量图形
SVG用于定义用于网络的基于矢量的图形
SVG使用XML格式定义图形
SVG图像在放大或改变尺寸的情况下其图形质量不会有损失
SVG是万维网联盟的标准
SVG的优势
与其他图像格式相比,是哟个SVG的优势在于:
SVG图像可通过文本编译器来创建和修改
SVG图像可被搜索、索引、脚本化或压缩
SVG是可伸缩的
SVG图像可在任何的分辨率下被高质量的打印
SVG可在图像质量不下降的情况下被放大
SVG与Canvas区别
SVG适用于描述XML中的2D图形的语言
Canvas随时随地绘制2D图形(使用javaScript)
SVG是基于XML的,意味这可以操作DOM,渲染速度较慢
在SVG中每个形状都被当做是一个对象,如果SVG发生改变,页面就会发生重绘
Canvas是一像素一像素地渲染,如果改变某一个位置,整个画布会重绘。
Canvas | SVG |
---|---|
依赖分辨率 | 不依赖分辨率 |
不支持事件处理器 | 支持事件处理器 |
能够以.png或.jpg格式保存结果图像 | 复杂度会减慢搞渲染速度 |
文字呈现功能比较简单 | 适合大型渲染区域的应用程序 |
最合适图像密集的游戏 | 不适合游戏应用 |
地理定位
使用getCurrentPosition()方法来获取用户的位置。以实现“LBS服务”
1 | var x = document.getElementById("demo"); |
拖放API
拖放是一种常见的特性,即捉取对象以后拖到另一个位置。在html5中,拖放是标准的一部分,任何元素都能够拖放。
1 | <div draggable="true" ondragstart="drag(event)"></div> |
拖动生命周期 | 属性名 | 描述 |
---|---|---|
拖动开始 | ondragstart | 在拖动操作开始时执行脚本 |
拖动过程中 | ondrag | 只要脚本在被拖动就运行脚本 |
拖动过程中 | ondragenter | 当元素被拖动到一个合法的防止目标时,执行脚本 |
拖动过程中 | ondragover | 只要元素正在合法的防止目标上拖动时,就执行脚本 |
拖动过程中 | ondragleave | 当元素离开合法的防止目标时 |
拖动结束 | ondrop | 将被拖动元素放在目标元素内时运行脚本 |
拖动结束 | ondragend | 在拖动操作结束时运行脚本 |
Web Worker
Web Worker可以通过加载一个脚本文件,进而创建一个独立工作的线程,在主线程之外运行。
基本使用:
Web Worker的基本原理就是在当前javascript的主线程中,使用Worker类加载一个javascript文件来开辟一个新的线程,
起到互不阻塞执行的效果,并且提供主线程和新县城之间数据交换的接口:postMessage、onmessage。
1 |
|
Web Storage
WebStorage是HTML新增的本地存储解决方案之一,但并不是取代cookie而指定的标准,cookie作为HTTP协议的一部分用来处理客户端和服务器的通信是不可或缺的,session正式依赖与实现的客户端状态保持。WebSorage的意图在于解决本来不应该cookie做,却不得不用cookie的本地存储。
websorage拥有5M的存储容量,而cookie却只有4K,这是完全不能比的。
客户端存储数据有两个对象,其用法基本是一致。
localStorage:没有时间限制的数据存储
sessionStorage:在浏览器关闭的时候就会清除。
1 | localStorage.setItem(key,value);//保存数据 |
WebSocket
WebSocket协议为web应用程序客户端和服务端之间提供了一种全双工通信机制。
特点:
(1)握手阶段采用HTTP协议,默认端口是80和443
(2)建立在TCP协议基础之上,和http协议同属于应用层
(3)可以发送文本,也可以发送二进制数据。
(4)没有同源限制,客户端可以与任意服务器通信。
(5)协议标识符是ws(如果加密,为wss),如ws://localhost:8023
弹性盒子常用属性
display:flex; *如果用了弹性布局,子元素不需要浮动*
justify-content: 子元素水平排列方式方式。
属性 | 描述 |
---|---|
center | 水平居中 |
space-between | 两端对齐 |
space-around | 手拉手平均分 |
flex-start | 居左对齐 |
flex-end | 居右对齐 |
align-items: 子元素垂直排列
属性 | 描述 |
---|---|
center | 垂直居中 |
space-between | 上下两端对齐 |
space-around | 手拉手上下平均分 |
flex-start | 顶部对齐 |
flex-end | 底部对齐 |
flex-direction: 排列方式
属性 | 描述 |
---|---|
row | 默认值 横向排列 |
row-reverse | 横向颠倒排列 |
column | 垂直排列 |
column-reverse | 垂直颠倒排列 |
flex-wrap: 默认no-wrap让元素步换行
属性 | 描述 |
---|---|
wrap | 换行 |
nowrap | 不换行 |
align-content: 控制容器内多行在Y轴上的排列方式
属性 | 描述 |
---|---|
stretch | 默认值 |
center | 居中对齐 |
flex-start | 顶部对齐 |
flex-end | 底部对齐 |
space-between | 上下对齐 |
space-around | 上下手拉手对齐 |
子级
flex:1 1指的是一个系数 *子元素再划分父元素宽度,先刨除固定宽度
flex-grow:1 定义子元素放大比例
媒体查询
使用 @media 查询,你可以针对不同的媒体类型定义不同的样式。
@media 可以针对不同的屏幕尺寸设置不同的样式,特别是如果你需要设置设计响应式的页面,@media 是非常有用的。
当你重置浏览器大小的过程中,页面也会根据浏览器的宽度和高度重新渲染页面。
语法
1、在CSS里使用:
1 | @media 类型 and (条件1) and (条件二) |
2、使用@import导入
1 | @import url("css/css.css") all and (max-width:980px); |
3、link连接
1 | <link rel="stylesheet" media="mediatype and|not|only (media feature)" href="css.css"> |
媒体类型
值 | 描述 |
---|---|
all | 用于所有设备 |
aural | 已废弃。用于语音和声音合成器 |
braille | 已废弃。 应用于盲文触摸式反馈设备 |
embossed | 已废弃。 用于打印的盲人印刷设备 |
handheld | 已废弃。 用于掌上设备或更小的装置,如PDA和小型电话 |
用于打印机和打印预览 | |
projection | 已废弃。 用于投影设备 |
screen | 用于电脑屏幕,平板电脑,智能手机等。 |
speech | 应用于屏幕阅读器等发声设备 |
tty | 已废弃。 用于固定的字符网格,如电报、终端设备和对字符有限制的便携设备 |
tv | 已废弃。 用于电视和网络电视 |
媒体功能
值 | 描述 |
---|---|
aspect-ratio | 定义输出设备中的页面可见区域宽度与高度的比率 |
color | 定义输出设备每一组彩色原件的个数。如果不是彩色设备,则值等于0 |
color-index | 定义在输出设备的彩色查询表中的条目数。如果没有使用彩色查询表,则值等于0 |
device-aspect-ratio | 定义输出设备的屏幕可见宽度与高度的比率。 |
device-height | 定义输出设备的屏幕可见高度。 |
device-width | 定义输出设备的屏幕可见宽度。 |
grid | 用来查询输出设备是否使用栅格或点阵。 |
height | 定义输出设备中的页面可见区域高度。 |
max-aspect-ratio | 定义输出设备的屏幕可见宽度与高度的最大比率。 |
max-color | 定义输出设备每一组彩色原件的最大个数。 |
max-color-index | 定义在输出设备的彩色查询表中的最大条目数。 |
max-device-aspect-ratio | 定义输出设备的屏幕可见宽度与高度的最大比率。 |
max-device-height | 定义输出设备的屏幕可见的最大高度。 |
max-device-width | 定义输出设备的屏幕最大可见宽度。 |
max-height | 定义输出设备中的页面最大可见区域高度。 |
max-monochrome | 定义在一个单色框架缓冲区中每像素包含的最大单色原件个数。 |
max-resolution | 定义设备的最大分辨率。 |
max-width | 定义输出设备中的页面最大可见区域宽度。 |
min-aspect-ratio | 定义输出设备中的页面可见区域宽度与高度的最小比率。 |
min-color | 定义输出设备每一组彩色原件的最小个数。 |
min-color-index | 定义在输出设备的彩色查询表中的最小条目数。 |
min-device-aspect-ratio | 定义输出设备的屏幕可见宽度与高度的最小比率。 |
min-device-width | 定义输出设备的屏幕最小可见宽度。 |
min-device-height | 定义输出设备的屏幕的最小可见高度。 |
min-height | 定义输出设备中的页面最小可见区域高度。 |
min-monochrome | 定义在一个单色框架缓冲区中每像素包含的最小单色原件个数 |
min-resolution | 定义设备的最小分辨率。 |
min-width | 定义输出设备中的页面最小可见区域宽度。 |
monochrome | 定义在一个单色框架缓冲区中每像素包含的单色原件个数。如果不是单色设备,则值等于0 |
orientation | 定义输出设备中的页面可见区域高度是否大于或等于宽度。 |
resolution | 定义设备的分辨率。如:96dpi, 300dpi, 118dpcm |
scan | 定义电视类设备的扫描工序。 |
width | 定义输出设备中的页面可见区域宽度。 |
JavaScript 基础语法
变量
变量保存的数据可以在需要时设置,更新或提取。赋值给变量的值都有对应的类型。JavaScript的类型有数、字符串、布尔值、函数、对象,还有undefined和null,以及数组、日期和正则表达式
变量作用域
作用域是指,在编写的算法函数中,我们能访问变量(在使用函数作用域时,也可以是一个函数)的地方。有局部变量和全局变量两种。
全局变量
1 | var a = 'global'; |
局部变量
1 | function test(){ |
例子:
1 | var myVariable = 'global'; |
运算符
算数运算符
运算符 | 描述 |
---|---|
+ | 加法 |
- | 减法 |
* | 乘法 |
/ | 除法 |
% | 系数 |
++ | 递加 |
– | 递减 |
赋值运算符
运算符 | 描述 |
---|---|
= | 赋值 |
+= | 加赋值(x += y) == (x = x + y) |
-= | 减赋值(x -= y) == (x = x - y) |
*= | 乘赋值(x *= y) == (x = x * y) |
/= | 除赋值(x /= y) == (x = x / y) |
%= | 取余赋值(x %= y) == (x = x % y) |
比较运算符
运算符 | 描述 |
---|---|
运算符 | 描述 |
== | 等于 |
=== | 等值等型 |
!= | 不相等 |
!== | 不等值或不等型 |
|大于
<|小于
=|大于或等于
<=|小于或等于
?|三元运算符
逻辑运算符
运算符 | 描述 |
---|---|
&& | 逻辑与 |
|| | 逻辑或 |
! | 逻辑非 |
位运算符
运算符 | 描述 | 例子 | 等同于 | 结果 | 十进制 |
---|---|---|---|---|---|
& | 与 | 5 & 1 | 0101 & 0001 | 0001 | 1 |
| | 或 | 5 | 1 | 0101 | 0001 | 0101 |
~ | 非 | ~ 5 | ~0101 | 1010 | 10 |
^ | 异或 | 5 ^ 1 | 0101 ^ 0001 | 0100 | 4 |
<< | 零填充左位移 | 5 << 1 | 0101 << 1 | 1010 | 10 |
|有符号右位移| 5 >> 1|0101 >> 1|0010|2
|零填充右位移|5 >>> 1|0101 >>> 1|0010|2
类型运算符
运算符 | 描述 |
---|---|
typeof | 返回变量的类型。 |
instanceof | 返回 true,如果对象是对象类型的实例。 |
真值和假值
在JavaScript中,true和false有些复杂。在大多数编程语言中,布尔值true和false仅仅表示true/false结果。在JavaScript中,如abc这样的字符,也可以看作true。
数值类型 | 转换成布尔值 |
---|---|
undefined | false |
null | false |
布尔值 | true是true,false是false |
数 | +0,-0和NaN都是false,其它都是true |
字符串 | 如果字符串长度为零就是false,其它都是true |
对象 | true |
让我们用代码来验证上面的总结。
1 | function demo(val){ |
这两个相等运算符的使用可能会引起一些困惑。
我们来分析一下两者不同
相等运算符(==和===)
“==” 的比较规则
- 先检查两个操作数的数据类型是否相同
- 如果相同,则比较两个数是否相等
- 如果不同,则先将两个数转换为相同数据类型,再进行比较
我们用表格来分析一下不同类型的值用相等运算符比较后的结果:
类型(x) | 类型(y) | 结果 |
---|---|---|
null | undefined | true |
undefined | null | true |
数 | 字符串 | x == toNumber(y) |
字符串 | 数 | toNumber(x) == y |
布尔值 | 任何类型 | toNumber(x) == y |
任何类型 | 布尔值 | x == toNumber(y) |
字符串或数 | 对象 | x == toPrimitive(y) |
对象 | 字符串或数 | toPrimitive(x) == y |
- 如果两个操作数都是对象,则仅当两个操作数都引用同一个对象时才返回true。
- 如果一个操作数是null,另一个操作数是undefined,则返回true。
- 如果两个操作数是不同类型的,就会尝试在比较之前将它们转换为相同类型:
- 当数字与字符串进行比较时,会尝试将字符串转换为数字值。
- 如果操作数之一是Boolean,则将布尔操作数转换为1或0。
- 如果操作数之一是对象,另一个是数字或字符串,会尝试使用对象的valueOf()和toString()方法将对象转换为原始值。
- 如果操作数具有相同的类型,则将它们进行如下比较:
- String:true仅当两个操作数具有相同顺序的相同字符时才返回。
- Number:true仅当两个操作数具有相同的值时才返回。+0并被-0视为相同的值。如果任一操作数为NaN,则返回false。
- Boolean:true仅当操作数为两个true或两个false时才返回true。
toNumber 和 toPrimitive 方法是内部的,并根据以下表格对其估值
toNumber 方法对不同类型返回的结果如下:
值类型 | 结果 |
---|---|
undefined | NaN |
null | +0 |
布尔值 | 如果是true,返回1;如果是false,返回+0 |
数 | 数对应的值 |
toPrimitive 方法对不同类型返回的结果如下:
值类型 | 结果 |
---|---|
对象 | 如果对象的valueOf方法的结果是返回原始值,返回原始值;如果对象的toString方法返回原始值,就返回这个值;其它情况都返回一个错误 |
我们可以用例子来验证一下:
例子1:
1 | console.log('demo' == true); // false |
首先,布尔值会被 toNumber 方法转成数 ,因此得到:demo == 1。
其次,用toNumber 转换字符串值。因为字符串包含字母,所以会被转成NaN,表达式编程了 NaN == 1,结果就是false
例子2
1 | console.log('demo' == false); // false |
首先,布尔值会被 toNumber 方法转成数 ,因此得到:demo == 0。
其次,用toNumber 转换字符串值。因为字符串包含字母,所以会被转成NaN,表达式编程了 NaN == 0,结果就是false
“===”的比较规则
- 先检查两个操作数的数据类型是否相同
- 若不同,直接返回false
- 若相同,则比较二者是否相等
我们可以用以下表格分析。
类型(x) | 类型(y) | 结果 |
---|---|---|
数 | x和y的值相同(但不是NaN) | true |
字符串 | x和y是相同字符 | true |
布尔值 | x和y都是true或false | true |
对象 | x和y引用同一个对象 | true |
让我们用代码来验证一下:
1 | console.log('张三' === true); // false (两者类型不相同) |
条件语句
条件语句用于基于不同条件执行不同的动作。
在您写代码时,经常会需要基于不同判断执行不同的动作。
您可以在代码中使用条件语句来实现这一点。
在 JavaScript 中,我们可使用如下条件语句
- 使用 if 来规定要执行的代码块,如果指定条件为 true
- 使用 else 来规定要执行的代码块,如果相同的条件为 false
- 使用 else if 来规定要测试的新条件,如果第一个条件为 false
- 使用 switch 来规定多个被执行的备选代码块
if 语句
如果想让一个脚本在仅当条件是true时执行,可以使用if语句
语法:
1 | if (条件) { |
示例:
1 | var num = 1; |
输出
1 | num 真的等于 1 |
else 语句
如果想在条件为true的时候执行脚本A,在条件为false的时候执行脚本B可以使用if…else语句。
语法:
1 | if (条件) { |
示例:
1 | var elseVariable = 0; |
输出
1 | elseVariable 不等于 1 |
也可以使用三元运算符:
1 | var elseVariable = 0; |
else if 语句
如果我们有多个脚本,可以多次使用if…else,根据不同条件执行不同的语句
语法:
1 | if (条件 1) { |
示例:
1 | var month = 5; |
输出:
1 | 月份不是一月,也不是二月或三月 |
switch
如果要判断的条件和上面的elseif一样,还可以使用switch语句
语法:
1 | switch(表达式) { |
代码解释:
- 计算一次 switch 表达式
- 把表达式的值与每个 case 的值进行对比
- 如果存在匹配,则执行关联代码
示例:
1 | var month = 5; |
输出:
1 | 月份不是一月,也不是二月或三月 |
循环
假如您需要运行代码多次,且每次使用不同的值,那么循环(loop)相当方便使用。
通常我们会遇到使用数组的例子:
不需要这样写:
1 | var arr = ['张三','李四','王五','赵六','杨七']; |
可以使用for循环:
1 | var arr = ['张三','李四','王五','赵六','杨七']; |
不同类型的循环
- for - 循环代码块一定的次数
- for/in - 循环遍历对象的属性
- while - 当指定的条件为 true 时循环指定的代码块
- do/while - 同样当指定的条件为 true 时循环指定的代码块
for 循环
语法:
1 | for (语句 1; 语句 2; 语句 3) |
代码解释:
语句 1 (代码块)开始前执行
语句 2 定义运行循环(代码块)的条件
语句 3 在循环(代码块)已被执行之后执行
示例:
打印小于10的正整数:
1 | for(let i = 1;i < 10;i++){ |
for/in 循环
用for/in 语句遍历对象的属性
语法:
1 | for(声明变量(即遍历数组的键名) in 数组){ |
示例:
1 | var studentScore = {chinese: 90, math: 93, english: 88}; |
输出:
1 | chinese分数为:90 |
While 循环
while 循环会在指定条件为真时循环执行代码块。
语法:
1 | while (条件) { |
示例:
打印小于10的正整数:
1 | var num = 1; |
do/while 循环
do/while 循环是 while 循环的变体。该循环会在检查条件是否为真之前执行一次代码块,然后如果条件为真的话,就会重复这个循环。
语法:
1 | do |
示例:
打印小于10的正整数:
1 | do { |
while与do…while的区别:
while
先判断条件是否满足,如果满足就执行循环体内的语句,执行完毕后再回来判断条件是否满足,如此无限重复;直到条件不满足时,执行while循环后边的语句。简单来讲就是说while循环是先判断后循环
do…while
与while循环的不同在于:它先执行循环中的语句,然后再判断表达式是否为真, 如果为真则继续循环;如果为假, 则终止循环。因此, do…while循环至少要执行一次循环语句。 简单来讲就是说while循环是先循环后判断 。
break 和 continue 语句
break 语句用于跳出循环。
continue 用于跳过循环中的一个迭代。
break 语句
break 语句可用于跳出循环。
break 语句跳出循环后,会继续执行该循环之后的代码(如果有的话)。
break 语句(不带标签引用),只能用在循环或 switch 中。
continue 语句
continue 语句中断循环中的迭代,如果出现了指定的条件,然后继续循环中的下一个迭代。
continue 语句(带有或不带标签引用)只能用在循环中。
函数
函数是由事件驱动的或者当它被调用时执行的可重复使用的代码块。JavaScript函数语法,函数就是包裹在花括号中的代码块,前面使用了关键词 function: 当调用该函数时,会执行函数内的代码。可以在某事件发生时直接调用函数(比如当用户点击按钮时),并且可由 JavaScript 在任何位置进行调用。
函数的声明
- 定义式
1 | fun(); // this is a function. |
- 变量式
1 | demo(); // 报错:demo is not a function |
为什么这里在声明前调用会报错 demo is not a function 呢?而上面定义式的fun();又能在之前调用?
javascript并不是严格的自上而下执行的语言 。JavaScript有个东西叫变量提升(hoisting),它会将当前作用域的所有变量的声明提升到程序的顶部。
1 | num = 1; |
等价于
1 | var num; |
那我们再来看一个例子:
1 | console.log(num); // undefined |
那为什么这里会打印 undefined 呢?原因为 JavaScript会将变量的声明提升到顶部,可是赋值语句并不会提升。
所以上面demo()函数的声明,变量demo会被提升到顶部,但是变量的值并没有提升,所以变量式声明函数时,函数的调用应该在该表达式的后面:
1 | var demo = function () { |
我们再来说一个题外话:
1 | fun(); |
你觉得上面会报fun is not a function吗?不,其实它会输出 this is a function. 当函数声明与其他声明一起出现的时候,是以谁为准呢?答案就是,函数声明高于一切。
构造器式
1 | let constructor = new Function('name','age',"console.log(name + '的年龄为' + age);") |
函数的返回值
当 JavaScript 到达 return 语句,函数将停止执行。
如果函数被某条语句调用,JavaScript 将在调用语句之后“返回”执行代码。
在JavaScript中不管我们指没指定函数的返回值,函数都会返回一个值
指定返回值 -> 返回指定的值
未指定返回值 -> 返回undefined
我们来用代码来展示效果:
1 | var fun1 = function () { |
为何使用函数?
您能够对代码进行复用:只要定义一次代码,就可以多次使用它。
您能够多次向同一函数传递不同的参数,以产生不同的结果。
面向对象
什么是类?什么是对象?
类是一个抽象的概念,是对某一类事物的抽象。 我们举个例子,人类可以看作一个类,这个类的共性有:第一、站立行走,第二、有一个很发达的大脑,上面这两点都是静态的,描述的是客观的属性(attributes)。人类还需要吃饭、需要睡觉,上面这两点都是动态的行为,即方法(methods)。类可以包含函数,函数在类中就是动态的行为,即方法。
对象就是类的实例化。人类是一个类,而每一个人就是人类的实例化,即每一个人就是一个对象,对象具有类的属性及方法(每个人都站立行走、有一个发达的大脑,并且需要吃饭睡觉)。
JavaScript中类的声明
1. 普通声明,基于已有对象扩充其属性和方法
1 | var obj = new Object(); |
这种方式的弊端:这种对象的可复用性不强,如果需要使用多个对象,还需要重新扩展其属性和方法。
2. 键值对声明
1 | var obj = { |
可以看得到,键值对中的键就是对象的属性,值就是对应属性的值
3. 构造函数方式
1 | function Person() { |
4. 原型(“prototype”)方式
1 | function Person() { |
使用原型存在的缺点:
- 不能传参数;
- 有可能会导致程序错误。如果使用原型方式来定义对象,那么生成的所有对象会共享原型中的属性,这样一个对象改变了该属性也会反映到其他对象当中。单纯使用原型方式定义对象无法在构造函数中为属性赋初值,只能在对象生成后再去改变属性值。
继承
创建一个或多个类的专门版本类方式称为继承(Javascript只支持单继承)。 创建的专门版本的类通常叫做子类,另外的类通常叫做父类。 在Javascript中,继承通过赋予子类一个父类的实例并专门化子类来实现。
让我们来看一下例子。
我们定义了 Student类作为 Person类的子类. 之后我们重定义了sayHello() 方法并添加了 squat() 方法
1 | function Person(name) { |
BOM与DOM
JavaScript的实现包括以下3个部分:
名称 | 描述 |
---|---|
ECMAScript | 描述了JS的语法和基本对象。 |
文档对象模型 (DOM) | 处理网页内容的方法和接口 |
浏览器对象模型(BOM) | 与浏览器交互的方法和接口 |
Document Object Model(文档对象模型),就是把「文档」当做一个「对象」来看待。
相应的,Browser Object Model(浏览器对象模型),即把「浏览器」当做一个「对象」来看待。
BOM(Browser Object Model)
BOM 即浏览器对象模型,BOM没有相关标准,BOM的最核心对象是window对象。window对象既为javascript访问浏览器提供API,同时在ECMAScript中充当Global对象。BOM和浏览器关系密切,浏览器很多东西可以通过javascript控制,例如打开窗口、打开选项卡、关闭页面、收藏夹等。这些功能与网页内容无关。由于没有标准,不同的浏览器实现同一功能,可以通过不同的实现方式。例如,加入收藏夹这个功能:
1 | IE浏览器: window.external.AddFavorite(url,title); |
虽然没有统一标准,但是各个浏览器的常用功能的js代码大同小异,对于常用的功能已经有默认的标准了。
DOM(Document Object Model)
DOM即文档对象模型,DOM是W3C标准,DOM的最根本对象是document(window.document),这个对象实际上是window对象的属性,这个对象的独特之处是这个是唯一一个既属于BOM又属于DOM的对象。DOM和文档有关,这里的文档指的是网页,也就是html文档。DOM和浏览器无关,他关注的是网页本身的内容,由于和浏览器没有多大的关系,所以标准就好定了。
JavaScript内置对象
基本对象
Object
**Object**
是 JavaScript 的一种 数据类型 。它用于存储各种键值集合和更复杂的实体。Objects 可以通过 Object()
构造函数或者使用 对象字面量 的方式创建
方法名 | 方法描述 |
---|---|
Object.assign() | 通过复制一个或多个对象来创建一个新的对象。 |
Object.create() | 使用指定的原型对象和属性创建一个新对象。 |
Object.defineProperty() | 给对象添加一个属性并指定该属性的配置。 |
Object.defineProperties() | 给对象添加多个属性并分别指定它们的配置。 |
Object.entries() | 返回给定对象自身可枚举属性的 [key, value] 数组。 |
Object.freeze() | 冻结对象:其他代码不能删除或更改任何属性。 |
Object.getOwnPropertyDescriptor() | 返回对象指定的属性配置。 |
Object.getOwnPropertyNames() | 返回一个数组,它包含了指定对象所有的可枚举或不可枚举的属性名。 |
Object.getOwnPropertySymbols() | 返回一个数组,它包含了指定对象自身所有的符号属性。 |
Object.getPrototypeOf() | 返回指定对象的原型对象。 |
Object.is() | 比较两个值是否相同。所有 NaN 值都相等(这与==和===不同)。 |
Object.isExtensible() | 判断对象是否可扩展。 |
Object.isFrozen() | 判断对象是否已经冻结。 |
Object.isSealed() | 判断对象是否已经密封。 |
Object.keys() | 返回一个包含所有给定对象自身可枚举属性名称的数组。 |
Object.preventExtensions() | 防止对象的任何扩展。 |
Object.seal() | 防止其他代码删除对象的属性。 |
Object.setPrototypeOf() | 设置对象的原型(即内部 [[Prototype]] 属性)。 |
Object.values() | 返回给定对象自身可枚举值的数组。 |
Function
每个 JavaScript 函数实际上都是一个 Function
对象。运行 (function(){}).constructor === Function // true
便可以得到这个结论。
实例属性
属性 | 描述 |
---|---|
Function.prototype.arguments | 对应传递给函数的参数数组,这个 Function 的属性已被弃用,请改用 arguments 对象(仅在函数范围内可用)。 |
Function.prototype.caller | 表明调用当前函数执行的函数,此属性已被弃用,且仅对一些不严格的函数可用。 |
Function.prototype.displayName | 函数的显示名称。 |
Function.prototype.length | 函数期望的参数数量。 |
Function.prototype.name | 函数的名称。 |
** 实例方法 **
方法名 | 描述 |
---|---|
Function.prototype.apply(thisArg [, argsArray]) | 调用一个函数并将其 this 的值设置为提供的 thisArg。参数可用以通过数组对象传递。 |
Function.prototype.bind(thisArg[, arg1[, arg2[, …argN]]]) | 创建一个新的函数,该函数在调用时,会将 this 设置为提供的 thisArg。在调用新绑定的函数时,可选的参数序列([, arg1[, arg2[, …argN]]])会被提前添加到参数序列中(译者注:即调用绑定创建的函数时,传递的参数会接续在可选参数序列后)。 |
Function.prototype.call(thisArg[, arg1, arg2, …argN]) | 调用一个函数,并将其 this 值设置为提供的值。也可以选择传输新参数。 |
Function.prototype.toString() | 返回表示函数源码的字符串。覆盖了 Object.prototype.toString 方法。 |
Boolean
**Boolean
**对象是一个布尔值的对象包装器。
如果需要,作为第一个参数传递的值将转换为布尔值。如果省略或值0
,-0
,null
,false
,NaN
,undefined
,或空字符串(""
),该对象具有的初始值false
。所有其他值,包括任何对象,空数组([]
)或字符串"false"
,都会创建一个初始值为true
的对象。
注意不要将基本类型中的布尔值 true
和 false
与值为 true
和 false
的 Boolean
对象弄混了。
其值不是undefined
或null
的任何对象(包括其值为false
的布尔对象)在传递给条件语句时都将计算为true
。 例如,以下if
语句中的条件评估为true
:
1 | var x = new Boolean(false); |
基本类型的布尔值不受此规则影响。例如下面的 if
语句的条件为假:
1 | var x = false; |
Symbol
symbol 是一种基本数据类型 (primitive data type)。Symbol()
函数会返回symbol类型的值,该类型具有静态属性和静态方法。它的静态属性会暴露几个内建的成员对象;它的静态方法会暴露全局的symbol注册,且类似于内建对象类,但作为构造函数来说它并不完整,因为它不支持语法:”new Symbol()
“。
每个从Symbol()
返回的symbol值都是唯一的。一个symbol值能作为对象属性的标识符;这是该数据类型仅有的目的。
1 | const symbol1 = Symbol(); |
数字和日期对象
Number
JavaScript 的 Number
对象是经过封装的能让你处理数字值的对象。Number
对象由 Number()
构造器创建。
JavaScript的Number
类型为双精度IEEE 754 64位浮点类型。
属性
属性名 | 描述 |
---|---|
Number.EPSILON | 两个可表示(representable)数之间的最小间隔。 |
Number.MAX_SAFE_INTEGER | JavaScript 中最大的安全整数 (2^53 - 1)。 |
Number.MAX_VALUE | 能表示的最大正数。最小的负数是 -MAX_VALUE。 |
Number.MIN_SAFE_INTEGER | JavaScript 中最小的安全整数 (-(2^53 - 1)). |
Number.MIN_VALUE | 能表示的最小正数即最接近 0 的正数 (实际上不会变成 0)。最大的负数是 -MIN_VALUE。 |
Number.NaN | 特殊的“非数字”值。 |
Number.NEGATIVE_INFINITY | 特殊的负无穷大值,在溢出时返回该值。 |
Number.POSITIVE_INFINITY | 特殊的正无穷大值,在溢出时返回该值。 |
Number.prototype (en-US) | Number 对象上允许的额外属性。 |
方法
方法名 | 描述 |
---|---|
Number.isNaN() | 确定传递的值是否是 NaN。 |
Number.isFinite() | 确定传递的值类型及本身是否是有限数。 |
Number.isInteger() | 确定传递的值类型是“number”,且是整数。 |
Number.isSafeInteger() | 确定传递的值是否为安全整数 ( -(2^53 - 1) 至 2^53 - 1)之间。 |
Number.toInteger() | 计算传递的值并将其转换为整数 (或无穷大)。 |
Number.parseFloat() | 和全局对象 parseFloat() 一样。 |
Number.parseInt() | 和全局对象 parseInt() 一样。 |
Math
Math 是一个内置对象,它拥有一些数学常数属性和数学函数方法。Math 不是一个函数对象。
与其他全局对象不同的是,Math 不是一个构造器。Math 的所有属性与方法都是静态的。引用圆周率的写法是 Math.PI,调用正余弦函数的写法是 Math.sin(x),x 是要传入的参数。Math 的常量是使用 JavaScript 中的全精度浮点数来定义的。
属性
属性名 | 描述 |
---|---|
Math.E | 欧拉常数,也是自然对数的底数,约等于 2.718。 |
Math.LN2 | 2 的自然对数,约等于 0.693。 |
Math.LN10 | 10 的自然对数,约等于 2.303。 |
Math.LOG2E | 以 2 为底的 E 的对数,约等于 1.443。 |
Math.LOG10E | 以 10 为底的 E 的对数,约等于 0.434。 |
Math.PI | 圆周率,一个圆的周长和直径之比,约等于 3.14159。 |
Math.SQRT1_2 | 二分之一 ½ 的平方根,同时也是 2 的平方根的倒数 ,约等于 0.707。 |
Math.SQRT2 | 2 的平方根,约等于 1.414。 |
方法
方法名 | 描述 |
---|---|
Math.abs(x) | 返回一个数的绝对值。 |
Math.acos(x) | 返回一个数的反余弦值。 |
Math.acosh(x) | 返回一个数的反双曲余弦值。 |
Math.asin(x) | 返回一个数的反正弦值。 |
Math.asinh(x) | 返回一个数的反双曲正弦值。 |
Math.atan(x) | 返回一个数的反正切值。 |
Math.atanh(x) | 返回一个数的反双曲正切值。 |
Math.atan2(y, x) | 返回 y/x 的反正切值。 |
Math.cbrt(x) | 返回一个数的立方根。 |
Math.ceil(x) | 返回大于一个数的最小整数,即一个数向上取整后的值。 |
Math.clz32(x) | 返回一个 32 位整数的前导零的数量。 |
Math.cos(x) | 返回一个数的余弦值。 |
Math.cosh(x) | 返回一个数的双曲余弦值。 |
Math.exp(x) | 返回欧拉常数的参数次方,E^x,其中 x 为参数,E 是欧拉常数(2.718…,自然对数的底数)。 |
Math.expm1(x) | 返回 exp(x) - 1 的值。 |
Math.floor(x) | 返回小于一个数的最大整数,即一个数向下取整后的值。 |
Math.fround(x) | 返回最接近一个数的单精度浮点型表示。 |
Math.hypot([x[, y[, …]]]) | 返回其所有参数平方和的平方根。 |
Math.imul(x, y) | 返回 32 位整数乘法的结果。 |
Math.log(x) | 返回一个数的自然对数(㏒e,即 ㏑)。 |
Math.log1p(x) | 返回一个数加 1 的和的自然对数(㏒e,即 ㏑)。 |
Math.log10(x) | 返回一个数以 10 为底数的对数。 |
Math.log2(x) | 返回一个数以 2 为底数的对数。 |
Math.max([x[, y[, …]]]) | 返回零到多个数值中最大值。 |
Math.min([x[, y[, …]]]) | 返回零到多个数值中最小值。 |
Math.pow(x, y) | 返回一个数的 y 次幂。 |
Math.random() | 返回一个 0 到 1 之间的伪随机数。 |
Math.round(x) | 返回四舍五入后的整数。 |
Math.sign(x) | 返回一个数的符号,得知一个数是正数、负数还是 0。 |
Math.sin(x) | 返回一个数的正弦值。 |
Math.sinh(x) | 返回一个数的双曲正弦值。 |
Math.sqrt(x) | 返回一个数的平方根。 |
Math.tan(x) | 返回一个数的正切值。 |
Math.tanh(x) | 返回一个数的双曲正切值。 |
Math.toSource() | 返回字符串 “Math”。 |
Math.trunc(x) | 返回一个数的整数部分,直接去除其小数点及之后的部分。 |
Date
创建一个 JavaScript Date 实例,该实例呈现时间中的某个时刻。Date 对象则基于 Unix Time Stamp,即自1970年1月1日(UTC)起经过的毫秒数。
Date 对象方法
方法
方法名 | 描述 |
---|---|
getDate() | 返回月中的第几天(从 1 到 31)。 |
getDay() | 返回星期几(0-6)。 |
getFullYear() | 返回年份。 |
getHours() | 返回小时(从 0-23)。 |
getMilliseconds() | 返回毫秒(0-999)。 |
getMinutes() | 返回分钟(从 0-59)。 |
getMonth() | 返回月份(从 0-11)。 |
getSeconds() | 返回秒数(从 0-59)。 |
getTime() | 返回自 1970 年 1 月 1 日午夜以来与指定日期的毫秒数。 |
getTimezoneOffset() | 返回 UTC 时间与本地时间之间的时差,以分钟为单位。 |
getUTCDate() | 根据世界时,返回月份中的第几天(从 1 到 31)。 |
getUTCDay() | 根据世界时,返回星期几(0-6)。 |
getUTCFullYear() | 根据世界时,返回年份。 |
getUTCHours() | 根据世界时,返回小时(0-23)。 |
getUTCMilliseconds() | 根据世界时,返回毫秒数(0-999)。 |
getUTCMinutes() | 根据世界时,返回分钟(0-59)。 |
getUTCMonth() | 根据世界时,返回月份(0-11)。 |
getUTCSeconds() | 根据世界时,返回秒数(0-59)。 |
getYear() | 已弃用。请改用 getFullYear() 方法。 |
now() | 返回自 1970 年 1 月 1 日午夜以来的毫秒数。 |
parse() | 解析日期字符串并返回自 1970 年 1 月 1 日以来的毫秒数。 |
setDate() | 设置 Date 对象中月的某一天。 |
setFullYear() | 设置日期对象的年份 |
setHours() | 设置日期对象的小时。 |
setMilliseconds() | 设置日期对象的毫秒数。 |
setMinutes() | 设置日期对象的分钟数。 |
setMonth() | 设置日期对象的月份。 |
setSeconds() | 设置日期对象的秒数。 |
setTime() | 将日期设置为 1970 年 1 月 1 日之后/之前的指定毫秒数。 |
setUTCDate() | 根据世界时,设置 Date 对象中月份的一天。 |
setUTCFullYear() | 根据世界时,设置日期对象的年份。 |
setUTCHours() | 根据世界时,设置日期对象的小时。 |
setUTCMilliseconds() | 根据世界时,设置日期对象的毫秒数。 |
setUTCMinutes() | 根据世界时,设置日期对象的分钟数。 |
setUTCMonth() | 根据世界时,设置日期对象的月份。 |
setUTCSeconds() | 根据世界时,设置日期对象的秒数。 |
setYear() | 已弃用。请改用 setFullYear() 方法。 |
toDateString() | 将 Date 对象的日期部分转换为可读字符串。 |
toGMTString() | 已弃用。请改用 toUTCString() 方法。 |
toISOString() | 使用 ISO 标准将日期作为字符串返回。 |
toJSON() | 以字符串形式返回日期,格式为 JSON 日期。 |
toLocaleDateString() | 使用区域设置约定将 Date 对象的日期部分作为字符串返回。 |
toLocaleTimeString() | 使用区域设置约定将 Date 对象的时间部分作为字符串返回。 |
toLocaleString() | 使用区域设置约定将 Date 对象转换为字符串。 |
toString() | 将 Date 对象转换为字符串。 |
toTimeString() | 将 Date 对象的时间部分转换为字符串。 |
toUTCString() | 根据世界时,将 Date 对象转换为字符串。 |
UTC() | 根据 UTC 时间,返回自 1970 年 1 月 1 日午夜以来的日期中的毫秒数。 |
valueOf() | 返回 Date 对象的原始值。 |
字符串
String
String 对象用于处理文本(字符串)。
方法
方法名 | 描述 |
---|---|
anchor() | 创建 HTML 锚。 |
big() | 用大号字体显示字符串。 |
blink() | 显示闪动字符串。 |
bold() | 使用粗体显示字符串。 |
charAt() | 返回在指定位置的字符。 |
charCodeAt() | 返回在指定的位置的字符的 Unicode 编码。 |
concat() | 连接字符串。 |
fixed() | 以打字机文本显示字符串。 |
fontcolor() | 使用指定的颜色来显示字符串。 |
fontsize() | 使用指定的尺寸来显示字符串。 |
fromCharCode() | 从字符编码创建一个字符串。 |
indexOf() | 检索字符串。 |
italics() | 使用斜体显示字符串。 |
lastIndexOf() | 从后向前搜索字符串。 |
link() | 将字符串显示为链接。 |
localeCompare() | 用本地特定的顺序来比较两个字符串。 |
match() | 找到一个或多个正则表达式的匹配。 |
replace() | 替换与正则表达式匹配的子串。 |
search() | 检索与正则表达式相匹配的值。 |
slice() | 提取字符串的片断,并在新的字符串中返回被提取的部分。 |
small() | 使用小字号来显示字符串。 |
split() | 把字符串分割为字符串数组。 |
strike() | 使用删除线来显示字符串。 |
sub() | 把字符串显示为下标。 |
substr() | 从起始索引号提取字符串中指定数目的字符。 |
substring() | 提取字符串中两个指定的索引号之间的字符。 |
sup() | 把字符串显示为上标。 |
toLocaleLowerCase() | 把字符串转换为小写。 |
toLocaleUpperCase() | 把字符串转换为大写。 |
toLowerCase() | 把字符串转换为小写。 |
toUpperCase() | 把字符串转换为大写。 |
toSource() | 代表对象的源代码。 |
toString() | 返回字符串。 |
valueOf() | 返回某个字符串对象的原始值。 |
JaScript DOM事件
HTML DOM 事件允许 JavaScript 在 HTML 文档中的元素上注册不同的事件处理程序。
事件通常与函数结合使用,在事件发生之前函数不会被执行(例如当用户单击按钮时)。
事件 | 描述 | 属于 |
---|---|---|
abort | 媒体加载中止时发生该事件。 | UiEvent、Event |
afterprint | 当页面开始打印时,或者关闭打印对话框时,发生此事件。 | Event |
animationend | CSS 动画完成时发生此事件。 | AnimationEvent |
animationiteration | 重复 CSS 动画时发生此事件。 | AnimationEvent |
animationstart | CSS 动画开始时发生此事件。 | AnimationEvent |
beforeprint | 即将打印页面时发生此事件。 | Event |
beforeunload | 在文档即将被卸载之前发生此事件。 | UiEvent |
blur | 当元素失去焦点时发生此事件。 | FocusEvent |
canplay | 当浏览器可以开始播放媒体时,发生此事件。 | Event |
canplaythrough | 当浏览器可以在不停止缓冲的情况下播放媒体时发生此事件。 | Event |
change | 当form元素的内容、选择的内容或选中的状态发生改变时,发生此事件 | Event |
click | 当用户单击元素时发生此事件。 | MouseEvent |
contextmenu | 当用户右键单击某个元素以打开上下文菜单时,发生此事件。 | MouseEvent |
copy | 当用户复制元素的内容时发生此事件。 | ClipboardEvent |
cut | 当用户剪切元素的内容时发生此事件。 | ClipboardEvent |
dblclick | 当用户双击元素时发生此事件。 | MouseEvent |
drag | 拖动元素时发生此事件。 | DragEvent |
dragend | 当用户完成拖动元素后,发生此事件。 | DragEvent |
dragenter | 当拖动的元素进入放置目标时,发生此事件。 | DragEvent |
dragleave | 当拖动的元素离开放置目标时,发生此事件。 | DragEvent |
dragover | 当拖动的元素位于放置目标之上时,发生此事件。 | DragEvent |
dragstart | 当用户开始拖动元素时发生此事件。 | DragEvent |
drop | 当将拖动的元素放置在放置目标上时,发生此事件。 | DragEvent |
durationchange | 媒体时长改变时发生此事件。 | Event |
ended | 在媒体播放到尽头时发生此事件。 | Event |
error | 当加载外部文件时发生错误后,发生此事件。 | ProgressEvent、UiEvent、Event |
focus | 在元素获得焦点时发生此事件。 | FocusEvent |
focusin | 在元素即将获得焦点时发生此事件。 | FocusEvent |
focusout | 在元素即将失去焦点时发生此事件。 | FocusEvent |
fullscreenchange | 当元素以全屏模式显示时,发生此事件。 | Event |
fullscreenerror 当元素无法在全屏模式下显示时,发生此事件。 | Event | |
hashchange | 当 URL 的锚部分发生改变时,发生此事件。 | HashChangeEvent |
input | 当元素获得用户输入时,发生此事件。 | InputEvent、vent |
invalid 当元素无效时,发生此事件。 | Event | |
keydown | 当用户正在按下键时,发生此事件。 | KeyboardEvent |
keypress | 当用户按下键时,发生此事件。 | KeyboardEvent |
keyup | 当用户松开键时,发生此事件。 | KeyboardEvent |
load | 在对象已加载时,发生此事件。 | UiEvent、vent |
loadeddata | 媒体数据加载后,发生此事件。 | Event |
loadedmetadata | 加载元数据(比如尺寸和持续时间)时,发生此事件。 | Event |
loadstart | 当浏览器开始查找指定的媒体时,发生此事件。 | ProgressEvent |
message | 在通过此事件源接收消息时,发生此事件。 | Event |
mousedown | 当用户在元素上按下鼠标按钮时,发生此事件。 | MouseEvent |
mouseenter | 当指针移动到元素上时,发生此事件。 | MouseEvent |
mouseleave | 当指针从元素上移出时,发生此事件。 | MouseEvent |
mousemove | 当指针在元素上方移动时,发生此事件。 | MouseEvent |
mouseout | 当用户将鼠标指针移出元素或其中的子元素时,发生此事件。 | MouseEvent |
mouseover | 当指针移动到元素或其中的子元素上时,发生此事件。 | MouseEvent |
mouseup | 当用户在元素上释放鼠标按钮时,发生此事件。 | MouseEvent |
mousewheel | 不推荐使用。请改用 wheel 事件。 | WheelEvent |
offline | 当浏览器开始脱机工作时,发生此事件。 | Event |
online | 当浏览器开始在线工作时,发生此事件。 | Event |
open | 当打开与事件源的连接时,发生此事件。 | Event |
pagehide | 当用户离开某张网页进行导航时,发生此事件。 | PageTransitionEvent |
pageshow | 在用户导航到某张网页时,发生此事件。 | PageTransitionEvent |
paste | 当用户将一些内容粘贴到元素中时,发生此事件。 | ClipboardEvent |
pause | 当媒体被用户暂停或以编程方式暂停时,发生此事件。 | Event |
play | 当媒体已启动或不再暂停时,发生此事件。 | Event |
playing | 在媒体被暂停或停止以缓冲后播放时,发生此事件。 | Event |
popstate | 窗口的历史记录改变时,发生此事件。 | PopStateEvent |
progress | 当浏览器正处于获得媒体数据的过程中时,发生此事件。 | Event |
ratechange | 媒体播放速度改变时发生此事件。 | Event |
reset | 重置表单时发生此事件。 | Event |
resize | 调整文档视图的大小时发生此事件。 | UiEvent、vent |
scroll | 滚动元素的滚动条时发生此事件。 | UiEvent、vent |
search | 当用户在搜索字段中输入内容时,发生此事件。 | Event |
seeked | 当用户完成移动/跳到媒体中的新位置时,发生该事件。 | Event |
seeking | 当用户开始移动/跳到媒体中的新位置时,发生该事件。 | Event |
select | 用户选择文本后(对于<input> 和<textarea> )发生此事件 | UiEvent、vent |
show | 当<menu> 元素显示为上下文菜单时,发生此事件。 | Event |
stalled | 当浏览器尝试获取媒体数据但数据不可用时,发生此事件。 | Event |
storage | Web 存储区域更新时发生此事件。 | StorageEvent |
submit | 在提交表单时发生此事件。 | Event |
suspend | 当浏览器有意不获取媒体数据时,发生此事件。 | Event |
timeupdate | 当播放位置更改时发生此事件。 | Event |
toggle | 当用户打开或关闭 <details> 元素时,发生此事件。 | Event |
touchcancel | 在触摸被中断时,发生此事件。 | TouchEvent |
touchend | 当手指从触摸屏上移开时,发生此事件。 | TouchEvent |
touchmove | 当手指在屏幕上拖动时,发生此事件。 | TouchEvent |
touchstart | 当手指放在触摸屏上时,发生此事件。 | TouchEvent |
transitionend | CSS 转换完成时,发生此事件。 | TransitionEvent |
unload | 页面卸载后(对于 <body> ),发生此事件。 | UiEvent、vent |
volumechange | 当媒体的音量已更改时,发生此事件。 | Event |
waiting | 当媒体已暂停但预期会恢复时,发生此事件。 | Event |
wheel | 当鼠标滚轮在元素向上或向下滚动时,发生此事件。 | WheelEvent |
JavaScript Ajax
AJAX = Asynchronous JavaScript And XML.
AJAX 并非编程语言。
AJAX 仅仅组合了:
- 浏览器内建的 XMLHttpRequest 对象(从 web 服务器请求数据)
- JavaScript 和 HTML DOM(显示或使用数据)
Ajax 是一个令人误导的名称。Ajax 应用程序可能使用 XML 来传输数据,但将数据作为纯文本或 JSON 文本传输也同样常见。
Ajax 允许通过与场景后面的 Web 服务器交换数据来异步更新网页。这意味着可以更新网页的部分,而不需要重新加载整个页面。
XMLHttpRequest 对象
XMLHttpRequest对象是ajax的基础,XMLHttpRequest 用于在后台与服务器交换数据。这意味着可以在不重新加载整个网页的情况下,对网页的某部分进行更新。目前所有浏览器都支持XMLHttpRequest
方 法 | 描 述 |
---|---|
abort() | 停止当前请求 |
getAllResponseHeaders() | 把HTTP请求的所有响应首部作为键/值对返回 |
getResponseHeader(“header”) | 返回指定首部的串值 |
open(“method”,”URL”,[asyncFlag],[“userName”],[“password”]) | 建立对服务器的调用。method参数可以是GET、POST或PUT。url参数可以是相对URL或绝对URL。这个方法还包括3个可选的参数,是否异步,用户名,密码 |
send(content) | 向服务器发送请求 |
setRequestHeader(“header”, “value”) | 把指定首部设置为所提供的值。在设置任何首部之前必须先调用open()。设置header并和请求一起发送 (‘post’方法一定要 ) |
五步使用法:
1.创建XMLHTTPRequest对象
2.使用open方法设置和服务器的交互信息
3.设置发送的数据,开始和服务器端交互
4.注册事件
5.更新界面
栗子:
1 | //步骤一:创建异步对象 |
JQuery
jQuery 选择器
选择器 | 实例 | 选取 |
---|---|---|
* | $(“*”) | 所有元素 |
#id | $(“#lastname”) | id=”lastname” 的元素 |
.class | $(“.intro”) | 所有 class=”intro” 的元素 |
element | $(“p”) | 所有 元素 |
.class.class | $(“.intro.demo”) | 所有 class=”intro” 且 class=”demo” 的元素 |
:first | $(“p:first”) | 第一个 元素 |
:last | $(“p:last”) | 最后一个 元素 |
:even | $(“tr:even”) | 所有偶数 |
:odd | $(“tr:odd”) | 所有奇数 |
:eq(index) | $(“ul li:eq(3)”) | 列表中的第四个元素(index 从 0 开始) |
:gt(no) | $(“ul li:gt(3)”) | 列出 index 大于 3 的元素 |
:lt(no) | $(“ul li:lt(3)”) | 列出 index 小于 3 的元素 |
:not(selector) | $(“input:not(:empty)”) | 所有不为空的 input 元素 |
:header | $(“:header”) | 所有标题元素- |
:animated | 所有动画元素 | |
:contains(text) | $(“:contains(‘W3School’)”) | 包含指定字符串的所有元素 |
:empty | $(“:empty”) | 无子(元素)节点的所有元素 |
:hidden | $(“p:hidden”) | 所有隐藏的 元素 |
:visible | $(“table:visible”) | 所有可见的表格 |
s1,s2,s3 | $(“th,td,.intro”) | 所有带有匹配选择的元素 |
[attribute] | $(“[href]”) | 所有带有 href 属性的元素 |
[attribute=value] | $(“[href=’#’]”) | 所有 href 属性的值等于 “#” 的元素 |
[attribute!=value] | $(“[href!=’#’]”) | 所有 href 属性的值不等于 “#” 的元素 |
[attribute$=value] | $(“[href$=’.jpg’]”) | 所有 href 属性的值包含以 “.jpg” 结尾的元素 |
:input | $(“:input”) | 所有 元素 |
:text | $(“:text”) | 所有 type=”text” 的 元素 |
:password | $(“:password”) | 所有 type=”password” 的 元素 |
:radio | $(“:radio”) | 所有 type=”radio” 的 元素 |
:checkbox | $(“:checkbox”) | 所有 type=”checkbox” 的 元素 |
:submit | $(“:submit”) | 所有 type=”submit” 的 元素 |
:reset | $(“:reset”) | 所有 type=”reset” 的 元素 |
:button | $(“:button”) | 所有 type=”button” 的 元素 |
:image | $(“:image”) | 所有 type=”image” 的 元素 |
:file | $(“:file”) | 所有 type=”file” 的 元素 |
:enabled | $(“:enabled”) | 所有激活的 input 元素 |
:disabled | $(“:disabled”) | 所有禁用的 input 元素 |
:selected | $(“:selected”) | 所有被选取的 input 元素 |
:checked | $(“:checked”) | 所有被选中的 input 元素 |
Query 事件方法
事件方法会触发匹配元素的事件,或将函数绑定到所有匹配元素的某个事件。
触发实例:
1 | $("button#demo").click() |
上面的例子将触发 id=”demo” 的 button 元素的 click 事件。
绑定实例:
1 | $("button#demo").click(function(){$("img").hide()}) |
上面的例子会在点击 id=”demo” 的按钮时隐藏所有图像。
方法 | 描述 |
---|---|
bind() | 向匹配元素附加一个或更多事件处理器 |
blur() | 触发、或将函数绑定到指定元素的 blur 事件 |
change() | 触发、或将函数绑定到指定元素的 change 事件 |
click() | 触发、或将函数绑定到指定元素的 click 事件 |
dblclick() | 触发、或将函数绑定到指定元素的 double click 事件 |
delegate() | 向匹配元素的当前或未来的子元素附加一个或多个事件处理器 |
die() | 移除所有通过 live() 函数添加的事件处理程序。 |
error() | 触发、或将函数绑定到指定元素的 error 事件 |
event.isDefaultPrevented() | 返回 event 对象上是否调用了 event.preventDefault()。 |
event.pageX | 相对于文档左边缘的鼠标位置。 |
event.pageY | 相对于文档上边缘的鼠标位置。 |
event.preventDefault() | 阻止事件的默认动作。 |
event.result | 包含由被指定事件触发的事件处理器返回的最后一个值。 |
event.target | 触发该事件的 DOM 元素。 |
event.timeStamp | 该属性返回从 1970 年 1 月 1 日到事件发生时的毫秒数。 |
event.type | 描述事件的类型。 |
event.which | 指示按了哪个键或按钮。 |
focus() | 触发、或将函数绑定到指定元素的 focus 事件 |
keydown() | 触发、或将函数绑定到指定元素的 key down 事件 |
keypress() | 触发、或将函数绑定到指定元素的 key press 事件 |
keyup() | 触发、或将函数绑定到指定元素的 key up 事件 |
live() | 为当前或未来的匹配元素添加一个或多个事件处理器 |
load() | 触发、或将函数绑定到指定元素的 load 事件 |
mousedown() | 触发、或将函数绑定到指定元素的 mouse down 事件 |
mouseenter() | 触发、或将函数绑定到指定元素的 mouse enter 事件 |
mouseleave() | 触发、或将函数绑定到指定元素的 mouse leave 事件 |
mousemove() | 触发、或将函数绑定到指定元素的 mouse move 事件 |
mouseout() | 触发、或将函数绑定到指定元素的 mouse out 事件 |
mouseover() | 触发、或将函数绑定到指定元素的 mouse over 事件 |
mouseup() | 触发、或将函数绑定到指定元素的 mouse up 事件 |
one() | 向匹配元素添加事件处理器。每个元素只能触发一次该处理器。 |
ready() | 文档就绪事件(当 HTML 文档就绪可用时) |
resize() | 触发、或将函数绑定到指定元素的 resize 事件 |
scroll() | 触发、或将函数绑定到指定元素的 scroll 事件 |
select() | 触发、或将函数绑定到指定元素的 select 事件 |
submit() | 触发、或将函数绑定到指定元素的 submit 事件 |
toggle() | 绑定两个或多个事件处理器函数,当发生轮流的 click 事件时执行。 |
trigger() | 所有匹配元素的指定事件 |
triggerHandler() | 第一个被匹配元素的指定事件 |
unbind() | 从匹配元素移除一个被添加的事件处理器 |
undelegate() | 从匹配元素移除一个被添加的事件处理器,现在或将来 |
unload() | 触发、或将函数绑定到指定元素的 unload 事件 |
jQuery操作DOM元素
插入节点
append()
: 向每个匹配的元素内部追加内容.appendTo()
: 将所有匹配的元素追加到指定的元素中,即$(A).appendTo(B),是将A追加到B中.prepend()
: 向每个匹配的元素内部前置内容.rependTo()
将所有匹配的元素前置到指定的元素中,即$(A).prependTo(B),是将A前置到B中.
前面几个方法都是插入子元素,后面的这几个方法是插入兄弟元素:
after()
: 在每个匹配的元素之后插入内容insertAfter()
: 将所有匹配的元素插入到指定元素的后面.before()
: 在每个匹配的元素之前插入内容.insertBefore()
: 将所有匹配的元素插入到指定元素的前面.
删除节点
jQuery中删除节点的方法:
remove()
: 移除所有匹配的元素.empty()
: 删除匹配的元素集合中所有内容,包括子节点.注意,元素本身没有被删除.
复制节点
jQuery中复制节点的方法:clone()
: 创建匹配元素集合的副本.clone()
:方法返回被复制的节点.
替换节点
jQuery中替换节点的方法:replaceAll()
: 用指定的HTML内容或元素替换被选元素.
1 | $(content).replaceAll(selector). |
replaceWith()
: 用新内容替换所匹配到的元素.
1 | $(selector).replaceWith(content). |
jQuery 效果
show()方法和hide()方法
show()
:根据hide()方法记住的display属性值来显示元素。
hide()
: 将该元素的display样式改为 “none”。
fadeIn()方法和fadeOut()方法
fadeOut()
:会在指定的一段时间内降低元素的不透明度,直到元素完全消失(“display:none”)。
fadeIn()
:与fadeOut()完全相反。
slideUp()方法和slideDown()方法
slideDown()
:如果一个元素的display属性值为”none”,当调用slideDown()时,这个元素将由上至下延伸显示。
slideUp()
:与slideDown()完全相反。
animate() 方法
语法:
1 | $(selector).animate({params},speed,callback); |
必需的 params 参数定义形成动画的 CSS 属性。
可选的 speed 参数规定效果的时长。它可以取以下值:”slow”、”fast” 或毫秒。
可选的 callback 参数是动画完成后所执行的函数名称。
下面的例子演示 animate() 方法的简单应用;它把 <div>
元素移动到左边,直到 left 属性等于 250 像素为止:
栗子:
1 | $("button").click(function(){ |
操作多个属性
1 | $("button").click(function(){ |
jQuery 遍历
函数 | 描述 |
---|---|
.add() | 将元素添加到匹配元素的集合中。 |
.andSelf() | 把堆栈中之前的元素集添加到当前集合中。 |
.children() | 获得匹配元素集合中每个元素的所有子元素。 |
.closest() | 从元素本身开始,逐级向上级元素匹配,并返回最先匹配的祖先元素。 |
.contents() | 获得匹配元素集合中每个元素的子元素,包括文本和注释节点。 |
.each() | 对 jQuery 对象进行迭代,为每个匹配元素执行函数。 |
.end() | 结束当前链中最近的一次筛选操作,并将匹配元素集合返回到前一次的状态。 |
.eq() | 将匹配元素集合缩减为位于指定索引的新元素。 |
.filter() | 将匹配元素集合缩减为匹配选择器或匹配函数返回值的新元素。 |
.find() | 获得当前匹配元素集合中每个元素的后代,由选择器进行筛选。 |
.first() | 将匹配元素集合缩减为集合中的第一个元素。 |
.has() | 将匹配元素集合缩减为包含特定元素的后代的集合。 |
.is() | 根据选择器检查当前匹配元素集合,如果存在至少一个匹配元素,则返回 true。 |
.last() | 将匹配元素集合缩减为集合中的最后一个元素。 |
.map() | 把当前匹配集合中的每个元素传递给函数,产生包含返回值的新 jQuery 对象。 |
.next() | 获得匹配元素集合中每个元素紧邻的同辈元素。 |
.nextAll() | 获得匹配元素集合中每个元素之后的所有同辈元素,由选择器进行筛选(可选)。 |
.nextUntil() | 获得每个元素之后所有的同辈元素,直到遇到匹配选择器的元素为止。 |
.not() | 从匹配元素集合中删除元素。 |
.offsetParent() | 获得用于定位的第一个父元素。 |
.parent() | 获得当前匹配元素集合中每个元素的父元素,由选择器筛选(可选)。 |
.parents() | 获得当前匹配元素集合中每个元素的祖先元素,由选择器筛选(可选)。 |
.parentsUntil() | 获得当前匹配元素集合中每个元素的祖先元素,直到遇到匹配选择器的元素为止。 |
.prev() | 获得匹配元素集合中每个元素紧邻的前一个同辈元素,由选择器筛选(可选)。 |
.prevAll() | 获得匹配元素集合中每个元素之前的所有同辈元素,由选择器进行筛选(可选)。 |
.prevUntil() | 获得每个元素之前所有的同辈元素,直到遇到匹配选择器的元素为止。 |
.siblings() | 获得匹配元素集合中所有元素的同辈元素,由选择器筛选(可选)。 |
.slice() | 将匹配元素集合缩减为指定范围的子集。 |
each
1 | var arr = [ "one", "two", "three", "four"]; |
JQuery Ajax
栗子:
1 | $(function(){ |
参数
options
类型:Object可选。AJAX 请求设置。所有选项都是可选的。
async
类型:Boolean默认值: true。默认设置下,所有请求均为异步请求。如果需要发送同步请求,请将此选项设置为 false。注意,同步请求将锁住浏览器,用户其它操作必须等待请求完成才可以执行。
beforeSend(XHR)
类型:Function发送请求前可修改 XMLHttpRequest 对象的函数,如添加自定义 HTTP 头。XMLHttpRequest 对象是唯一的参数。这是一个 Ajax 事件。如果返回 false 可以取消本次 ajax 请求。
cache
类型:Boolean默认值: true,dataType 为 script 和 jsonp 时默认为 false。设置为 false 将不缓存此页面。jQuery 1.2 新功能。
complete(XHR, TS)
类型:Function请求完成后回调函数 (请求成功或失败之后均调用)。参数: XMLHttpRequest 对象和一个描述请求类型的字符串。这是一个 Ajax 事件。
contentType
类型:String默认值: “application/x-www-form-urlencoded”。发送信息至服务器时内容编码类型。默认值适合大多数情况。如果你明确地传递了一个 content-type 给 $.ajax() 那么它必定会发送给服务器(即使没有数据要发送)。
context
类型:Object这个对象用于设置 Ajax 相关回调函数的上下文。也就是说,让回调函数内 this 指向这个对象(如果不设定这个参数,那么 this 就指向调用本次 AJAX 请求时传递的 options 参数)。比如指定一个 DOM 元素作为 context 参数,这样就设置了 success 回调函数的上下文为这个 DOM 元素。就像这样:
$.ajax({ url: "test.html", context: document.body, success: function(){ $(this).addClass("done"); }});
data
类型:String发送到服务器的数据。将自动转换为请求字符串格式。GET 请求中将附加在 URL 后。查看 processData 选项说明以禁止此自动转换。必须为 Key/Value 格式。如果为数组,jQuery 将自动为不同值对应同一个名称。如 {foo:[“bar1”, “bar2”]} 转换为 ‘&foo=bar1&foo=bar2’。
dataFilter
类型:Function给 Ajax 返回的原始数据的进行预处理的函数。提供 data 和 type 两个参数:data 是 Ajax 返回的原始数据,type 是调用 jQuery.ajax 时提供的 dataType 参数。函数返回的值将由 jQuery 进一步处理。
dataType
类型:String预期服务器返回的数据类型。如果不指定,jQuery 将自动根据 HTTP 包 MIME 信息来智能判断,比如 XML MIME 类型就被识别为 XML。在 1.4 中,JSON 就会生成一个 JavaScript 对象,而 script 则会执行这个脚本。随后服务器端返回的数据会根据这个值解析后,传递给回调函数。可用值:”xml”: 返回 XML 文档,可用 jQuery 处理。”html”: 返回纯文本 HTML 信息;包含的 script 标签会在插入 dom 时执行。”script”: 返回纯文本 JavaScript 代码。不会自动缓存结果。除非设置了 “cache” 参数。注意:在远程请求时(不在同一个域下),所有 POST 请求都将转为 GET 请求。(因为将使用 DOM 的 script标签来加载)”json”: 返回 JSON 数据 。”jsonp”: JSONP 格式。使用 JSONP 形式调用函数时,如 “myurl?callback=?” jQuery 将自动替换 ? 为正确的函数名,以执行回调函数。”text”: 返回纯文本字符串
error
类型:Function默认值: 自动判断 (xml 或 html)。请求失败时调用此函数。有以下三个参数:XMLHttpRequest 对象、错误信息、(可选)捕获的异常对象。如果发生了错误,错误信息(第二个参数)除了得到 null 之外,还可能是 “timeout”, “error”, “notmodified” 和 “parsererror”。这是一个 Ajax 事件。
global
类型:Boolean是否触发全局 AJAX 事件。默认值: true。设置为 false 将不会触发全局 AJAX 事件,如 ajaxStart 或 ajaxStop 可用于控制不同的 Ajax 事件。
ifModified
类型:Boolean仅在服务器数据改变时获取新数据。默认值: false。使用 HTTP 包 Last-Modified 头信息判断。在 jQuery 1.4 中,它也会检查服务器指定的 ‘etag’ 来确定数据没有被修改过。
jsonp
类型:String在一个 jsonp 请求中重写回调函数的名字。这个值用来替代在 “callback=?” 这种 GET 或 POST 请求中 URL 参数里的 “callback” 部分,比如 {jsonp:’onJsonPLoad’} 会导致将 “onJsonPLoad=?” 传给服务器。
jsonpCallback
类型:String为 jsonp 请求指定一个回调函数名。这个值将用来取代 jQuery 自动生成的随机函数名。这主要用来让 jQuery 生成度独特的函数名,这样管理请求更容易,也能方便地提供回调函数和错误处理。你也可以在想让浏览器缓存 GET 请求的时候,指定这个回调函数名。
password
类型:String用于响应 HTTP 访问认证请求的密码
processData
类型:Boolean默认值: true。默认情况下,通过data选项传递进来的数据,如果是一个对象(技术上讲只要不是字符串),都会处理转化成一个查询字符串,以配合默认内容类型 “application/x-www-form-urlencoded”。如果要发送 DOM 树信息或其它不希望转换的信息,请设置为 false。
scriptCharset
类型:String只有当请求时 dataType 为 “jsonp” 或 “script”,并且 type 是 “GET” 才会用于强制修改 charset。通常只在本地和远程的内容编码不同时使用。
success
类型:Function请求成功后的回调函数。参数:由服务器返回,并根据 dataType 参数进行处理后的数据;描述状态的字符串。这是一个 Ajax 事件。
traditional
类型:Boolean如果你想要用传统的方式来序列化数据,那么就设置为 true。请参考工具分类下面的 jQuery.param 方法。
timeout
类型:Number设置请求超时时间(毫秒)。此设置将覆盖全局设置。
type
类型:String默认值: “GET”)。请求方式 (“POST” 或 “GET”), 默认为 “GET”。注意:其它 HTTP 请求方法,如 PUT 和 DELETE 也可以使用,但仅部分浏览器支持。
url
类型:String默认值: 当前页地址。发送请求的地址。
username
类型:String用于响应 HTTP 访问认证请求的用户名。
xhr
类型:Function需要返回一个 XMLHttpRequest 对象。默认在 IE 下是 ActiveXObject 而其他情况下是 XMLHttpRequest 。用于重写或者提供一个增强的 XMLHttpRequest 对象。这个参数在 jQuery 1.3 以前不可用。
回调函数
如果要处理 $.ajax() 得到的数据,则需要使用回调函数:beforeSend、error、dataFilter、success、complete。
函数名 | 说明 |
---|---|
beforeSend | 发送请求之前调用,并且传入一个 XMLHttpRequest 作为参数。 |
error | 在请求出错时调用。传入 XMLHttpRequest 对象,描述错误类型的字符串以及一个异常对象(如果有的话) |
dataFilter | 在请求成功之后调用。传入返回的数据以及 “dataType” 参数的值。并且必须返回新的数据(可能是处理过的)传递给 success 回调函数。 |
success | 当请求之后调用。传入返回后的数据,以及包含成功代码的字符串。 |
complete | 当请求完成之后调用这个函数,无论成功或失败。传入 XMLHttpRequest 对象,以及一个包含成功或错误代码的字符串。 |
Bootstrap
响应式布局相关的 标签
Bootstrap 采用的是 移动设备优先(mobile first) 的开发策略,因此,我们首先为移动设备优化代码,然后根据需要并利用 CSS 媒体查询功能来缩放组件。为了确保所有设备都能支持正确的渲染和触屏缩放,请务必在 <head>
标签中 添加让 viewport(视口)支持响应式布局的 标签。
1 | <meta name="viewport" content="width=device-width, initial-scale=1"> |
ES6
let 与 const
1、let
它的作用类似于var,用来声明变量,但是所声明的变量,只在let命令所在的代码块内有效。
1 | if(true){ |
体会下let和var的作用域范围:
1 | function f1() { |
2、let的应用
for循环的计数器,就很合适使用let命令。
1 | var a = []; |
如果把let换成var ,将输出10。这是由于let的块级作用域。
3、const
a、const 声明的是常量,一旦声明,值将是不可变的。
1 | const PI = 3.1415; |
b、const 也具有块级作用域
1 | if (true) { |
c、const 不能变量提升(必须先声明后使用)
1 | if (true) { |
d、const 不可重复声明
1 | var message = "Hello!"; |
Proxy
Proxy 用于修改某些操作的默认行为,等同于在语言层面做出修改,所以属于一种“元编程”(meta programming),即对编程语言进行编程。
Proxy 可以理解成,在目标对象之前架设一层“拦截”,外界对该对象的访问,都必须先通过这层拦截,因此提供了一种机制,可以对外界的访问进行过滤和改写。Proxy 这个词的原意是代理,用在这里表示由它来“代理”某些操作,可以译为“代理器”。
1 | var obj = new Proxy({}, { |
上面代码对一个空对象架设了一层拦截,重定义了属性的读取(get
)和设置(set
)行为。这里暂时先不解释具体的语法,只看运行结果。对设置了拦截行为的对象obj
,去读写它的属性,就会得到下面的结果。
1 | obj.count = 1 |
上面代码说明,Proxy 实际上重载(overload)了点运算符,即用自己的定义覆盖了语言的原始定义。
ES6 原生提供 Proxy 构造函数,用来生成 Proxy 实例。
1 | var proxy = new Proxy(target, handler); |
Proxy 对象的所有用法,都是上面这种形式,不同的只是handler
参数的写法。其中,new Proxy()
表示生成一个Proxy
实例,target
参数表示所要拦截的目标对象,handler
参数也是一个对象,用来定制拦截行为。
下面是另一个拦截读取属性行为的例子。
1 | var proxy = new Proxy({}, { |
上面代码中,作为构造函数,Proxy
接受两个参数。第一个参数是所要代理的目标对象(上例是一个空对象),即如果没有Proxy
的介入,操作原来要访问的就是这个对象;第二个参数是一个配置对象,对于每一个被代理的操作,需要提供一个对应的处理函数,该函数将拦截对应的操作。比如,上面代码中,配置对象有一个get
方法,用来拦截对目标对象属性的访问请求。get
方法的两个参数分别是目标对象和所要访问的属性。可以看到,由于拦截函数总是返回35
,所以访问任何属性都得到35
。
注意,要使得Proxy
起作用,必须针对Proxy
实例(上例是proxy
对象)进行操作,而不是针对目标对象(上例是空对象)进行操作。
如果handler
没有设置任何拦截,那就等同于直接通向原对象。
1 | var target = {}; |
上面代码中,handler
是一个空对象,没有任何拦截效果,访问proxy
就等同于访问target
。
一个技巧是将 Proxy 对象,设置到object.proxy
属性,从而可以在object
对象上调用。
1 | var object = { proxy: new Proxy(target, handler) }; |
Proxy 实例也可以作为其他对象的原型对象。
1 | var proxy = new Proxy({}, { |
上面代码中,proxy
对象是obj
对象的原型,obj
对象本身并没有time
属性,所以根据原型链,会在proxy
对象上读取该属性,导致被拦截。
同一个拦截器函数,可以设置拦截多个操作。
1 | var handler = { |
对于可以设置、但没有设置拦截的操作,则直接落在目标对象上,按照原先的方式产生结果。
下面是 Proxy 支持的拦截操作一览,一共 13 种。
- **get(target, propKey, receiver)**:拦截对象属性的读取,比如
proxy.foo
和proxy['foo']
。 - **set(target, propKey, value, receiver)**:拦截对象属性的设置,比如
proxy.foo = v
或proxy['foo'] = v
,返回一个布尔值。 - **has(target, propKey)**:拦截
propKey in proxy
的操作,返回一个布尔值。 - **deleteProperty(target, propKey)**:拦截
delete proxy[propKey]
的操作,返回一个布尔值。 - **ownKeys(target)**:拦截
Object.getOwnPropertyNames(proxy)
、Object.getOwnPropertySymbols(proxy)
、Object.keys(proxy)
、for...in
循环,返回一个数组。该方法返回目标对象所有自身的属性的属性名,而Object.keys()
的返回结果仅包括目标对象自身的可遍历属性。 - **getOwnPropertyDescriptor(target, propKey)**:拦截
Object.getOwnPropertyDescriptor(proxy, propKey)
,返回属性的描述对象。 - **defineProperty(target, propKey, propDesc)**:拦截
Object.defineProperty(proxy, propKey, propDesc)
、Object.defineProperties(proxy, propDescs)
,返回一个布尔值。 - **preventExtensions(target)**:拦截
Object.preventExtensions(proxy)
,返回一个布尔值。 - **getPrototypeOf(target)**:拦截
Object.getPrototypeOf(proxy)
,返回一个对象。 - **isExtensible(target)**:拦截
Object.isExtensible(proxy)
,返回一个布尔值。 - **setPrototypeOf(target, proto)**:拦截
Object.setPrototypeOf(proxy, proto)
,返回一个布尔值。如果目标对象是函数,那么还有两种额外操作可以拦截。 - **apply(target, object, args)**:拦截 Proxy 实例作为函数调用的操作,比如
proxy(...args)
、proxy.call(object, ...args)
、proxy.apply(...)
。 - **construct(target, args)**:拦截 Proxy 实例作为构造函数调用的操作,比如
new proxy(...args)
。
Proxy 实例的方法
下面是上面这些拦截方法的详细介绍。
get()
get
方法用于拦截某个属性的读取操作,可以接受三个参数,依次为目标对象、属性名和 proxy 实例本身(严格地说,是操作行为所针对的对象),其中最后一个参数可选。
get
方法的用法,上文已经有一个例子,下面是另一个拦截读取操作的例子。
1 | var person = { |
上面代码表示,如果访问目标对象不存在的属性,会抛出一个错误。如果没有这个拦截函数,访问不存在的属性,只会返回undefined
。
get
方法可以继承。
1 | let proto = new Proxy({}, { |
上面代码中,拦截操作定义在Prototype
对象上面,所以如果读取obj
对象继承的属性时,拦截会生效。
下面的例子使用get
拦截,实现数组读取负数的索引。
1 | function createArray(...elements) { |
上面代码中,数组的位置参数是-1
,就会输出数组的倒数第一个成员。
利用 Proxy,可以将读取属性的操作(get
),转变为执行某个函数,从而实现属性的链式操作。
1 | var pipe = function (value) { |
上面代码设置 Proxy 以后,达到了将函数名链式使用的效果。
下面的例子则是利用get
拦截,实现一个生成各种 DOM 节点的通用函数dom
。
1 | const dom = new Proxy({}, { |
下面是一个get
方法的第三个参数的例子,它总是指向原始的读操作所在的那个对象,一般情况下就是 Proxy 实例。
1 | const proxy = new Proxy({}, { |
上面代码中,proxy
对象的getReceiver
属性是由proxy
对象提供的,所以receiver
指向proxy
对象。
1 | const proxy = new Proxy({}, { |
上面代码中,d
对象本身没有a
属性,所以读取d.a
的时候,会去d
的原型proxy
对象找。这时,receiver
就指向d
,代表原始的读操作所在的那个对象。
如果一个属性不可配置(configurable)且不可写(writable),则 Proxy 不能修改该属性,否则通过 Proxy 对象访问该属性会报错。
1 | const target = Object.defineProperties({}, { |
set()
set
方法用来拦截某个属性的赋值操作,可以接受四个参数,依次为目标对象、属性名、属性值和 Proxy 实例本身,其中最后一个参数可选。
假定Person
对象有一个age
属性,该属性应该是一个不大于 200 的整数,那么可以使用Proxy
保证age
的属性值符合要求。
1 | let validator = { |
上面代码中,由于设置了存值函数set
,任何不符合要求的age
属性赋值,都会抛出一个错误,这是数据验证的一种实现方法。利用set
方法,还可以数据绑定,即每当对象发生变化时,会自动更新 DOM。
有时,我们会在对象上面设置内部属性,属性名的第一个字符使用下划线开头,表示这些属性不应该被外部使用。结合get
和set
方法,就可以做到防止这些内部属性被外部读写。
1 | const handler = { |
上面代码中,只要读写的属性名的第一个字符是下划线,一律抛错,从而达到禁止读写内部属性的目的。
下面是set
方法第四个参数的例子。
1 | const handler = { |
上面代码中,set
方法的第四个参数receiver
,指的是原始的操作行为所在的那个对象,一般情况下是proxy
实例本身,请看下面的例子。
1 | const handler = { |
上面代码中,设置myObj.foo
属性的值时,myObj
并没有foo
属性,因此引擎会到myObj
的原型链去找foo
属性。myObj
的原型对象proxy
是一个 Proxy 实例,设置它的foo
属性会触发set
方法。这时,第四个参数receiver
就指向原始赋值行为所在的对象myObj
。
注意,如果目标对象自身的某个属性不可写,那么set
方法将不起作用。
1 | const obj = {}; |
上面代码中,obj.foo
属性不可写,Proxy 对这个属性的set
代理将不会生效。
注意,set
代理应当返回一个布尔值。严格模式下,set
代理如果没有返回true
,就会报错。
1 | ; |
上面代码中,严格模式下,set
代理返回false
或者undefined
,都会报错。
apply()
apply
方法拦截函数的调用、call
和apply
操作。
apply
方法可以接受三个参数,分别是目标对象、目标对象的上下文对象(this
)和目标对象的参数数组。
1 | var handler = { |
下面是一个例子。
1 | var target = function () { return 'I am the target'; }; |
上面代码中,变量p
是 Proxy 的实例,当它作为函数调用时(p()
),就会被apply
方法拦截,返回一个字符串。
下面是另外一个例子。
1 | var twice = { |
上面代码中,每当执行proxy
函数(直接调用或call
和apply
调用),就会被apply
方法拦截。
另外,直接调用Reflect.apply
方法,也会被拦截。
1 | Reflect.apply(proxy, null, [9, 10]) // 38 |
has()
has()
方法用来拦截HasProperty
操作,即判断对象是否具有某个属性时,这个方法会生效。典型的操作就是in
运算符。
has()
方法可以接受两个参数,分别是目标对象、需查询的属性名。
下面的例子使用has()
方法隐藏某些属性,不被in
运算符发现。
1 | var handler = { |
上面代码中,如果原对象的属性名的第一个字符是下划线,proxy.has()
就会返回false
,从而不会被in
运算符发现。
如果原对象不可配置或者禁止扩展,这时has()
拦截会报错。
1 | var obj = { a: 10 }; |
上面代码中,obj
对象禁止扩展,结果使用has
拦截就会报错。也就是说,如果某个属性不可配置(或者目标对象不可扩展),则has()
方法就不得“隐藏”(即返回false
)目标对象的该属性。
值得注意的是,has()
方法拦截的是HasProperty
操作,而不是HasOwnProperty
操作,即has()
方法不判断一个属性是对象自身的属性,还是继承的属性。
另外,虽然for...in
循环也用到了in
运算符,但是has()
拦截对for...in
循环不生效。
1 | let stu1 = {name: '张三', score: 59}; |
上面代码中,has()
拦截只对in
运算符生效,对for...in
循环不生效,导致不符合要求的属性没有被for...in
循环所排除。
construct()
construct()
方法用于拦截new
命令,下面是拦截对象的写法。
1 | const handler = { |
construct()
方法可以接受三个参数。
target
:目标对象。args
:构造函数的参数数组。newTarget
:创造实例对象时,new
命令作用的构造函数(下面例子的p
)。
1 | const p = new Proxy(function () {}, { |
construct()
方法返回的必须是一个对象,否则会报错。
1 | const p = new Proxy(function() {}, { |
另外,由于construct()
拦截的是构造函数,所以它的目标对象必须是函数,否则就会报错。
1 | const p = new Proxy({}, { |
上面例子中,拦截的目标对象不是一个函数,而是一个对象(new Proxy()
的第一个参数),导致报错。
注意,construct()
方法中的this
指向的是handler
,而不是实例对象。
1 | const handler = { |
deleteProperty()
deleteProperty
方法用于拦截delete
操作,如果这个方法抛出错误或者返回false
,当前属性就无法被delete
命令删除。
1 | var handler = { |
上面代码中,deleteProperty
方法拦截了delete
操作符,删除第一个字符为下划线的属性会报错。
注意,目标对象自身的不可配置(configurable)的属性,不能被deleteProperty
方法删除,否则报错。
defineProperty()
defineProperty()
方法拦截了Object.defineProperty()
操作。
1 | var handler = { |
上面代码中,defineProperty()
方法内部没有任何操作,只返回false
,导致添加新属性总是无效。注意,这里的false
只是用来提示操作失败,本身并不能阻止添加新属性。
注意,如果目标对象不可扩展(non-extensible),则defineProperty()
不能增加目标对象上不存在的属性,否则会报错。另外,如果目标对象的某个属性不可写(writable)或不可配置(configurable),则defineProperty()
方法不得改变这两个设置。
getOwnPropertyDescriptor()
getOwnPropertyDescriptor()
方法拦截Object.getOwnPropertyDescriptor()
,返回一个属性描述对象或者undefined
。
1 | var handler = { |
上面代码中,handler.getOwnPropertyDescriptor()
方法对于第一个字符为下划线的属性名会返回undefined
。
getPrototypeOf()
getPrototypeOf()
方法主要用来拦截获取对象原型。具体来说,拦截下面这些操作。
Object.prototype.__proto__
Object.prototype.isPrototypeOf()
Object.getPrototypeOf()
Reflect.getPrototypeOf()
instanceof
下面是一个例子。
1 | var proto = {}; |
上面代码中,getPrototypeOf()
方法拦截Object.getPrototypeOf()
,返回proto
对象。
注意,getPrototypeOf()
方法的返回值必须是对象或者null
,否则报错。另外,如果目标对象不可扩展(non-extensible), getPrototypeOf()
方法必须返回目标对象的原型对象。
isExtensible()
isExtensible()
方法拦截Object.isExtensible()
操作。
1 | var p = new Proxy({}, { |
上面代码设置了isExtensible()
方法,在调用Object.isExtensible
时会输出called
。
注意,该方法只能返回布尔值,否则返回值会被自动转为布尔值。
这个方法有一个强限制,它的返回值必须与目标对象的isExtensible
属性保持一致,否则就会抛出错误。
1 | Object.isExtensible(proxy) === Object.isExtensible(target) |
下面是一个例子。
1 | var p = new Proxy({}, { |
ownKeys()
ownKeys()
方法用来拦截对象自身属性的读取操作。具体来说,拦截以下操作。
Object.getOwnPropertyNames()
Object.getOwnPropertySymbols()
Object.keys()
for...in
循环
下面是拦截Object.keys()
的例子。
1 | let target = { |
上面代码拦截了对于target
对象的Object.keys()
操作,只返回a
、b
、c
三个属性之中的a
属性。
下面的例子是拦截第一个字符为下划线的属性名。
1 | let target = { |
注意,使用Object.keys()
方法时,有三类属性会被ownKeys()
方法自动过滤,不会返回。
- 目标对象上不存在的属性
- 属性名为 Symbol 值
- 不可遍历(
enumerable
)的属性
1 | let target = { |
上面代码中,ownKeys()
方法之中,显式返回不存在的属性(d
)、Symbol 值(Symbol.for('secret')
)、不可遍历的属性(key
),结果都被自动过滤掉。
ownKeys()
方法还可以拦截Object.getOwnPropertyNames()
。
1 | var p = new Proxy({}, { |
for...in
循环也受到ownKeys()
方法的拦截。
1 | const obj = { hello: 'world' }; |
上面代码中,ownkeys()
指定只返回a
和b
属性,由于obj
没有这两个属性,因此for...in
循环不会有任何输出。
ownKeys()
方法返回的数组成员,只能是字符串或 Symbol 值。如果有其他类型的值,或者返回的根本不是数组,就会报错。
1 | var obj = {}; |
上面代码中,ownKeys()
方法虽然返回一个数组,但是每一个数组成员都不是字符串或 Symbol 值,因此就报错了。
如果目标对象自身包含不可配置的属性,则该属性必须被ownKeys()
方法返回,否则报错。
1 | var obj = {}; |
上面代码中,obj
对象的a
属性是不可配置的,这时ownKeys()
方法返回的数组之中,必须包含a
,否则会报错。
另外,如果目标对象是不可扩展的(non-extensible),这时ownKeys()
方法返回的数组之中,必须包含原对象的所有属性,且不能包含多余的属性,否则报错。
1 | var obj = { |
上面代码中,obj
对象是不可扩展的,这时ownKeys()
方法返回的数组之中,包含了obj
对象的多余属性b
,所以导致了报错。
preventExtensions()
preventExtensions()
方法拦截Object.preventExtensions()
。该方法必须返回一个布尔值,否则会被自动转为布尔值。
这个方法有一个限制,只有目标对象不可扩展时(即Object.isExtensible(proxy)
为false
),proxy.preventExtensions
才能返回true
,否则会报错。
1 | var proxy = new Proxy({}, { |
上面代码中,proxy.preventExtensions()
方法返回true
,但这时Object.isExtensible(proxy)
会返回true
,因此报错。
为了防止出现这个问题,通常要在proxy.preventExtensions()
方法里面,调用一次Object.preventExtensions()
。
1 | var proxy = new Proxy({}, { |
setPrototypeOf()
setPrototypeOf()
方法主要用来拦截Object.setPrototypeOf()
方法。
下面是一个例子。
1 | var handler = { |
上面代码中,只要修改target
的原型对象,就会报错。
注意,该方法只能返回布尔值,否则会被自动转为布尔值。另外,如果目标对象不可扩展(non-extensible),setPrototypeOf()
方法不得改变目标对象的原型。
Proxy.revocable()
Proxy.revocable()
方法返回一个可取消的 Proxy 实例。
1 | let target = {}; |
Proxy.revocable()
方法返回一个对象,该对象的proxy
属性是Proxy
实例,revoke
属性是一个函数,可以取消Proxy
实例。上面代码中,当执行revoke
函数之后,再访问Proxy
实例,就会抛出一个错误。
Proxy.revocable()
的一个使用场景是,目标对象不允许直接访问,必须通过代理访问,一旦访问结束,就收回代理权,不允许再次访问。
this 问题
虽然 Proxy 可以代理针对目标对象的访问,但它不是目标对象的透明代理,即不做任何拦截的情况下,也无法保证与目标对象的行为一致。主要原因就是在 Proxy 代理的情况下,目标对象内部的this
关键字会指向 Proxy 代理。
1 | const target = { |
上面代码中,一旦proxy
代理target
,target.m()
内部的this
就是指向proxy
,而不是target
。所以,虽然proxy
没有做任何拦截,target.m()
和proxy.m()
返回不一样的结果。
下面是一个例子,由于this
指向的变化,导致 Proxy 无法代理目标对象。
1 | const _name = new WeakMap(); |
上面代码中,目标对象jane
的name
属性,实际保存在外部WeakMap
对象_name
上面,通过this
键区分。由于通过proxy.name
访问时,this
指向proxy
,导致无法取到值,所以返回undefined
。
此外,有些原生对象的内部属性,只有通过正确的this
才能拿到,所以 Proxy 也无法代理这些原生对象的属性。
1 | const target = new Date(); |
上面代码中,getDate()
方法只能在Date
对象实例上面拿到,如果this
不是Date
对象实例就会报错。这时,this
绑定原始对象,就可以解决这个问题。
1 | const target = new Date('2015-01-01'); |
另外,Proxy 拦截函数内部的this
,指向的是handler
对象。
1 | const handler = { |
上面例子中,get()
和set()
拦截函数内部的this
,指向的都是handler
对象。
实例:Web 服务的客户端
Proxy 对象可以拦截目标对象的任意属性,这使得它很合适用来写 Web 服务的客户端。
1 | const service = createWebService('http://example.com/data'); |
上面代码新建了一个 Web 服务的接口,这个接口返回各种数据。Proxy 可以拦截这个对象的任意属性,所以不用为每一种数据写一个适配方法,只要写一个 Proxy 拦截就可以了。
1 | function createWebService(baseUrl) { |
同理,Proxy 也可以用来实现数据库的 ORM 层。