JavaScript基础
1.变量
1.1 命名规范
- 不用关键字(let,var…)
- 只由数字字母,下划线,$组成(数字不开头)
- 严格区分大小写
- 小驼峰命名:第一个单词首字母小写,后面单词首字母大写
1.2声明变量并赋值
- 组成:关键字(let/var) 变量 = xxx
2.常量
- const声明
- 声明同时初始化(赋值)
- 变量不会改变用const,不用let
2.数据类型
2.1 分类
- 基本数据类型/值类型:存储的是值本身
- number数字型(特殊:Nan,非数字类型)
- string字符串型(单引双引反引都可,推荐单引’ ')
- boolean布尔型(两固定值:真true 假false)
- undefined未定义型(只声明不赋值)
- null空类型(赋值了但内容为空)
- 引用数据类型/复杂类型:在存储时仅仅是地址
- new关键字创建的对象,如:Object、Array、Date
- 检测数据类型typeof,两种表示
- 运算符形式:typeof x(常用)
- 函数形式:typeof(x)
- 堆栈空间分配
- 栈:简单数据类型放栈
- 堆:存储复杂类型,一般由程序员释放,若不释放则由回收机制回收,引用数据类型放堆里
2.2类型转换
- 隐式转换:系统内部自动转换数据类型
- +作为正号可以转换成数字型
- 任何数据+字符都是字符串
- 除+外的其他算术运算符(- / *)会把数据转成数字类型
- 显式转换
- 转成数据型:Number(数据)
- parseInt:整数
- parseFloat:小数
2.3 字符串
- 单双引号可以互相嵌套,但不能自己嵌套自己
- 必要可用转义符\
- 字符串相连用+
- 模板字符串:解决字符串与变量相连麻烦的问题
- 用反引号``
- 引用变量${变量名}
3.运算符
3.1比较运算符
- =单等是赋值
- ==是判断(判断值是否一样,字符和数字比时会转成数字型)
- ===是全等(判断类型和值是否一样)
- !==不全等
- 比较运算符中字符串比较是Ascll码
- 比较运算符返回值是true/false
3.2逻辑运算符
- 与或非
- 优先级:! > && > ||
4.语句
4.1分支语句
-
if语句
- 单分支
- 双分支
- 多分支
1、括号里为true才执行语句
2、括号里的数字除了0 返回都为true
3、括号里的字符串除了null返回都为true
-
三元运算符?:
- 语法:
条件?满足条件执行的代码:不满足条件执行的代码
- 等于if双分支语句,适用于语句简单
- 前面可以赋值
- 语法:
-
switch语句
- 语法:
switch (数据) { case 值1: 代码1 break //退出switch语句 case 值2: 代码2 break default: 代码n break }
4.2循环语句
-
while循环
-
语法
while (循环条件) { 重复执行的代码(循环体) }
-
循环条件为真 才执行代码
-
三要素:起始值、终止条件、变量变化量(防止死循环)
-
适用于循环次数不确定
-
-
-
for循环
- 语法
for (变量起始值;终止条件;变量变化量) { //循环体 }
-
退出循环:break退出循环,continue 退出本次循环,继续下次循环
-
适用于循环次数确定
while(true)无限循环,for(;;)需要break退出
5.数组
5.1声明语法
法一:let 数组名 = [数据1,数据2,数据3,...,数据n]
法二(了解):let arr = new Array(数据1,数据2,数据3,...,数据n)
- 索引从0开始
- 字面量用中括号[]表示
5.2查询数组
- 查询
数组[下标]
5.3加新数据
- push方法
- 一个/多个元素加到末尾,并返回数组新长度
- 语法:
arr.push(元素1,元素2,...,元素n)
- unshift方法
- 将一个或多个元素加到数组开头,并返回数组新长度
- 语法:
arr.unshift(元素1,元素2,...,元素n)
5.4删除数组
- pop方法
- 删除最后一个元素,并返回该元素值
- 语法
arr.pop()
- shift方法
- 删除第一个元素,并返回该元素值
- 语法
arr.shift()
- splice方法
- 删除指定元素
- 语法
arr.splice(起始位置的索引号,删除元素个数)
5.5 数组排序
- sort函数
arr.sort(function(a,b){return a-b})
(默认升序) - 降序:返回值 return b - a 即可
5.6 数组的map方法
-
作用:获取数组的下标和元素,进行处理后返回一个新数组,两数组有映射关系
-
用法:
const arr = ['red','blue','pink'] const newArr = arr.map(function(ele, index){ return ele + '颜色' })
5.7 数组的join方法
-
作用:将数组转换为字符串
-
用法:
newArr.join() //结果:red颜色,blue颜色,pink颜色(默认逗号隔开) newArr.join('') //结果:red颜色blue颜色pink颜色 newArr.join('|') //结果:red颜色|blue颜色|pink颜色
6.函数
6.1函数的基本使用
- 声明
function 函数名(形式参数列表) {
函数体
}
参数列表逗号隔开
-
函数名命名规范
- 和变量命名基本一致
- 小驼峰起名
- 前缀为动词
动词 含义 can 是否可执行 has 是否含某值 is 是否为某值 get 获取某值 set 设置某值 load 加载某些数据
-
函数调用
- 语法
函数名(实际参数列表)
- 语法
-
参数默认值
- 若用户不输入实参,可给形参默认值,可默认为0
-
函数返回值return
- return后面的代码不会执行
- 函数可以无return,默认返回值undefined
-
在javascript中,实参和形参个数可不同
- 若形参多于实参,则会自动填充undefined
- 若实参多于形参,则多余实参被忽略
-
两个相同函数,后面会覆盖前面
-
作用域
- 分为全局作用域(函数外部/script)和局部作用域(函数内部)
- 特殊:局部变量/块级变量没有let直接当作全局(不推荐);函数内部的形参可以当作局部变量看
-
变量的访问原则:在能访问的情况下,先局部再全局(就近原则)
6.2 匿名函数
-
含义:无函数名的函数
-
表示形式:
- 函数表达式
let fn = function() { //函数体 } //调用 fn()
函数表达式必须先声明再调用
- 立即执行函数(避免全局变量之间的污染)
//方式1 (function (形参) { console.log(11)} ) (实参); //方式2 (function (形参) { console.log(11)}(实参));
第二个括号就是调用函数(括号里是实参),前面的括号包含了整个函数
=多个立即执行函数必须用逗号,隔开
6.3逻辑中断
- 短路:&&和||中,满足以下条件可让右边代码不执行
符号 | 短路条件 |
---|---|
&& | 左边为false就短路(一假全假) |
|| | 左边为true就短路(一真全真) |
原因:通过左边就能得到整个式子的结果
运算结果最后执行得到的值,一般要赋给变量
6.4类型转换
- 显式转换:Boolean(内容)
‘’、0、undefined、null、false、NaN转换为布尔值后都是false,其余为true
常用于if等语句的判断
- 隐式转换
- 字符串+数据变成字符
- 空字符串‘’-数字,空字符串看成0
- null经转换变0
- undefined经数字转换变NaN
7.对象
7.1什么是对象
- 一种数据类型,无序的数据集合
null类似于空对象let object={},用typeod检测为object
7.2 对象的使用
- 语法
let 对象名 = {} 或 let 对象名 = new Object()
{ }是对象字面量,[ ]是数组字面量
-
对象组成:属性+方法
- 属性:特征信息(名词)
多个属性逗号分隔,属性相当于变量
- 方法:功能/行为(动词)
let 对象名 = { 属性名:属性值, 方法名:function () { } }
方法调用:对象名.方法名
7.3对象的属性
- 查:两种表示方法
- 对象名.属性
- 对象名[‘属性’]——适用于属性是字符串的场景
- 改:对象名.属性=新值
- 增:对象名.新属性=新值
- 删(了解):delete 对象名.属性
7.4遍历对象
for (let k in obj) {
console.log(k) //打印属性名
console.log(obj[k]) //打印属性值
}
- for in 语法遍历对象
- k ==‘属性’
- 获得属性值必须用表示属性的第二种方法,即对象名[k]
7.5内置对象-Math
- 含义:是Javascript提供的数学对象,包含了许多方法
- random:生成0~1的随机数(不包含1)
生成N~M之间的随机数:
Math.floor(Math.random()*(M - N + 1))+ N
- ceil:向上取整(往大的取)
- floor:向下取整
- max:找最大数
- min:找最小数
- pow:幂运算
- abs:绝对值
- sqrt:平方根
API
1声明变量-const优先
- const:存储在栈里的数据不变便用const
- 有变量优先const,若后面要修改再改成let
- 数组和对象用const声明
- 对象是引用类型,存储的是地址,当修改对象的属性只是修改了堆里的内容,地址值不变,所以可以用const
- 用let
- 基本数据类型/引用数据类型的地址变化
- 一个变量进行加减运算
2 Web API分类
2.1作用
- 使用JS操作html和浏览器
2.2分类
-
分类:DOM(文档对象模型)和BOM(浏览器对象模型)
3DOM
3.1含义和作用
- 含义:文档对象模型
- 作用:操作网页内容,可以开发网页特效和实现用户交互
3.2 DOM树
- 含义:表示HTML文档的树状结构
- 作用:体现标签之间的关系
3.3DOM对象
- 含义:根据html标签生成的JS对象
- 这个对象有所有的标签属性
- 修改对象的属性会映射到标签上
- 核心思想:把网页内容当对象处理
- document对象
- DOM提供的对象
- 它带的属性和方法用来访问和操作网页内容
- 网页所有内容都在document里
3.4获取DOM对象
-
方式一:CSS选择器获取元素(重点)
1、获取单个元素
- 语法
document.querySelector('CSS选择器') //一定要用引号,否则就变成变量会报错!!
- 参数:包含一个/多个有效的选择器字符串
- 返回值:一个HTML元素对象,没有获取则返回null
2、获取多个元素
- 语法
document.querySelectorAll('ul li')
- 参数:包含一个/多个有效的选择器字符串
- 返回值:NodeList对象集合,是伪数组(有索引有长度,没有数组的push等方法),需要遍历得到每个元素
3.5修改元素内容属性
- 设置DOM元素内容
- 元素.innerText(对象的属性)——只识别文本,不解析标签
- 元素.innerHTML(对象的属性)——识别文本,解析标签
3.6修改元素样式属性
-
方法1:style属性操作样式
- 语法:
对象.style.样式属性 = 值
- 若样式属性有-,则改成小驼峰命名
- 值是字符串,且加单位
生成的CSS是行内样式,权重高
- 语法:
-
方法2:类名(className)操作样式
- 语法:
元素.className = 'active box' //acitive是新增类名,box是原来的类名(如果要保留的话)
- 类名不加点,且是字符串
- 新值换旧值,若需多加个类,需要保留之前的类名
- 语法:
-
方法3:classList操作样式(重点)
- 追加和删除类名
- 语法:
//追加类,类名不加点,且是字符串 元素.classList.add('类名') //删除类 元素.classList.remove('类名') //切换类 元素.classList.toggle('类名')
- 追加和删除不影响以前的类名
3.7修改表单元素属性
- 获取值
表单.value='用户名'
修改内容不用innerHTML(这是表单元素,不是普通元素)- 表单有些属性为布尔值true(t添加有效果)或false(移除没效果),如:disabled(按钮禁用属性)、checked(勾选选框)、selected
3.8自定义属性
-
标准属性:标签自带的属性
-
自定义属性:
- 属性名为data-xxx
- 自定义属性:DOM对象.dataset.xxx
dataset返回的是这个DOM对象的自定义属性集合,要获取某一属性需要用点语法操作
3.9定时器—间歇函数
- 目标:间隔一定时间,重复执行代码
- 语法:
let 变量名 = setInterval(函数名,间隔时间) //打开定时器
clearInterval(变量名) //关闭定时器
变量名 = setInterval(函数名,间隔时间) //再次打开定时器,因为相当于重新赋值,因此声明关键字用let
-
间隔时间单位是毫秒ms
-
每个定时器有一个专门的id号,返回的是这个id
-
函数名不加括号(调用标志)
注意:倒计时函数的调用函数两种方式,如果需要传参,可以在匿名函数里嵌套一个传参的函数
比如:
setInterval(function() {
daojishi(arg1, arg2); // 在匿名函数中调用带参数的函数
}, 1000)
3.10 事件监听
- 语法:
元素对象.addEventListener('事件类型',执行的函数)
同一元素可多次绑定不同事件,前面不会被后面覆盖
- 三元素
- 事件源:获取dom元素
- 事件类型:什么方式触发(如:鼠标单击/鼠标经过),要加引号
- 要调用的函数
元素.事件类型()
:利用JS自动调用元素的事件
3.11 事件类型
鼠标事件 | 焦点事件 | 键盘事件 | 文本事件 |
---|---|---|---|
click 鼠标点击 | focus 获得焦点 | Keydown 按下键盘 | input 输入事件 |
mouseenter 鼠标经过 | blur 失去焦点 | Keyup 抬起键盘 | |
mouseleave 鼠标离开 |
3.12 事件对象
- 语法
元素.addEventListener('click',function(e){} )
- 这里的e就是事件对象
- 一般命名为e、event、ev
- e的常用属性
属性 | 作用 |
---|---|
type | 获取当前的事件类型 |
clientX/clientY | 获取光标相对于浏览器的位置 |
offsetX/offsetY | 获取光标相对于当前dom元素的位置 |
key | 用户按下键盘的具体值 |
清除字符串两边的空格符可以用trim方法
3.13 环境对象
- 含义:函数内部的变量this,代表当前函数运行时所处的环境
- 直接调用,指代window
- 谁调用,this 就是谁
3.13 阻止表单默认行为(补充)
-
语法:
e.preventDefault()
-
原因:
当未指名form action 属性和button type类型或按下回车键,会先触发自定义按钮事件然后表单请求事件(表单又重新刷新了一遍),输入的结果不会显示
-
目的:阻止页面的刷新和跳转
-
方式一:解决点击没有设置type属性的按钮的默认行为
-
加上type属性,属性值选择不是submit
-
在button的事件处理函数中加入阻止默认行为的语句
submit_btn.onclick = function(e) { e.preventDefault();//阻止默认行为 console.log('submit_btn') }
-
-
方式二:解决input框按回车键的默认行为
-
form表单的onsubmit事件中加入阻止默认行为的语句
form_test.onsubmit = function(e) { e.preventDefault(); console.log('123') }
-
-
方式三:在form标签下加入onsubmit = "return false"的属性
转自原作者:山水猿
3.14 回调函数
- 函数A作为参数传给函数B,A就是回调函数
3.15 事件流
事件流指事件完整执行的流动路径:捕获阶段(父到子)—>冒泡阶段(子到父)
- 事件捕获
- 语法
DOM.addEventListener(事件类型,事件处理函数,是否捕获?)
- 第三个参数为true为捕获(很少使用)
- 语法
- 事件冒泡
- 当某元素触发事件后,依次想上调用所有父元素的同名事件类型
- 冒泡默认存在
- 第三个参数默认false,冒泡
- 阻止冒泡和捕获
- 语法
事件对象e.stopPropagation()
- 目的:不影响父级元素的同名事件
- 语法
3.17 事件委托
- 作用:减少注册次数,提高性能
- 绑定对象:父元素
- 原理:点击子元素,冒泡执行父元素事件
找到触发的的子元素:e.target;找到具体的名字e.target.tagName
3.18 页面加载事件load
-
作用:等外部资源加载完毕,再触发事件
这样的js代码可以写在和head头部
-
load事件
- 语法:`window.addEventListener(‘load’,function(){ })
也可以针对某个资源绑定load事件
-
DOMContentLoaded
- 语法:
document.addEventListener('DOMContentLoaded',function(){ })
- 特点:无需等待样式表,图像完全加载
- 语法:
3.19 页面滚动事件
-
scroll事件
-
语法:
window.addEventListener('scroll',function(){ } )
监听可以是某个元素
-
获取位置两大属性-scrollLeft、scrollTop
- 获取被卷的大小
- 内容往上或往左滚看不到的距离
- 数字型,两值可读写(可取值,也可赋值)
- 检测滚动距离:
window.addEventListener('scroll',function(){ //1、获取html元素 const n = document.documentElement.scrollTop //2、检测上部被卷距离 console.log(n) } )
尽量在scroll里面获取滚动距离
-
回到页面顶部的两种方式
- 直接设置属性
document.documentElement.scrollTop = 0
- 方法间接设置
window.scrollTo(0,0)
- 直接设置属性
3.20 页面尺寸事件
-
获取元素本身宽高(不算外边距)
- offsetWidth
- offsetHeight
获取的是可视宽高,若盒子隐藏则为0
-
获取位置
- 获取元素距离自己定位的祖先元素的左、上距离
- 若都没有定位则以文档左上角为准
offsetTop、offsetLeft只读属性
-
获取位置2:element.getBoundingClientRect()
这是个方法,返回的是元素大小和相对于可视区的位置
-
总结
属性 作用 说明 scrollLeft、scrollTop 被卷去的头部和左侧 可读写 clientWidth、clientHeight 获取元素宽高 不包含margin,border,滚动条,只读 offsetWidth、offsetHeight 获取元素宽高 包含padding,border,滚动条等,只读 offsetTop、offsetLeft 获取距离定位父级元素的距离 只读
3.21 日期对象
- 实例化关键字new
用法:const n = new Date(里面可以指定日期、时间)
- 日期对象方法:点语法调用
方法 | 作用 | 说明 |
---|---|---|
getFullYear() | 年 | |
getMouth() | 月 | 取值0~11,记得+1 |
getDate() | 日 | |
getDay() | 周几 | 0~6对应周日到周六 |
getHours/getMintues/getSeconds() | 时分秒 | |
toLocaleString() | 日期时间格式化 | 如:2024/3/24 16:06:23 |
toLocaleDateString() | 获得格式化日期 | 2024/3/24 |
toLocaleTimeString() | 获得格式化时间 | 16:08:04 |
-
时间戳ms
1、获取方式
-
getTime()方法
const date = new Date() console.log(data.getTime())
-
+new Date()
console.log(+new Date())
无需实例化 -
Date.now()
无需实例化,但只能得到当前的时间戳
2、倒计时毫秒转换公式
- d = parseInt(总秒数/60/60/24); //计算天数
- h = parseInt(总秒数/60/60%24); //计算小时
- m = parseInt(总秒数/60%60); //计算分数
- s = parseInt(总秒数%60); //计算秒数
-
3.22 节点操作
-
查找节点
-
父节点:parentNode属性,返回最近一级的父节点,找不到返回为null
子元素.parentNode
-
子节点:children属性,亲儿子(返回伪数组)
-
兄弟节点:nextElementSibling上一个兄弟 previousElementSibling下一个兄弟
-
-
新增节点:先创建,再追加
-
创建节点
document.createElement('标签名')
-
插入到网页里
-
插入到父元素的最后一个子元素
父元素.appendChild(要插入的元素)
-
插入到父元素的某个子元素之前
父元素.insertBefore(要插入的元素,在哪个元素之前)
-
-
-
克隆节点:复制原有节点,放入指定元素内部
元素.cloneNode(布尔值)
- 布尔值为true—深度克隆,会包含后代节点(文本、元素等)
- 布尔值为false(默认)为浅度克隆,只复制该标签
-
删除节点:要经过父元素才能删除节点
父元素.removeChild(要删除的元素)
- 若不存在父子关系则删除不成功
3.23 M端的触屏事件
- 只有移动端才有
touch事件 | 说明 |
---|---|
touchstart | 触摸到DOM元素 |
touchmove | 滑动DOM元素时触发 |
touchend | 从DOM元素移开时触发 |
4.Window对象
4.1BOM
- 含义:浏览器对象模型(Browser Object Model)
- window对象是一个全局对象
- 像document,alert(),console.log()都是window的属性,基本BOM方法都是window的
- 调用window对象的属性和方法时可以省略window
- 所有通过var定义在全局作用域的变量和函数都会变成window的属性和方法
4.2 定时器—延时函数
-
含义:一段代码延迟执行
-
语法:
let timer = setTimeout(回调函数,等待的毫秒数)
-
清除延时函数:
clearTimeout(timer)
4.3 JS执行机制
-
异步和同步
-
同步:都在主线程上执行,形成执行栈
-
异步:JS的异步通过回调函数执行,一般有以下三种类型
- 普通事件,click、resize等
- 资源加载,load、error等
- 定时器,包括setInterval、setTimeout等
异步任务加到任务队列中
-
-
执行顺序:先同步后异步
由于主线程不断获得任务,执行任务,再获取再执行,这种机制称为事件循环(event loop)
4.4 location对象
- 作用:拆分并保存了URL地址的各个部分
- href属性获取完整的url地址,对其赋值可用于地址跳转
- search属性获取地址中的参数,符号?后面
- harsh属性获取地址中的哈希值,符号#后面部分
- 刷新方法
location.reload() //刷新
,括号传入true为强制刷新
4.5 nevigator对象
-
含义:记录了浏览器的相关信息
-
通过
navigator.userAgent
拿到当前浏览器与操作系统的信息- 检测方法
!(function () { const userAgent = nevigator.userAgent //验证是否为Agent或iPhone const android = userAgent.match(/(Android);?[\s\/]+([\d.]+)?/) const iphone = userAgent.match(/(iPhone\sOS)\s([\d_]+)/) //如果是安卓后iPhone,则跳到移动站点 if(android || iphone){ location.href = 'http://m.itcast.cn' } } )()
4.6 history对象
- 含义:管理历史记录,与浏览器的前进后退操作对应
- 相关方法:
对象方法 | 作用 |
---|---|
back() | 后退 |
forward() | 前进 |
go() | 参数1:前进;2:后退 |
5.本地存储
- 作用:数据存在用户浏览器中,页面刷新不丢失
- 分类:localStorage、sessionStorage
5.1 localStorage
- 作用:数据永久存储在本地,(除了删除)
- 特点:
- 同一浏览器的多个页面可共享
- 键值对形式存储
- 本地存储默认类型字符串
- 语法:
- 存储/修改
localStorage.setItem('key','value')
都要加引号! - 获取/查找
localStorage.getItem('key')
- 删除
localStorage.removeItem('key')
- 存储/修改
5.2 sessionStorage
- 特性:
- 关闭浏览器窗口数据就会丢失
- 同一个页面下可共享数据
- 键值对存储
- 语法同上
5.3 存储复杂数据类型
- 原因:本地只能存字符串,想要存复杂类型需要转换
- 语法:JSON.stringify(复杂数据类型)
- 结果:就变成JSON字符串
5.4 获取复杂数据类型
- 原因:本地存的是字符串,无法直接获取对象
- 语法:JSON.parse(JSON字符串)
6.正则表达式
6.1含义
匹配字符串中字符组合的模式
6.2 作用(使用场景)
- 匹配(表单验证)
- 替换(过滤敏感词)
- 提取
6.3 使用
-
步骤:定义规则 — 查找是否匹配
-
定义规则:
const a = /需要匹配的字符/
//是正则表达式的字面量
-
test()方法:匹配有符合规则的字符串,
- 语法:
a.test(被检测的字符串)
- 返回的是布尔值,匹配返回true,反之为false
- 语法:
-
exec()方法:查找符合规则的字符串
- 返回的是一个数组,否则为null
6.4 元字符
-
含义:有特殊含义的字符
-
分类:边界符(开头^/结尾$)、量词(重复次数)、字符类
-
如果^和$表示精确匹配
-
量词:设定某个模式的次数
- +表示>=1次
- *表示>=0次
- ?表示重复0次或1次
- [m,n]表示重复m到n次,括号里不要加空格!!
-
字符类
-
[ ]匹配字符串集合
-
/[abc]/
字符串中只要包含abc任一字符都返回true,是三选一-表示连字符:
- [a-z]
- [a-zA-Z]
- [0-9]
-
^写在[ ]里是非的意思,写在外面才是以xx开头
-
-
字符点 “ . ” :匹配除换行符外的任一字符
-
预定义:常见模式的简写模式
预定类 说明 \d [0-9] 匹配0-9任一数字 \D [^0-9] 匹配除0-9外的任一字符 \w [a-zA-Z0-9] 匹配任一字母、数字、下划线 \W [^a-zA-Z0-9] 匹配除任一字母、数字、下划线外的字符 \s [\t\r\n\v\f] 匹配空格 \S [^ \t\r\n\v\f] 匹配非空格的字符 -
6.5 修饰符
-
作用:约束正则的细节
-
语法:
/表达式/修饰符
-
i是正则匹配忽略字母大小写
-
g是需满足所有正则匹配的结果/全局应用
-
replace:替换掉原字符串的部分字符
需要替换的字符串.replace(/正则表达式/,'替换的文本')
JS进阶
1.作用域
1.1作用域链
- 本质:变量查找机制
- 规则:
- 优先在当前作用域中查找变量
- 若查不到会依次逐级查找父级作用域直到全局
1.2 垃圾回收机制GC
-
内存分配的生命周期:
- 内存分配:声明变量/函数/对象时,系统自动分配内存
- 内存使用:使用
- 内存回收
全局变量一般不会回收,局部变量不用了自动回收
-
内存泄漏:由于程序,内存未释放
-
堆栈空间分配
- 堆:存放基本数据类型,系统自动分配释放
- 栈:复杂数据类型,程序员或垃圾回收机制回收
-
垃圾回收机制
-
引用计数:跟踪次数,多+1少-1,变0回收
嵌套引用(两对象相互引用)无法回收,导致内存泄漏
-
标记清除法:从根部扫描,回收查找不到的
-
1.3 闭包
-
内层函数+外层函数的变量
-
作用:
- 封闭数据,实现私有化,
- 外部也能访问内部变量
-
可能会引起内存泄漏
全局变量指向外部函数的调用,由于全局变量不会被回收,垃圾回收机制无法回收
1.4 变量提升
- 关键字var会有变量提升:提升到当前作用域的最前面
- 提升声明,不提升赋值
2.函数进阶
2.1 函数提升
- 函数在声明前可被调用
- 提升声明,不提升赋值
- 函数表达式不会提升,必须先声明再调用(因为提升的是变量,但不赋函数)
2.2 函数参数—argument动态参数
- 只存在函数中
- 伪数组
2.3 函数参数—剩余参数
- 运算符:…
- 使用场景:获取多余实参,放在最末函数形参
- 获取的实参是真数组
2.4 展开运算符
- 运算符:…
- 使用场景:数组中使用,求数组最大/小值,合并数组等
2.5 箭头函数
- 语法
const a = ( x ) => { x + x }
- 常用于函数表达式,不存在函数提升
- 当只有一个形参可省略括号
- 当函数体只有一行代码可省略花括号{ }
- 加括号的函数体返回对象表达式
箭头函数不会创建this,它沿用的是上一层作用域的this
Dom事件回调函数不要用箭头函数
3.解构赋值
3.1 数组解构
-
含义:将数组单元值批量赋值给对应变量
-
有两种情况需要加分号:
-
立即执行函数
-
数组解构
;[b,a]=[a,b]
-
3.2 对象解构
- 含义:将对象属性和方法赋值给变量
4.对象扩展
4.1 构造函数的方式
-
作用:创建多个类似对象
-
对象字面量
const o = {name:'佩奇'}
-
new Object创建对象
const o = new Object({name:'佩奇'})
-
构造函数
- new 关键字调用称为实例化
- 函数名开头大写
- 没有参数可以省略括号()
- 函数体内返回的是新创建对象,不需要写return(无效)
function Pig(name,age){ this.name = name this.age = age } //构造函数创建对象 const Peppa = new Pig('佩奇',6)
4.2 new实例化过程
- 创建新对象
- 构造函数this指向新对象
- 执行函数代码,修改this,添加新属性
- 返回新对象
4.3 实例成员和静态成员
实例成员
- 实例对象的属性和方法称为实例成员
- 实例对象相互独立
静态成员
- 构造函数的属性和方法称为静态成员
4.4 内置构造函数
更多方法参考MDN
-
Object: keys,values,assign(静态方法)
-
Array:
实例方法
方法 作用 说明 forEach 遍历数组 不返回数组,用于遍历数组元素 filter 过滤数组 返回新数组,筛选满足条件的元素 map 迭代数组 返回新数组,返回处理后的 reduce 累计器 返回累计处理的结果,常用于求和 join 可用于拼接数组元素成字符串 find 查找符合条件的元素,返回第一个数组元素值,若无则返回undefined every 检查数组所有元素是否符合条件,符合返回true,否则返回false some 检查数组元素是否符合条件,符合返回true,否则返回false Array.from 伪数组转真数组 静态方法 reduce语法:
arr.reduce(function(上一次值,当前值){},起始值)
若有起始值,则将其累加到里面
-
String
实例方法
方法 | 作用 | 说明 |
---|---|---|
length | 获取长度 | |
split(‘分隔符’) | 拆分成数组 | 和join相反 |
substring | 截取 | 左闭右开,不包含结束索引的值 |
startsWith | 判断是否以某字符开头 | 返回布尔值 |
includes | 判断一个字符串是否在另一个字符串中 | 返回布尔值 |
- Number:用于创建数值
-
num.toFixed(2):保留几位小数
-
5 编程思想
5.1 面向过程
- 按步骤依次调用函数
- 性能高
- 难维护,难复用,扩展性差
5.2 面向对象(oop)
- 事务分解成一个个对象
- 特性:
- 封装性
- 继承性
- 多态性
- 性能较低
- 易维护,易复用,易扩展
JS通过构造函数实现面向对象
构造函数里有复杂数据类型时会浪费内存
6 原型
6.1 原型(对象)
- 含义:prototype为原型对象,是构造函数的一个属性
- 作用:有同个构造函数创建的多个对象可共享方法
- 构造函数和原型里的this指向实例化对象
6.2 constructor属性
- 原型和对象原型里的constructor属性指向构造函数
6.3 对象原型
-
__proto__
是JS非标准属性 -
__proto__
等价于[[prototype]]
-
表示当前实例对象指向哪个原型对象prototype
-
只能获取不能赋值
-
__proto__
里也有constructor属性,指向构造函数对象原型指向原型对象
6.4 原型继承
- 目的:多个由不同构造函数创建的实例对象有相同的公共属性
- 方式:每个实例对象通过原型继承公共部分(由新的构造函数创建),子类的原型 = new 父类
6.5 原型链
- 含义:基于原型对象的继承使不同构造函数的原型对象关联,这种关联的关系是链状结构,将原型对象的链状结构称为原型链
7 拷贝
深浅拷贝都只针对引用类型
7.1 浅拷贝
- 拷贝的是地址
- 常见方法:
- 拷贝对象:
Object.assgin(新,旧)
/展开运算符const new = {...obj}
- 拷贝数组:
Array.prototype.concat()
或者[…arr]
- 拷贝数组:
- 拷贝对象:
浅拷贝适用于对象只有一层,有多层,里面还是直接指向地址
7.2 深拷贝
-
拷贝的是对象,不是地址
-
方法
-
递归函数:
一个函数在内部调用本身,这叫递归函数
容易栈溢出,必须加退出条件
步骤:
1.通过调用函数将旧对象赋值给原对象
2.若是简单数据类型则直接赋值
3.若是复杂数据类型,通过递归继续调用函数
4.函数里的判断条件是先数组后对象最后才是简单数据类型
-
利用js库的lodash里的_.cloneDeep()
需要先引用地址
<script src = 'lodash.md.js'> </script>
语法:_.cloneDeep()
const newObject = _.cloneDeep(oldObject)
-
JSON的字符串转换(不能克隆函数)
const newObject = JSON.parse(JSON.stringify(oldObject))
8 异常处理
8.1 throw抛出异常
- 作用:预估程序执行可能出现的错误,并抛出异常中断运行
- throw后面跟错误提示信息
- throw搭配Error对象使用,能看到更详细的错误信息
function counter(x,y){ if(!x || !y){ throw new Error('参数不能为空!') } return x+y }
8.2 try/catch 捕获异常
-
-
作用:try里检测代码执行是否出错,catch接收error参数,若出错则执行catch代码,并截获错误信息,finally代码段无论前面是否出错都会执行
-
语法:
function foo(){
try{
const p = document.queSelector('.p')
p.style.color = 'red'
}catch (error){
//这两行代码也能用throw语句代替,能打印信息也能阻止程序运行
console.log(error.message)
return
}finally{
alert('无论是否储蓄哦都会执行的代码')
}
console.log('若出现错误,该代码不会执行')
}
8.3 debugger
- 在某段代码前写这个相当于打断运行代码会自动停到当前这个地方
9 this处理
9.1 this指向
-
普通函数this指向
谁调用就指谁,没有明确调用者this指向window,但在严格模式下会指向undefined
-
箭头函数this指向
- 函数内不存在this,它沿用的是上一级的
- 不适用Dom对象的回调函数,构造函数,原型函数等
9.2 改变this
-
作用:动态指定普通函数this指向
-
call() ——了解
- 使用该方法调用函数,并指定this的值
- 语法:
fun.call(this指向的对象,实参1,实参2,...)
-
apply()
- 与call方法类似,区别只在于第二个是实参数组
- 语法:
fun.apply(this指向的对象,[实参数组])
该方法有两种使用场景:一是改变this指向;二是求数组最大值(现在ES6改进用展开运算符求最大值)
const arr =[100,22,44] const max1 = Math.max.apply(null,arr) coonst max2 = Math.max(...arr)
-
bind()方法
- 不会立即调用函数,适用于比如定时器(默认指向window)里改变this指向
- 语法:
fun.bind(this指向的对象,实参1,实参2,...)
- 返回的是有指定的this和原函数拷贝
10 性能优化
10.1防抖
-
含义:在单位时间内,频繁触发事件,只执行最后一次
停止执行完
-
使用场景:搜索栏输入,表单的验证
-
实现方式:
-
lodash里的debounce方法
_.debounce(需要防抖的函数,延迟时间)
-
手写防抖函数:核心是利用setTimeout定时器实现
步骤:
1.声明定时器变量
2.每次触发事件判断是否有定时器,有则清除
3.没有则开启定时器并存入变量
4.定时器写函数的调用
function debounce(fn, t){ //1 let time //返回一个匿名函数 234 return function (){ if(time) clearTimeout(time) time = setTimeout(function(){ fn() },t) } }
-
10.2节流 —— throttle
-
含义:在单位时间内,频繁触发事件,只执行一次
开始后必须执行完
-
使用场景:鼠标移动mousemove,页面缩放reszie,滚动条scroll
-
实现方式:
-
lodash里的throttle方法
_.debounce(需要防抖的函数,间隔时间)
-
手写节流函数
步骤:
1.声明一个定时器变量
2.当鼠标移动是判断是否有定时器,有则不开启
3.没有则开启定时器
4.定时器除了调用函数,还要记得清空定时器便于下次回调节流函数
function throttle(fn,t){ let time = null return function(){ if(!time){ time = setTimeout(function(){ fn() //不能用clearTimeout,因为此时在定时器匿名函数里,无法关闭 time = null },t) } } }
-