前言
JavaScript
是一种轻量级的脚本语言,所谓脚本语言就是指它不具备开发操作系统的能力,而只是用来编写控制其他大型应用程序的脚本。 JavaScript
是一种嵌入式语言,本身提供的核心语法不算很多,可用于 html
和 web
,更可广泛应用于服务器,PC等设备
类似于 C 语言,一行一行的执行,每一行就是一条语句
优点
- 操控浏览器的能力
- 广泛的使用领域
- 易学
与ECMAScript 的关系
ECMAScript
和 JavaScript
的关系,前者式后者的规格。后者是前者的一种实现
将js引入到html文件中
嵌入到文件中
需要在 <body>
标签之内嵌入
1 | <body> |
引入独立js文件
要在 script
标签内定义 type
和 src
属性
1 | <script type="text/javascript" src="./语法.js"></script> |
type
表示引入文件类型src
文件的路径
引入网络来源文件
1 | <script src="https://..."></script> |
其中的 src
就是引入的 js 文件的网址,不需要指定 type
类型
语法
标识符
标识符指的是用来识别各种值的合法名称,最常见的标识符就是变量名,标识符是由字母,dollar符号,下划线和数字组成,不能以数字开头,中文是合法的标识符,可做变量名,不推荐
保留关键字
在 js 中的保留关键字不能用作标识符
变量
可以被赋值的标识符,类似于 C 语言
注释
js 中代码的注释不会被引擎解释,有两种写法
- 行注释
//
- 块注释
/*...*/
- 嵌入在
html
中的注释<!--...-->
输出
有多种输出方式
alert(content)
弹窗输出document.write(content)
文件写入console.log(content)
终端输出
数据类型
- 原始数据类型
- 数值
- 字符串
- 布尔值
- 特殊值
- undefined
- null
- 合成类型
- 对象
- 新增类型
- Symbol
- BigInt
运算符
- typeof运算符 可以检测数据类型,对于数据类型中,
null
和undefined
都可以表示没有,将一个变量做这两种赋值是没有区别的 +
-
*
/
%
++
--
=
+=
-=
*=
/=
%=
<
>
<=
>=
==
===
严格相等!=
!==
严格不相等!
&&
||
条件语句
if
if...else if...else
switch...case...default
三目运算符
1 | (condition) ? a : b; |
循环语句
for
while()
跳出循环的语句 break
中断循环, continue
终止此次循环,开启下次循环
字符串
由零个或多个放在双引号或者单引号之中的字符,单引号字符串内部可以使用双引号,双引号字符串内部可以使用单引号。对于双引号内部使用双引号和单引号内部使用单引号,必须使用转义 \'
和 \"
常用方法
length
属性,返回字符串的长度charAt()
返回指定位置的字符concat()
用于连接两个字符串,返回一个新的字符串,不改变原字符串,可以接收多个字符串,如果参数不是字符串会将其转为字符串然后连接substring()
截取字符串,两个参数,第一个表示开始位置,第二个表示结束位置,不包括结束位置,默认是到末尾,会自动调换两和位置的顺序,保证小的在前,会把负数转为 0substr()
截取字符串,两个参数,第一个表示开始位置(从0开始),第二个表示截取长度,到结束为止。第一个参数为 0 意味着倒着计算字符的为止,第二个参数小于等于 0 返回空字符串indexOf()
用于确定一个字符串在另一个字符串中第一次出现的为止,返回结果是匹配开始的为止,如果返回-1
表示没有匹配项,还可以接受第二个参数,表示从该位置向后匹配trim()
去除字符串两端的空格,返回新的字符串,不改变源字符串,去除的不仅仅是空格,还有换行,回车和制表符split()
按照某个字符来分割,就是以某个字符作为分割符,从字符串中找到该字符时将该字符作为分割符把字符串分割,如果分割字符为空,则返回源字符的每一个字符
数组
是按照次序排列的一组值,每个值位置都有编号,整个数组用方括号表示,位置排列从 0 开始,这个数组是一个通用的数组,任何数据都可以被放入数组中
length
属性,返回数组的长度- 遍历,可以使用
for
循环,或者是while
循环,使用for(... in ...)
进行循环 Array.isArray()
返回一个布尔值,表示参数是否为数组,可以弥补typeof
运算符的不足,这个方法不是数组的内部元素push()
用于在数组的末端添加一个或多个元素,并且返回添加新元素后的数组长度,该方法会改变原数组pop()
用于删除数组的最后一个元素,并且返回该元素shift()
用于删除数组的第一个元素,并且返回该元素,会改变原数组unshift()
用于向元素第一个位置添加元素,并且返回该数组的长度,会改变原数组,可以接收多个参数,这些参数都会添加到目标数组头部join()
指定参数作为分割符,将所有数组成员连接成为一个字符串,默认为逗号,对于数组中的数组,就使用逗号进行分割,如果数组成员时undefined
或者null
或者空位,会被转为空字符串concat()
用于多个数组的合并,将新数组的成员添加到原数组候补,并且返回一个新数组,原数组不变,也支持其它类型的值reverse()
用于颠倒原数组,返回改变后的数组,但是会改变原数组indexOf()
返回给定元素在数组中第一次出现的位置,如果没有出现则返回-1
,可接受第二个参数,表示开始查找的位置
函数
是一块能反复调用的代码块,使用 function
命令声明代码区块,就是一个函数 function
命令后面就是函数名,函数名之后是一对圆括号,里面是传入函数的参数,函数体放在打括号内,类似于C语言,但在小括号内的参数不需要添加参数类型
函数声明时,只需要将函数名和形参声明即可.
对象
对象就是键值对,是一种无序的符合数据集合,声明类似于 python
中的字典
对象的每一个键名又称为属性,它的键值可以是任何数据类型
如果一个属性的值为函数,通常把这个属性称为方法,可以像调用函数一样调用
如果属性值还是一个对象,就形成了链式引用
math对象
是 JS 的原生对象,提供各种数学功能
Math.abs()
返回绝对值Math.max()
返回最大值Math.min()
返回最小值Math.floor()
返回小于参数值的最大整数Math.ceil()
返回大于参数值的最小整数Math.random()
返回 0 到 1 之间的一个伪随机,可能等于 0,但一定小于 1
Date对象
date
是 JavaScript
原生的时间库,以1970年1月1日0点作为时间的零点,可以表示的时间范围是前后各一亿天
Date.now()
返回当前时间距离时间零点的毫秒数- 时间戳,就是距离时间零点的秒数
Date.getTime()
返回实例距离时间零点毫秒数Date.getDate()
返回实例对象对应每个月的几号Date.getDay()
返回实例星期几,周日为Date.getYear()
返回距离1900的年数Date.getFullYear()
返回四位的年份Date.getMonth()
返回月份Date.getHours()
返回小时Date.getMilliseconds()
返回毫秒Date.getMinutes()
返回分钟Date.getSeconds()
返回秒
js错误
- 使用
try
语句测试代码块的错误 - 使用
catch
语句处理错误 - 使用
throw
创建自定义错误,相当于是抛出错误 - 使用
finally
语句在最后,无论上述是否触发错误,都会执行的语句
1 | try{ |
let声明
let
声明的变量旨在当前代码块内有效
const声明
const
声明的变量一旦声明,常量的值就不能改变
变量提升
就是有时候会在变量声明之前使用,这时候不会报错,而变量的值为 undefined
dom
dom是 JavaScript
操作网页的接口,是文档对象模型。作用是将网页转为一个 JavaScript
对象,从而使用脚本进行各种操作,比如对元素的增删改等
浏览器会根据 dom 模型,将结构化文档 html
解析成一系列的节点,再由这些节点组成一个树状结构 dom tree
。所有的节点和最终的树状结构都有对外的接口。
dom 就是一个接口规范,可以用各种语言实现,但是 dom 是 JavaScript
最常见的任务
节点
dom 的最小组成单位为节点,文档的树形结构是不同的节点组成的,每个节点相当于是文档树的一片叶子,类型有 7 种,如下
Document
文档树的顶层节点DocumentType
doctype标签Element
网页各种 html 标签Attribute
网页元素的属性Text
标签之间或标签包含的文本Comment
注释DocumentFragment
文档的片段
节点树
一个文档的所有节点,按照所在的层级,可以抽象成一种树状结构。浏览器原生提供 document
节点,代表整个文档。除了根节点,其他节点都有如下三种层级关系
- 父节点关系:直接的上级节点
- 子节点关系:直接的下级节点
- 同级节点关系:拥有同一个父节点的节点
Node.nodeType
Node类型 | Named Constant |
---|---|
1 | ELEMENT_NODE |
2 | ATTRIBUTE_NODE |
3 | TEXT_NODE |
4 | CDATA_SECTION_NODE |
5 | ENTITY_REFERENCE_NODE |
6 | ENTITY_NODE |
7 | PROCESSING_INSTRUCTION_NODE |
8 | COMMENT_NODE |
9 | DOCUMENT_NODE |
10 | DOCUMENT_TYPE_NODE |
11 | DOCUMENT_FRAGMENT_NODE |
12 | NOTATION_NODE |
不同节点的 nodeType
属性值和对应的常量如下
Document
9DocumentType
1Element
2Attribute
3DocumentFragment
11
document 获取元素
getElementsByTagName()
通过搜索 html 标签名返回符合条件的元素,返回值是一个类似数组对象的,如果没有匹配的元素,返回空集getElementsByClassName()
通过类名搜索,返回包含该类名的元素,元素的变化也会实时返回在结果中,参数可以是多个,通过空格分隔getElementsByName()
用于选择拥有name
属性的 html 元素,返回一个类似数组的对象getElementById()
匹配指定 id 属性的元素节点,如果没有发现节点,返回 nullquerySelector()
接受一个css
选择器作为参数返回匹配该选择器的元素节点,如果有多个返回第一个querySelectorAll()
接受一个css
选择器作为参数返回匹配该选择器的元素节点,返回一个数组
document 创建元素
createElement()
生成元素节点,并且返回该节点,参数是元素类型createNextNode()
用于生成文本节点,并且返回该节点,参数是文本节点的内容createAttribute()
生成一个新的属性节点,并且返回该节点
element 对象属性
element
对象对应于网页的 html
元素,每一个 html
元素都会被转化为一个 element
节点对象
id
属性返回指定元素的id
属性,该属性可读写className
用于读写该元素节点的class
属性,值是一个字符串,中间用空格隔开classList
有如下方法add()
增加一个class
remove()
移除一个class
contain()
检查当前元素是否包含某个class
toggle()
将某个class
移入或移除当前元素
innerHTML
返回一个字符串,等于该元素包含的所有html
代码,该属性可读写,用来设置节点的内容,能改写所有元素节点的内容,包括<html>
和<body>
元素innerText
与上述类似,不同的是该方法会直接渲染为字符串
element 获取元素位置
clientHeight
获取元素高度,包括padding
但是不包括border
和margin
,只对块级元素生效,如果有水平滚动条,需要减去水平滚动条的高度clientWidth
获取元宽度,同上scrollHeight
元素总高度,同上,但是包括溢出的不可见的内容scrollWidth
元素总宽度,同上scrollLeft
元素水平滚动条向右滚动的像素效果scrollTop
元素水平滚动条向下滚动的像素效果offsetHeight
元素的 CSS 垂直高度,包括元素本身的高度,padding
和border
offsetWidth
元素的 CSS 垂直高度,同上offsetLeft
元素到定位父级左边界的间距offsetTop
元素到定位父级上边界的间距
CSS 操作
操作 CSS
样式最简单的办法就是,对 html
元素的 style
属性进行操作,有三种操作方式
- 使用
setAttribute
设置属性style
的参数 - 使用元素节点的
style
属性进行设置 - 使用元素节点的
style
属性设置该属性的cssText
进行设置样式
事件处理程序
html
事件处理,类似于按钮点击特效果dom
0级事件处理,其中html
和js
是分离的,但是无法添加多个事件dom
2级事件处理,其中html
和js
是分离的,可以添加多个事件
鼠标事件
鼠标事件指的是与鼠标相关的事件,具体
click
按下鼠标触发dblclick
在同一个元素上双击鼠标触发mousedown
按下鼠标时触发mouseup
释放鼠标时触发mousemove
鼠标在节点内部移动时触发,鼠标持续移动,该事件会持续触发mouseseenter
当鼠标进入一个节点时触发,进入子结点不会触发mouseleave
当鼠标离开一个节点时触发,离开父结点不会触发这个事件mouseover
鼠标进入一个节点时触发,进入子结点会再次触发mouseout
鼠标离开一个节点时触发,离开父结点也会触发wheel
滚动鼠标滚轮时触发
事件对象
一个事件发生以后,会产生一个事件对象,作为参数传给监听函数
属性
Event.Target
返回事件当前所在的节点Event.type
返回一个字符串,表示事件类型,事件类型是在生成事件时产生,该属性只读
方法
Event.preventDefault()
取消浏览器对当前事件的默认行为Event.stopPropagation()
阻止事件在dom
中继续传播,防止再次触发在别的节点上的监听函数,但是不包括在当前节点上的其它事件的监听函数,例如对于父子元素都有点击事件,当点击子元素时,父元素也会触发点击事件,这个方法能阻止子元素点击事件的扩散,以至于不会触发父元素的点击事件
键盘事件
用户击打键盘触发主要有三个事件
keydown
按下键盘时触发keypress
按下有值的键时触发,也就是按下ctrl
,alt
等无值的键不会触发,对于有值的键,先触发keydown
再触发keypress
keyup
松开键盘时触发的事件
event对象
keyCode
表示你所按下的按键的代码
表单事件
是使用表单元素以及输入框元素可以监听的一系列事件
input
当<input>
,<select>
和<textarea>
的值发生变化时触发,对于复选框<input type=checkbox>
或单选框<input type=radio>
,当用户改变选项时,也会触发这个事件,每按下一次按键就会触发一次select
当<select>
事件在<input>
和<textarea>
中选中文本时触发Change
当<input>
,<select>
和<textarea>
的值发生变化时触发,但是只有当全部修改完之后才会触发reset
这是发生在表单对像上的,当表单重置时触发submit
这是发生在表单对象上的,当表单数据向服务器提交时触发,发生对象是<form>
元素,而不是<button>
元素
事件代理
由于事件会在冒泡阶段传递给父结点,因此可以把子结点的监听函数定义在父结点,由父结点的监听函数统一处理多个子元素的事件,这种方法就是代理
定时器setTimeout
js
中提供定时执行代码的功能,叫做定时器,主要由 setTimeout
和 setInterval
两个函数完成,它们向任务队列中添加定时任务
setTimeout
用来指定某个函数或者某段代码,在多少毫秒之后运行,返回一个整数,表示定时器的编号,以后可以取消定时器,接收两个参数,第一个参数是将要推迟执行的函数名或者一段代码,第二个参数是推迟执行的毫秒数,只执行一次。还有就是如果回调函数是对象的方法,那么该函数使得方法内部this
关键字指向全局环境,而不是定义时所在的那个对象setInterval
这个函数与上述定时器的函数几乎一致,唯一不同之处在于这个函数的定时器是循环执行无数次clearTimeout(id)
取消定时器,参数就是上述的定时器编号
防抖
防抖严格来说应该属于性能优化事件,对于高频的信息,处理不当会导致浏览器卡死,例如一个滚动条监听的例子
1 |
|
一次滚动能产生好多条消息,执行频率太高了,会导致网页卡顿,有一种解决方式就是在第一次触发时,不立即执行函数,而是给一个期望值的定时器去执行,然后如果在这个期望值内没有发生触发滚动条件,那就执行函数,如果在这段时间内再次触发事件,那之前的计时取消,从新开始计时,从而保证短时间内多次触发只执行一次函数
节流
节流也属于是性能优化的功能,对于上述的防抖,就会导致在规定的时间段内,不断触发滚动事件,只要不停止触发,理论上就永远不会输出当前距离顶部的位置
节流就是在某次触发之后,函数执行一次之后,在短时间内不会再次触发,过了一段事件之后才生效
对于防抖的常用场景
- 搜索框
input
要支持实时搜索可以使用节流方案,或者实现输入间隔大于某个值之后就当作输入完成,然后开始搜索 - 页面
resize
事件,用于需要做页面适配的时候,根据最终呈现的情况进行dom
渲染就可以了,一般会使用防抖,因为只需要判断最后一次的变化情况就可