JavaScript笔记
- JS中的整除运算
- 传值与传址
- P2_JavaScript的组成部分
- P3_书写位置
- P4_变量
- P5_数据类型
- P6_数据类型转换
- P7_运算符
- P8_条件分支语句-if
- P10_条件分支语句-switch
- P12_循环结构语句-while
- P13_循环结构语句-dowhile
- P14_循环结构语句-for
- P17_函数
- P18_递归函数
- P19_作用域
- P20_对象数据类型
- P21_数组数据类型
- P24_数组常用方法
- P25_字符串常用方法
- P26_数字常用方法
- P26_时间常用方法
- P28_BOM操作
- P29_定时器
- P30_DOM操作(上)
- P34_DOM操作(下)
- P36_事件(上)
- P38_事件(下)
- P40_面向对象
- P41_面向对象-创建对象的方式
- P42_面向对象-构造函数的使用
- P43_面向对象-构造函数的不合理
- P44_面向对象-原型(prototype)
- P46_原型
- P47_构造函数的不好
- P48_解决问题
- P49_原型链
- P50_问题1、问题2
- P51_问题3
- P52_问题4、问题5
- P53_问题6、问题7
- P54_ES6-定义变量
- P55_ES6-箭头函数
- P56_ES6-函数参数默认值
- P57_ES6-解构赋值
- P58_ES6-模板字符串
- P59_ES6-展开运算符
- P60_ES6-类语法
- P61_认识前后端交互
- P62_认识接口文档
- P63_Ajax-第一次测试
- P64_Ajax-第二次测试
- P65_Ajax-GET和POST的区别
- P66_Ajax-GET和POST请求测试
- P68_jQuery-引入
- P69_jQuery-选择器
- P70_jQuery-筛选器
- P71_jQuery-操作元素文本内容
- P72_jQuery-操作元素类名
- P73_jQuery-操作元素样式
- P74_jQuery-操作元素属性
- P75_jQuery-获取元素尺寸
- P76_jQuery-获取元素偏移量
- P77_jQuery-事件绑定
- P78_jQuery-事件解绑和触发
- P79_jQuery-基本动画函数
- P80_jQuery-折叠动画函数
- P81_jQuery-渐隐渐显动画函数
- P82_jQuery-综合动画函数
- P83_jQuery-结束动画函数
- P84_jQuery-Ajax请求
- 补充
对应b站视频:【千锋前端JavaScript全套教程_JS零基础完美入门到项目实战】https://www.bilibili.com/video/BV1W54y1J7Ed?vd_source=99b0080c20437dec6ac4e3437f81d47a
【千锋教育JavaScript全套视频教程(10天学会Js,kerwin前端javascript入门必备)】https://www.bilibili.com/video/BV15T411j7pJ?vd_source=99b0080c20437dec6ac4e3437f81d47a
JS中的整除运算
Math.ceil(count / pagesize); // 向上整除 4/3=2;
Math.floor(count / pagesize); // 向下整除 4/3=1;
Math.round(count / pagesize); // 四舍五入
parseInt(count / pagesize); // 丢弃小数部分,保留整数部分
传值与传址
- 值类型是传值的
- 对象和数组是传址的
P2_JavaScript的组成部分
BOM:JS 操作浏览器发生变化的属性和方法
DOM:JS 操作文档流发生变化的属性和方法
ECMAScript:JS 代码的书写语法和书写规则
- JS 的作用:用 ECMAScript 语法去操作浏览器和文档流
P3_书写位置
- 行内式 - 直接把代码书写在标签身上
- a 标签 - 书写在 href 属性上:
<a href="javascript: JS代码 ;"></a>
- 非 a 标签 - 书写在标签的行为属性上:
<div 行为属性=" JS代码 "></div>
- a 标签 - 书写在 href 属性上:
- 内嵌式 - 代码书写在一个 script 标签内
<script></script>
- 不需要依赖任何行为,打开页面就会执行
- 外链式 - 代码书写在一个 .js 文件内
- XXX.js
<script src="路径"></script>
- 不需要依赖任何行为,打开页面就会执行
- 使用 script 标签的 src 属性引入指定 JS 文件
P4_变量
- 在程序运行过程中,保存一个中间值使用
var num = 100;
- 变量可以由数字、字母、下划线、美元符组成,其它内容不行且不能以数字开头
- 严格区分大小写
- 不能是关键字
- 最好使用一些有意义的单词
// 单行注释
/*
多行注释
*/
- alert() 在浏览器弹窗显示
- console.log() 在控制台打印
- document.write() 直接在页面输出
P5_数据类型
-
数值类型:正负整数、科学计数法、0x(十六进制)、0o(八进制)、0b(二进制)
-
字符串类型:一切以“单引号”和“双引号”包裹的
-
布尔类型:true、false
-
空类型null:有值,有一个空值
-
undefined:表示没有值
-
检测数据类型:
var res = typeof 要检测的数据
P6_数据类型转换
- 转数值
Number(要转换的内容)
- 解析规则:整体不可转换为数值则返回 NaN
parseInt(要转换的内容)
- 挨个位转,只有第一位就不是数字类型才返回 NaN
parseFloat(要转换的内容)
- 解析规则与 parseInt 相同,但是可以解析到小数位
- 转字符串
String(要转换的内容)
要转换的内容.toString()
- 转布尔
要转换的内容.Boolean()
- 0、NaN、undefined、‘(空字符串)’、null 会被转换为 false
P7_运算符
- 算数运算符
- “+”:当符号两边都是数字或者布尔的时候会进行数学运算;符号任意一边是字符串的时候会进行字符串拼接
- “-”:减法运算
- “*”:乘法运算
- “/”:除法运算
- “%”:取余运算
- 赋值运算符
- “=”:进行赋值操作
- “+=”:
- “-=”:
- “*=”:
- “/=”:
- “%=”:
- 比较运算符
- “>”
- “<”
- “>=”
- “<=”
- “==”:等于比较 只比较值,不考虑数据类型
- “===”:全等于比较 比较值和数据类型
- “!=”:不等于比较
- “!==”:不全等于比较
- 逻辑运算符
- “&&”:与
- “||”:或
- “!”:非
- 自增自减运算符
- “++”:前置++
++变量
,先把变量的值改变,再用改编后的值参与运算;后置++变量++
,先把变量现在的值拿来参与运算,然后再改变变量的值 - “–”
- “++”:前置++
P8_条件分支语句-if
if (条件1) {
代码;
} else if (条件2) {
代码;
} else {
代码;
}
P10_条件分支语句-switch
switch (条件) {
case 选项1:
代码;
break;
case 选项2:
代码;
break;
……
default:
代码;
}
- 如果不写 “break” 则会从第一个满足条件的位置向下穿透
- default 会在所有选项都不匹配时执行
P12_循环结构语句-while
while (条件) {
会被重复执行的代码;
……
}
P13_循环结构语句-dowhile
do {
会被重复执行的代码;
……
} while (条件)
P14_循环结构语句-for
for (定义初始变量; 条件判断; 改变初始值) {
重复执行的代码;
……
}
P17_函数
// 定义
function fn(形参1, 形参2, ……) {
装在盒子里的代码;
……
return 结果;
}
// 调用
fn(实参1, 实参2, ……)
- 形参:一个特殊的变量,只能在函数内部使用,函数调用的时候由实参确定0
P18_递归函数
- 一个函数,调用了它自身,并设置了结束条件
function fn(n) {
if(n===1) return 1;
return n * fn(n-1);
}
P19_作用域
P20_对象数据类型
var 对象名 = {
键: 值,
键: 值,
……
}
- 增:
对象名.键 = 值;
对象名['键'] = 值;
- 删:
delete 对象名.键
delete 对象名['键']
- 改:
对象名.键 = 值;
对象名['键'] = 值;
- 查
对象名.键
对象名['键']
P21_数组数据类型
var 数组名 = [值1, 值2, ……]
- 数组内可以存储任何数据类型
- 索引从0开始,依次加一
P24_数组常用方法
数组.push(数据)
将数据追加到数组的末尾 返回追加数据后数组最新的长度数组.pop()
删除数组的最后一个数据 返回被删除的数据数组.unshift(数据)
在数组的最前面添加一个数据 返回添加数据后数组的长度数组.shift()
删除数组的最前面的一个数据 返回被删除的数据数组.reverse()
将数组反转 返回反转之后的数组数组.splice(开始索引(默认0), 多少个(默认0), 要插入的数据(默认没有))
删除数组中若干数据,并选择是否插入(从哪删除,就从哪插入)新的数据 以新数组的形式返回被删除的数据
数组.sort() // 字典序
数组.sort( function (a, b) { return a-b; } ) // 从小到大
数组.sort( function (a, b) { return b-a; } ) // 从大到小
- 作用:把数组进行排序
- 返回值:排好序的数组
数组.join(连接符)
将数组用连接符连接成为一个字符串 返回连接好的字符串数组.concat(其他数组)
将其他数组和数组拼接在一起 返回拼接好的新数组数组.slice(开始索引(默认0), 结束索引(默认提取到数组末尾))
截取数组中的某些数据 以新数组的形式返回截取出来的数据数组.indexOf(数据)
查找数据在数组中的索引位置 如果有该数据则返回第一次出现的索引位置,没有返回-1
数组.forEach( function ( item, index, arr ) {
// 数组的每一项
console.log(item)
// 索引
console.log(index)
// 原始数组
console.log(arr)
} )
- 遍历数组 无返回值
数组.map( function ( item, index, arr ) { return 映射条件; } )
映射数组 映射后的新数组数组.filter( function ( item, index, arr ) { return 过滤条件; } )
过滤数组 过滤后的新数组数组.every( function ( item, index, arr ) { return 条件; } )
判断数组是不是每一项都满足条件 返回一个布尔值数组.some( function ( item, index, arr ) { return 条件; } )
判断数组是不是有某一项满足条件 返回一个布尔值数组.find( function ( item, index, arr ) { return 条件; } )
判断数组是不是有某一项满足条件 返回该元素
P25_字符串常用方法
字符串.charAt(索引)
获取对应索引位置的字符 返回对应索引位置的字符字符串.toLowerCase()
将字符串内的字母全部转换成小写 返回转换好的字符串字符串.toUpperCase()
将字符串内的字母全部转换成大写 返回转换好的字符串字符串.replace(换下内容, 换上内容)
将字符串内第一个满足换下内容的片段替换成换上内容字符串.trim()
去除字符串首尾的空格 返回去除首尾空格后的字符串字符串.split(分隔符)
按照分隔符(必须是字符串中本来就含有的符号)将字符串切割成为一个数组 返回切割后的数组字符串.substr(开始索引, 多少个)
截取字符串 返回截取出来的字符串字符串.substring(开始索引, 结束索引)
截取字符串(包含开始索引,不包含结束索引) 返回截取出来的字符串字符串.slice(开始索引, 结束索引)
截取字符串(包含开始索引,不包含结束索引) 返回截取出来的字符串
P26_数字常用方法
Math.random()
获取0~1之间的随机小数,包含0,不包含1 返回0~1之间的随机小数Math.round(数字)
对数字进行四舍五入取整 返回四舍五入后的整数Math.ceil(数字)
对数字进行向上取整 返回向上取整后的整数Math.floor(数字)
对数字进行向下取整 返回向下取整后的整数Math.pow(底数, 指数)
对数字进行取幂运算 返回取幂运算的结果Math.sqrt(数字)
对数字进行二次方根运算 返回二次方根后的结果(只保留正数结果)Math.abs(数字)
对数字进行绝对值运算 绝对值运算的结果Math.max(数字1, 数字2, ……)
获取若干数字的最大值 返回若干数字中的最大值Math.min(数字1, 数字2, ……)
获取若干数字的最小值 返回若干数字中的最小值Math.PI
得到一个近似 π 的值(最多小数点后17位)
P26_时间常用方法
// 创建一个当前时间节点的时间对象
var time = new Date();
// 创建一个指定时间节点的时间对象(0表示一月)
var time = new Date(年, 月, 日, 时, 分, 秒);
获取:
时间对象.getFullYear()
获取时间对象中的年份信息时间对象.getMonth()
获取时间对象中的月份信息(0表示一月)时间对象.getDate()
获取时间对象中的日期信息时间对象.getHours()
获取时间对象中的小时信息时间对象.getMinutes()
获取时间对象中的分钟信息时间对象.getSeconds()
获取时间对象中的秒钟信息时间对象.getDay()
获取时间对象中的星期信息时间对象.getTime()
获取时间对象中的时间戳信息(ms)
设置:
时间对象.setFullYear(数字)
设置时间对象中的年份信息时间对象.setMonth(数字)
设置时间对象中的月份信息(0表示一月)时间对象.setDate(数字)
设置时间对象中的日期信息时间对象.setHours(数字)
设置时间对象中的小时信息时间对象.setMinutes(数字)
设置时间对象中的分钟信息时间对象.setSeconds(数字)
设置时间对象中的秒钟信息时间对象.setTime(数字)
设置时间对象中的时间戳信息(ms)
P28_BOM操作
- 一套操作浏览器相关内容的属性和方法
1. 获取浏览器窗口尺寸
- 获取可视窗口宽度:
window.innerWidth
- 获取可视窗口高度:
window.innerHeight
2. 浏览器的弹出层
- 提示框:
window.alert('提示信息')
- 询问框:
window.confirm('提示信息')
返回一个布尔值 - 输入框:
window.prompt('提示信息')
返回输入的内容或 null
3. 开启和关闭标签页
- 开启:
window.open('地址')
- 关闭:
window.close()
4. 浏览器常见事件
- 资源加载完毕:
window.onload = function () {}
- 可视尺寸改变:
window.onresize = function () {}
- 滚动条位置改变:
window.onscroll = function () {}
5. 浏览器的历史记录操作
- 回退页面:
window.history.back()
- 前进页面:
window.history.forward()
6. 浏览器卷去的尺寸
- 卷去的高度:
- 有 “DOCTYPE” 标签:
document.documentElement.scrollTop
- 无 “DOCTYPE” 标签:
document.body.scrollTop
- 有 “DOCTYPE” 标签:
- 卷去的宽度:
- 有 “DOCTYPE” 标签:
document.documentElement.scrollLeft
- 无 “DOCTYPE” 标签:
document.body.scrollLeft
- 有 “DOCTYPE” 标签:
- 一般使用 “||” 运算符来兼容:
document.documentElement.scrollTop || document.body.scrollTop
7. 浏览器滚动到
- 滚动到(瞬间定位):
window.scrollTo(left, top)
- left:浏览器卷去的宽度
- top:浏览器卷去的高度
- 滚动到(滚动):
window.scrollTo( {
left: xx,
top: yy,
behavior: 'smooth' // 设置定位方式是平滑滚动
} )
P29_定时器
1. 间隔定时器
- 按照指定周期(毫秒)去执行指定的代码
setInterval(函数, 时间)
- 函数:每次要执行的内容
- 时间:单位是ms
setInterval(function () {
要执行的代码;
}, 1000)
2. 延时定时器
- 在固定的时间(毫秒)后执行一次代码
setTimeout(函数, 时间)
setTimeout(function () {
要执行的代码;
}, 1000)
- 定时器的返回值:不区分定时器,表示是当前页面的第几个定时器
关闭定时器
-
clearInterval(要关闭定时器的返回值)
-
clearTimeout(要关闭定时器的返回值)
-
可互相关闭,不区分定时器种类
P30_DOM操作(上)
- 操作文档流相关内容的属性和方法
获取元素
1. 根据 id 名称获取:
document.getElementById('id名称')
- 获取文档流中该 id 名对应的一个元素
- 返回值:有 id 对应的元素,则就是这个元素;没有 id 对应的元素返回 null
2. 根据元素类名获取:
document.getElementsByClassName('元素类名')
- 获取文档流中所有该类名对应的元素
- 返回值:必然是一个伪数组(如果有类名对应的元素,则有多少获取多少;没有则返回空的伪数组)
3. 根据标签名获取
document.getElementsByTagName('标签名')
- 获取文档流中所有标签名对应的元素
- 返回值:必然是一个伪数组(如果有标签名对应的元素,则有多少获取多少;没有则返回空的伪数组)
4. 根据选择器获取一个
document.querySelector('选择器')
- 获取文档流中满足选择器规则的第一个元素
- 返回值:如果有选择器对应的元素,则获取到第一个;没有则返回 null
5. 根据选择器获取一组
document.querySelectorAll('选择器')
- 获取文档流中所有满足选择器规则的元素
- 返回值:必然是一个伪数组(如果有选择器对应的元素,则有多少获取多少;没有则返回空的伪数组)
操作元素内容
- 操作元素文本内容:
- 获取:
元素.innerText
- 设置:
元素.innerText = '新内容'
- 获取:
- 操作元素超文本内容
- 获取:
元素.innerHTML
- 设置:
元素.innerHTML = '新内容'
- 获取:
操作元素属性(一般不用做操作元素的类名和样式)
- 原生属性:
- 获取:
元素.属性名
- 设置:
元素.属性名 = '属性值'
- 获取:
- 自定义属性:
- 获取:
元素.getAttribute('属性名')
- 设置:
元素.setAttribute('属性名', '属性值')
- 删除:
元素.removeAttribute('属性名')
- 获取:
操作元素的类名
- 获取:
元素.className
- 设置:
元素.className = '新类名'
操作元素行内样式
- 获取:
元素.style.样式名
- 设置:
元素.style.样式名 = '样式值'
- 带有中划线的样式名,在 JS 中要改为 “驼峰命名法”
获取元素非行内样式
- 获取:
window.getComputedStyle(元素).样式名
- 可以获取行内样式,也可以获取非行内样式
- 无设置非行内样式的方法
P34_DOM操作(下)
节点操作
1. 创建节点
document.createElement('标签名称')
- 创建一个指定标签元素
- 返回值:一个创建好的元素节点
2. 插入节点
- 语法1:
父节点.appendChild(子节点)
把子节点放在父节点内部最后的位置 - 语法2:
父节点.insertBefore(要插入的子节点, 哪一个子节点的前面)
把子节点放在父节点内部一个已经存在的子节点前面的位置
3. 删除节点
- 语法1:
父节点.removeChild(子节点)
从父节点内删除某一个子节点 - 语法2:
节点.remove()
把自己删除
4. 替换节点
父节点.replaceChild(换上节点, 换下节点)
在父节点内使用换上节点替换掉换下节点
5. 克隆节点
节点.cloneNode(是否克隆后代节点)
- 把该节点复制一份一模一样的内容
- 返回值:克隆好的节点
获取元素尺寸
- 语法1:
元素.offsetHeight
元素.offsetWidth
- 获取元素 “内容+padding+border” 区域的尺寸
- 语法2:
元素.clientHeight
元素.clientWidth
- 获取元素 “内容+padding” 区域的尺寸
P36_事件(上)
- 前端开发人员通过代码的方式和页面中的某些内容做好一个约定,当用户真实触发指定行为的时候就会执行这些代码
事件绑定
- 三要素
- 事件源:和谁做好约定
- 事件类型:约定一个什么行为
- 事件处理函数:当用户触发该行为的时候,执行什么代码
- 语法:
事件源.on事件类型 = 事件处理函数
div.onclick = function () {
要执行的代码;
}
事件类型
事件对象
- 当事件触发的时候,一个描述该事件信息的对象数据类型
// 直接在事件处理函数接收形参
// 浏览器传递的实参就是本次事件的事件对象
div.onclick = function(e) {
console.log(e)
}
事件对象内的信息 - 鼠标事件
- 坐标信息
- offsetX、offsetY 相对于触发事件的元素的坐标点位
- clientX、clientY 相对于浏览器可视窗口的坐标点位
- pageX、pageY 相对于页面文档流的坐标点位
事件对象内的信息 - 键盘事件
事件对象.keyCode
P38_事件(下)
事件传播
- 浏览器响应事件的机制
- 浏览器窗口最先知道事件的发生
- 捕获阶段:从 window 开始,按照结构子级的顺序传递到目标
- 目标阶段:准确触发事件的元素接收到行为
- 冒泡阶段:从 “目标” 按照结构父级的顺序传递到 window
- 本次事件传播结束
阻止事件传播
事件对象.stopPropagation()
outer.onclick = function () { console.log('我是 outer 元素,我被点击了') }
center.onclick = function () { console.log('我是 center 元素,我被点击了') }
inner.onclick = function (e) {
// 阻止事件传播
e.stopPropagation()
console.log('我是 inner 元素,我被点击了')
}
事件委托
利用事件冒泡的机制,把自己的事件委托给结构父级中的某一层
- 方便后期添加新的 LI
// 给 ul 绑定点击事件
ul.onclick = function (e) {
// 通过事件目标来判断点击的是 li
if (e.target.tagName === 'LI') {
console.log('点击的是 li')
}
}
P40_面向对象
-
面向过程:在开发过程中我们需要关注每一个细节、步骤、顺序
-
面向对象:在开发过程中我们看看有没有一个对象能帮我们完成任务
=> 如果有,直接让对象帮我们完成
=> 没有,则制造一个这样的对象来帮我完成 -
面向对象的核心:高内聚低耦合(就是对面向过程的高度封装)
P41_面向对象-创建对象的方式
- 找到一个机器,能批量生产对象
- 生产出来的对象,每一个都有自己的属性和方法
- 每一个对象可能类似,但是内容不太一样
- 构造函数
- 可以批量生产对象
- 可以像函数一样传递参数,也可以给每一个对象添加一些不同的内容
- 当你需要完成一个功能的时候,我们先制造一个构造函数
- 利用构造函数去创建一个可以完成任务的对象
- 依赖这个对象完成功能
- 这个 “机器(构造函数)” 要生产有属性有方法的合理的对象
- 机器:构造函数
- 属性:直接写在构造函数体内
- 方法:写在构造函数的原型上
1. 字面量方式创建对象 ×
var obj = {
name: 'Jack',
age: 18,
sayHi: function () { …… }
}
2. 内置构造函数创建对象 ×
var obj = new Object()
obj.name = 'Jack'
obj.age = 18
obj.sayHi = function () { …… }
3. 工厂函数创建对象
// 3-1 创建工厂函数
function createObj(name, age) {
// 手动创建一个对象
var obj = {}
// 手动向里面添加属性
obj.name = name
obj.age = age
obj.sayHi = function () { …… }
// 手动返回这个对象
return obj
}
// 3-2 使用工厂函数创建对象
var obj1 = createObj('Jack', 18)
var obj2 = createObj('Rose', 20)
4. 自定义构造函数创建对象
// 4-1 制造一个自定义构造函数
// 构造函数会自动创建对象,自动返回这个对象
// 我们只需手动向里面添加内容就可以了
function createObj(name, age) {
// 自动创建对象
// 手动向对象里面添加成员
// 这里的 this 指向当前实例(new 前面的变量)
this.name = name
this.age = age
this.sayHi = function () { …… }
// 自动返回对象
}
// 4-2 使用自定义构造函数去创建对象
// 构造函数在使用时需和 new 关键字连用
// 如果不连用,那么没有意义
var obj1 = new createObj('Jack', 18)
var obj2 = new createObj('Rose', 20)
P42_面向对象-构造函数的使用
- 构造函数和普通函数没有区别,只不过在调用的时候和 new 关键字连用
- 规范:书写构造函数函数名首字母大写(这样看到名字就知道要和 new 关键字连用)
- 调用的时候需要和 new 关键字连用
- 只有和 new 关键字连用的时候,这个函数才会有自动创建和返回对象的能力
- 之所以写构造函数就是为了使用它去批量生产对象,如果不和 new 关键字连用,那么该函数就没有创建对象的能力,也没有自动返回对象的能力
function Person() {
}
var obj = new Person()
- 调用构造函数的时候,如果不需要传递参数可以不写最后的小括号(不推荐)
var obj2 = new Person
- 当函数名和 new 关键字连用的时候,函数内部的 this 指向当前实例(new 关键字前面的变量);直接在函数体内部书写
this.xxx = 值
就是在向自动创建出来的对象里面添加内容 - 构造函数内部不要随便写 return
- 当你 return 了一个基本数据类型的时候,写了白写
- 当你 return 了一个复杂数据类型的时候,构造函数白写
P43_面向对象-构造函数的不合理
function Person(name, age) {
this.name = name
this.age = age
this.sayHi = function () { console.log('hello world') }
}
var p1 = new Person('Jack', 18)
var p2 = new Person('Rose', 20)
console.log(p1.sayHi == p2.sayHi) // false
- 当在构造函数体内书写方法的时候:当你需要向对象上添加方法的时候,只要创建一次对象(new 一次)就会有一个函数在占用空间,导致一样的函数重复占用空间
P44_面向对象-原型(prototype)
- 原型(prototype):
- 每个函数天生自带一个属性 “prototype”,它是一个对象
- 构造函数也是函数自然也有此属性,可以使用对象操作的语法向其中添加一些内容
- 对象:
- 当访问对象的成员的时候,如果其自己没有这个属性,会自动去所属构造函数的 prototype 上查找
- 自定义构造函数创建的对象也是对象,当访问其某一个成员的时候,如果没有也会自动去所属构造函数的原型上查找,哪一个构造函数创建的对象,这个对象就属于哪一个构造函数
function Person() {}
Person.prototype.sayHi = function () { conslole.log('我是 Person 原型上的方法') }
// 创建一个实例化对象
var p1 = new Person()
p1.sayHi()
- 只要向 Person 的原型上添加一些方法,由 Person 创建出来的每一个实例都可以使用,并且使用的都是同一个函数,不会浪费空间
P46_原型
- 当需要给实例对象添加方法,直接书写在构造函数体内这个行为并不好,原型可以解决这个问题
P47_构造函数的不好
- 当把方法书写在构造函数体内,每次创建实例的时候都会创建一个函数数据类型,多个函数方法一模一样,但是占据了多份存储空间
P48_解决问题
原型:
- 概念:每一个构造函数天生自带一个 prototype 属性,是一个对象数据类型
- 概念:每一个对象天生自带一个属性 __proto__,指向所属构造函数的 prototype
- 概念:当你访问对象的成员的时候,首先在自己身上查找,如果没有,自动去到 __proto__ 上查找
如何解决问题: - 我们把需要添加给实例的方法放在构造函数的原型(prototype)上,这样就可以由实例进行访问使用
// 当函数书写完毕后就会有 prototype 出现
function Person() {}
// 直接向 prototype 内添加一些成员
Person.prototype.a = 100
Person.prototype.b = 200
// 创建一个实例对象
// p1 所属的构造函数就是 Person,p1.__proto__ === Person.prototype
var p1 = new Person()
// 当访问 p1 的 a 成员,p1 没有,会去自己的 __proto__ 上查找
// 又因为自己的 __proto__ 就是 Person.prototype,所以其实是去 Person.prototype 上查找
console.log(p1.a)
function Person(name, age) {
// 向实例对象上添加属性
this.name = name
this.age = age
}
// 把想添加给实例对象的方法书写在原型上
Person.prototype.sayHi = function () { console.log('hello world') }
// p1 和 p2 所属的构造函数都是 Person
var p1 = new Person('Jack', 18)
var p2 = new Person('Rose', 20)
// p1.__proto__ === Person.prototype
// p2.__proto__ === Person.prototype
// 因为 p1.__proto__ 和 p2.__proto__ 是一个对象空间
// p1 和 p2 的 sayHi 是一个
console.log(p1.sayHi === p2.sayHi) // true
- 原型就是构造函数天生自带的一个 prototype,作用是由构造函数添加方法,专门给实例对象使用
P49_原型链
问题1:实例对象身上的 __proto__ 指向谁?
问题2:Person.prototype 的 __proto__ 指向谁?
问题3:Person 的 __proto__ 指向谁?
P50_问题1、问题2
问题1:实例对象身上的 __proto__ 指向谁?
- 指向所属构造函数的 prototype
- p1 所属构造函数是 Person
- p1.__proto__ 指向 Person.prototype
问题2:Person.prototype 的 __proto__ 指向谁?
- Person.prototype 是一个对象数据类型(object)
- 在 JS 中,所有的 object 数据类型都是属于 “Object” 这个内置构造函数
- 所以 Person.prototype 的 __proto__ 指向 Object.prototype
问题3:Person 的 __proto__ 指向谁?
问题4:Object.prototype 的 __proto__ 指向谁?
问题5:Object 的 __proto__ 指向谁?
P51_问题3
问题3:Person 的 __proto__ 指向谁?
- Person 是一个函数
- 在 JS 中,所有函数都属于内置构造函数 “Function" 的实例
- 所以 Person.__proto__ 指向 Function.prototype
问题4:Object.prototype 的 __proto__ 指向谁?
问题5:Object 的 __proto__ 指向谁?
问题6:Function.prototype 的 __proto__ 指向谁?
问题7:Function 的 __proto__ 指向谁?
P52_问题4、问题5
问题4:Object.prototype 的 __proto__ 指向谁?
- 虽然 Object.prototype 也是一个对象数据类型,但是
- 注意:Object.prototype 在 JS 中叫做 “顶级原型”,不再有 __proto__
- 所以 Object.prototype 的 __proto__ 指向 null
问题5:Object 的 __proto__ 指向谁?
- Object 是一个内置构造函数,总同时也是一个函数
- 在 JS 中,所有函数都属于内置构造函数 “Function” 的实例
- 所以 Object.__proto__ 指向 Function.prototype
问题6:Function.prototype 的 __proto__ 指向谁?
问题7:Function 的 __proto__ 指向谁?
P53_问题6、问题7
问题6:Function.prototype 的 __proto__ 指向谁?
- Function.prototype 也是一个对象数据类型
- 在 JS 中,所有的对象数据类型都是属于 “Object” 这个内置构造函数
- Function.prototype 的 __proto__ 指向 Object.prototype
问题7:Function 的 __proto__ 指向谁
- Function 是一个内置构造函数,也是一个函数
- 在 JS 中,所有函数都属于内置构造函数 “Function” 的实例
- Function 自己是自己的构造函数,自己是自己的实例对象
- Function 的 __proto__ 指向 Function.prototype
原型链:
- 用 __proto__ 串联起来的对象链状结构
- 注意:只能用 __proto__
- 每一个对象数据类型都有一个属于自己的原型链
- 作用:为了访问对象的成员(对象访问机制)
- 当你需要访问对象的成员的时候,首先在自身上查找,如果有直接使用
- 如果没有,会自动去 __proto__ 上查找
- 如果还没有,就再去深层的 __proto__ 上查找
- 直到 Object.prototype 都没有,那么返回 undefined
P54_ES6-定义变量
新增了两个定义变量的关键字
- let => 定义变量
- const => 定义常量(特殊的变量 )
区别:
var 与 let/const:
- var 会进行预解析,let/const 不会
console.log(num1) // undefined
var num1 = 100
console.log(num2) // 报错
let num2 = 200
- var 可以声明两个重名的变量,let/const 不能
var n1 = 100
var n1 = 200 // 正常
let n2 = 100
let n2 = 200 // 报错
- var 没有块级作用域,let/const 有
if (true) {
var num1 = 100
console.log(num1)
}
console.log(num1) // 正常
if (true) {
let num2 = 100
console.log(num2)
}
console.log(num2) // 报错
let 与 const:
- let 可以定义变量的时候不进行赋值,const 必须赋值
let num1
console.log(num1) // undefined
const num2
console.log(num2) // 报错
- let 定义的变量可以被修改,const 不能
let num1 = 100
num1 = 200 // 正常
const num2 = 100
num2 = 200 // 报错
P55_ES6-箭头函数
var fn1 = function () { console.log('我是 fn1 函数') }
var fn2 = () => { console.log('我是 fn2 函数') }
- 箭头函数某些时候可以省略 “()”:当只有一个形参时
var fn1 = () => { console.log('我没有形参') }
fn1()
var fn2 = a => { console.log('我一个形参: ', a) }
fn2(100)
var fn3 = (a, b) => { console.log('我两个形参: ', a, b) }
fn3(100, 200)
- 箭头函数某些时候可以省略 “{}”:当代码只有一句话的时候,并且会自动把结果当作返回值
var fn1 = function (a, b) {
return a + b
}
console.log(fn1(10, 20))
var fn2 = (a, b) => a + b
console.log(fn2(10, 20))
- 箭头函数内没有 “arguments”
var fn1 = function () {
console.log(arguments)
}
fn1(100, 200, 300) // 正常
var fn2 = () => {
console.log(arguments)
}
fn2(100, 200, 300) // 报错
- 箭头函数内没有 “this”,箭头函数的 this 就是外部作用域的 this
var obj = {
fn1: function () { console.log(this) },
fn2: () => { console.log(this) }
}
obj.fn1() // 因为 fn 函数被 obj 调用,所以 this 是 obj
obj.fn2() // 因为是箭头函数,内部没有 this,所以就是外部作用域的 this
P56_ES6-函数参数默认值
- 函数在定义的时候可以直接给形参设置一个默认值;当没有传递实参的时候,就使用默认值;当传递了实参,就使用传递的实参;普通函数可以使用,箭头函数也可以使用
function fn(a = 100, b = 200) {
console.log('a: ', a)
console.log('b: ', b)
}
fn() // 100 200
fn(10) // 10 200
fn(10, 20) // 10 20
P57_ES6-解构赋值
- 快速从对象或者数组中获取成员
- 快速从数组中获取数据(解构数组)
// 原始方法
var arr = ['hello', 'world']
var a = arr[0]
var b = arr[1]
// 解构赋值
var [a, b] = ['hello', 'world']
// 解构数组
var arr = ['hello', 'world']
var [a, b] = arr
- 快速从对象中获取数据(解构对象)
// 原始方法
var obj = {
name: 'Jack',
age: 18
}
var name = obj.name
var age = obj.age
// 解构赋值
var obj = {
name: 'Jack',
age: 18
}
var {name, age, a} = obj // 定义 name 变量和 age 变量,分别获取 obj 内叫做 name 和 age 的成员的值
console.log(a) // undefined
var {a} = obj
console.log(a) // undefined
var {age: 别名} = obj
console.log(别名) // 18
P58_ES6-模板字符串
- 就是 ES6 内新增的定义字符串的方式
// 原始方法
var str1 = '内容'
var str2 = "内容"
// ES6新方法
var str3 = `内容` // 反引号
区别:
- 可以换行书写
var str = `
hello
world
`
- 可以直接在字符串内解析变量,当需要解析变量的时候直接书写 ${ 变量 },省去字符串拼接的麻烦
var age = 18
var s1 = `我叫syp,今年 ${age} 岁`
P59_ES6-展开运算符
- …
- 作用:展开数组的 “[ ]” 或者是展开对象的 “{ }”
- 展开数组
console.log(100, 200, 300, 400)
var arr = [100, 200, 300, 400]
console.log(arr)
console.log(...arr)
// 作用1:合并数组
var arr1 = [10, 20]
var arr2 = [30, 40]
var arr3 = [50, 60, 70]
var arr4 = [...arr1, ...arr2, ...arr3]
// 作用2:给函数传递参数
var arr5 = [10, 54, 55, 2, 51, 24, 89,34]
var max = Math.max(...arr5)
- 展开对象
var obj1 = {
name: 'Jack',
age: 18
}
// 作用1:用来复制对象
// 在有相同成员时,注意展开书写的顺序问题
var obj2 = {
gender: '男',
...obj1
}
P60_ES6-类语法
- 就是 ES6 书写构造函数的方法
原始方法:
function Person(name, age) {
this.name = name
this.age = age
}
// 不好2:原型上的方法,写在原型外面
Person.prototype.sayHi = function () { console.log('hello world') }
// 书写静态属性和方法
Person.a = 100
Person.go = function () { console.log('跑起来') }
var p1 = new Person('Jack', 18)
// 不好1:构造函数本身是一个函数,本可以不和 new 关键字连用
var p2 = Person('Rose', 20)
console.log(p2) // undefined
console.log(Person.a)
Person.go()
类的书写:
class Person {
constructor (name, age) {
// 这里按照 ES5 的构造函数体书写
this.name = name
this.age = age
}
// 直接书写原型上的方法
sayHi () { console.log('hello world') }
// 静态属性
static a = 100
// 静态方法
static go () { console.log('跑起来') }
}
var p1 = new Person('Jack', 18)
var p2 = Person('Rose', 20) // 报错,类必须和 new 关键字连用
console.log(Person.a)
Person.go()
P61_认识前后端交互
P62_认识接口文档
P63_Ajax-第一次测试
Ajax步骤:
- 创建 ajax 对象
var xhr = new XMLHttpRequest()
- 配置本次请求信息
xhr.open(请求方式, 请求地址, 是否异步)
- 请求方式:按照接口文档来书写
- 请求地址:按照接口文档来书写
- 是否异步:默认是 true 表示异步请求,选填为 false,表示同步请求
- 注册请求完成事件
xhr.onload = function () {}
- 请求完成指本次请求发送出去,服务器接收到了我们的请求,并且服务器返回的信息已经回到了浏览器
- 把请求发送出去
xhr.send()
var xhr = new XMLHttpRequest()
xhr.open('GET', 'http://……', true)
xhr.onload = function {
// 获取后端返回的信息
console.log(xhr.responseText)
}
xhr.send()
P64_Ajax-第二次测试
var xhr = new XMLHttpRequest()
xhr.open('GET', 'http://……', true)
xhr.onload = function {
// 当后端返回 json 格式的字符串的时候,需要进行单独的解析
// 语法:JSON.parse(json格式字符串)
// 返回值:解析好的 js 格式的数据
var res = JSON.parse(xhr.responseText)
console.log(res)
}
xhr.send()
P65_Ajax-GET和POST的区别
GET
- 偏向获取的语义化
- 参数是查询字符串
- 大小有限制,2KB左右
- 参数位置在地址后面
xhr.open('GET', 'xxx?key=value&key2=value2')
POST
- 偏向提交的语义化
- 参数格式多样,但需要特殊说明
- 大小理论上没有限制
- 参数在请求体内
xhr.send(key=value&key2=value2)
P66_Ajax-GET和POST请求测试
GET
var xhr = new XMLHttpRequest()
// 带的参数由接口文档提供
xhr.open('GET', 'xxxx?name=syp&age=18', true)
xhr.onload = function () {
console.log(JSON.parse(xhr.responseText))
}
xhr.send()
POST
var xhr = new XMLHttpRequest()
xhr.open('POST', 'xxx', true)
xhr.onload = function () {
console.log(JSON.parse(xhr.responseText))
}
// POST请求特殊说明
// 语法: xhr.setRequestHeader('content-type', '传递参数的格式(由接口文档提供)')
xhr.setRequestHeader('content-type', 'application/x-www-form-urlencoded')
// 带的参数由接口文档提供
xhr.send('name=syp&age=18')
P68_jQuery-引入
- 一个大型的、简单的第三方类库
- 对常见的 DOM 操作进行了封装
<body>
<script src="路径"></script>
<script>
// 当引入 jQuery 文件后,会在全局暴露两个变量名:jQuery 和 $
// 二者作用相同
console.log($)
console.log(jQuery)
</script>
</body>
P69_jQuery-选择器
- 语法:$(‘选择器’)
<body>
<ul>
<li>1</li>
<li class="a">2</li>
<li>3</li>
<li class="b">4</li>
<li>5</li>
<li class="a">6</li>
<li>7</li>
<li id="box">8</li>
<li>9</li>
<li>10</li>
</ul>
<script src="路径"></script>
<script>
// 无论使用何种选择器,获取到的元素都是一个元素集合
// id 选择器
// 获取 id 名为 box 的元素的集合
console.log($('#box'))
// 类名选择器
console.log($('.a'))
// 标签名选择器
console.log($('li'))
// 结构选择器
console.log($('li:nth-child(odd)'))
</script>
</body>
P70_jQuery-筛选器
- 对选择器获取到的元素进行二次筛选
- 语法:$(‘选择器’).筛选器名称()
<body>
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5
<i>子两级</i>
</li>
<i>子一级</i>
<span>我是 ul 内的一个 span 标签</span>
<li>6
<p>
<i>子三级</i>
</p>
</li>
<li>7</li>
<li>8</li>
<li>9</li>
<li>10</li>
</ul>
<script src="路径"></script>
<script>
// 1.first()
console.log($('li').first())
// 2.last()
console.log($('li').last())
// 3.eq(索引)
console.log($('li').eq(3))
// 4.next()
console.log($('span').next())
// 5.nextAll()
console.log($('span').nextAll())
// 6.prev
console.log($('span').prev())
// 7.prevAll
console.log($('span').prevAll())
// 8.parent()
console.log($('span').parent())
// 9.parents()
// 获取的是该元素所有父级结构,逐层获取,直至 html 标签为止
console.log($('span').parents())
// 10.siglings()
// 拿到该元素所有兄弟元素
console.log($('span').siglings())
// 11.find('选择器')
// 找到该元素所有后代(子子孙孙)元素中满足选择器要求的元素
console.log($('ul').find('i'))
</script>
</body>
P71_jQuery-操作元素文本内容
1. html()
- 等价于原生 JS 中的 innerHTML
- 获取超文本内容
元素集合.html()
- 拿到该元素下的所有内容(包括 html 结构)
- 设置超文本内容
元素集合.html(要设置的内容)
- 可以识别并解析 html 结构字符串
2. text()
- 等价于原生 JS 中的 innerText
- 获取文本内容
元素集合.text()
- 拿到该元素下所有文本内容
- 设置文本内容
元素集合.html(要设置的内容)
- 不可以识别并解析 html 结构字符串
3. val()
- 等价于原生 JS 中的 value
- 多用于操作表单元素
- 获取 value
元素集合.val()
- 拿到该表单元素下的 value 值
- 设置 value
元素集合.val(要设置的内容)
- 设置该表单元素的 value 值
P72_jQuery-操作元素类名
1. addClass() 添加类名
- 语法:
元素集合.addClass(要添加的类名)
2. removeClass() 删除类名
- 语法:
元素集合.removeClass(要删除的类名)
3. toggleClass() 切换类名
- 语法:
元素集合.toggleClass()
- 切换:如果本身有这个类名,那么就是删除;如果本身没有这个类名,那么就是添加
P73_jQuery-操作元素样式
css()
- 获取样式
- 语法:
元素集合.css(要获取的样式名称)
- 可以获取元素的行内样式,也可以获取元素的非行内样式
- 返回值:该样式的样式值
- 语法:
- 设置样式
- 语法:
元素集合.css(样式名, 样式值)
- 当需要给一个元素设置样式值为 px 单位的时候,可以省略单位不写
- 语法:
- 批量设置样式
- 语法:
元素集合.css( {
// 所有需要设置的样式
样式名: 样式值,
……
} )
P74_jQuery-操作元素属性
1. attr()
- 一般用于操作元素的自定义属性(也可以操作原生属性)
- attr 操作的所有属性都会直接出现在元素的标签身上
- 获取属性
- 语法:
元素.attr(要获取的属性名)
- 返回值:该属性名对应的属性值
- 语法:
- 设置属性
- 语法:
元素.attr(属性名, 属性值)
- 语法:
2. removeAttr()
- 对元素属性进行删除操作
- 语法:
元素.removeAttr(要删除的属性名)
3. prop()
- 当 prop 设置元素的原生属性时,会直接响应在元素标签身上
- 当 prop 设置元素的自定义属性时,不会直接响应在元素标签身上,会响应在元素对象身上
- prop 方法不能获取元素标签身上的自定义属性,只能获取到 prop 方法自己设置的自定义属性
- 获取属性
- 语法:
元素.prop(要获取的属性名)
- 返回值:该属性名对应的属性值
- 语法:
- 设置属性
- 语法:
元素.prop(属性名, 属性值)
- 语法:
4. removeProp()
- 用来删除元素属性
- 不能删除原生属性,只能删除 prop 方法设置的自定义属性
- 语法:
元素.removeProp(要删除的属性名)
P75_jQuery-获取元素尺寸
1. width() 和 height()
- 获取元素内容区域的尺寸
元素.width()
和元素.height()
2. innerWidth() 和 innerHeight()
- 内容 + padding
元素.innerWidth()
和元素.innerHeight()
3. outerWidth() 和 outerHeight()
- 内容 + padding + border
元素.outerWidth()
和元素.outerHeight()
4. outerWidth(true) 和 outerHeight(true)
-
内容 + padding + border + 设置的margin
-
元素.outerWidth(true)
和元素.outerHeight(true)
-
无论元素是否隐藏,都能获取到该元素的值
-
无论盒子模型是什么状态,拿到的区域不变(值可能会改变)
P76_jQuery-获取元素偏移量
1. offset()
- 获取元素相对于页面左上角的坐标位置
- 返回值是一个对象数据类型:{ top: yyy, left: xxx }
元素.offset()
2. position()
- 获取的就是元素的定位位置
- 返回值是一个对象数据类型:{ top: yyy, left: xxx }
元素.position()
P77_jQuery-事件绑定
1. on() 方法绑定事件
- 基础绑定事件
- 语法:
元素集合.on('事件类型', 事件处理函数)
- 语法:
- 事件委托绑定事件
- 语法:
元素集合.on('事件类型', 选择器, 事件处理函数)
- 把 “选择器” 的事件委托给了 “元素集合” 来绑定
- 语法:
- 批量绑定事件
- 语法:
元素集合.on( 事件类型1: 处理函数1, 事件类型2: 处理函数2, …… )
- 此时不能进行事件委托
- 语法:
2. one() 方法绑定事件
- 与 on 方法绑定事件方法相同
- one 方法绑定的事件只能触发一次
- 基础绑定事件
- 语法:
元素集合.one('事件类型', 事件处理函数)
- 语法:
- 事件委托绑定事件
- 语法:
元素集合.one('事件类型', 选择器, 事件处理函数)
- 把 “选择器” 的事件委托给了 “元素集合” 来绑定
- 语法:
- 批量绑定事件
- 语法:
元素集合.one( 事件类型1: 处理函数1, 事件类型2: 处理函数2, …… )
- 此时不能进行事件委托
- 语法:
3. hover() 方法绑定事件
- 语法:
元素集合.hover(移入时触发的函数, 移出时触发的函数)
- 只传递一个函数时,会在移入和移出时都触发
4. 常用事件处理函数
- jQuery 将我们常用的一些事件单独做成了事件函数,可以通过调用这些函数来达到绑定事件的效果
- 常见事件函数:click()、mouseover()、mouseout()、change()……
- 语法:
元素集合.事件函数(处理函数)
P78_jQuery-事件解绑和触发
1. off() 事件解绑
- 解绑全部的事件处理函数
- 语法:
元素集合.off(事件类型)
- 会把 “元素” 的 “事件” 对应的所有事件处理函数全部解绑
- 语法:
- 解绑指定的事件处理函数
- 语法:
元素集合.off(事件类型, 要解绑的事件处理函数)
- 只会把 “元素” 的 “事件” 对应的 “要解绑的事件处理函数” 解绑
- 语法:
2. trigger() 事件触发
- 使用代码的方式来触发事件
- 语法:
元素集合.trigger(事件类型)
P79_jQuery-基本动画函数
1. show() 显示
- 语法:
元素集合.show(运动时间, 运动曲线, 运动结束的回调函数)
2. hide() 隐藏
- 语法:
元素集合.hide(运动时间, 运动曲线, 运动结束的回调函数)
3. toggle() 切换
- 语法:
元素集合.toggle(运动时间, 运动曲线, 运动结束的回调函数)
- 如果本身是显示的,就隐藏;如果本身是隐藏的,就显示
P80_jQuery-折叠动画函数
1. slideDown()
- 语法:
元素集合.slideDown(运动时间, 运动曲线, 运动结束的回调函数)
2. slideUp()
- 语法:
元素集合.slideUp(运动时间, 运动曲线, 运动结束的回调函数)
3. slideToggle()
- 语法:
元素集合.slideToggle(运动时间, 运动曲线, 运动结束的回调函数)
- 如果本身是显示的,就隐藏;如果本身是隐藏的,就显示
P81_jQuery-渐隐渐显动画函数
1. fadeIn()
- 语法:
元素集合.fadeIn(运动时间, 运动曲线, 运动结束的回调函数)
2. fadeOut()
- 语法:
元素集合.fadeOut(运动时间, 运动曲线, 运动结束的回调函数)
3. fadeToggle()
- 语法:
元素集合.fadeToggle(运动时间, 运动曲线, 运动结束的回调函数)
- 如果本身是显示的,就隐藏;如果本身是隐藏的,就显示
4. fadeTo()
- 语法:
元素集合.fadeTo(运动时间, 指定的透明度, 运动曲线, 运动结束的回调函数)
P82_jQuery-综合动画函数
-
语法:
元素集合.animate()
- 第一个参数:要运动的样式(自己DIY),以一个对象数据类型传递
- 第二个参数:运动时间
- 第三个参数:运动曲线
- 第四个参数:运动结束的回调函数
-
关于 ”颜色“ 相关的样式是不能运动的
-
关于 “transform” 相关的样式是不能运动的
P83_jQuery-结束动画函数
1. stop()
- 当任何一个元素执行了 stop 方法以后,会立刻结束当前的所有运动,停留在目前的运动位置
- 一般对于结束动画的使用,都是在运动开始之前
例:元素集合.stop().toggle(2000)
每一次触发的时候都会把之前的动画停止下来,只执行本次最新的动画
2. finish()
- 当任何一个元素执行了 finish 方法以后,会立刻结束当前的所有运动,直接去到动画的结束位置
- 一般对于结束动画的使用,都是在运动开始之前
例:元素集合.finish().toggle(2000)
每一次触发的时候都会把之前的动画瞬间完成,只执行本次最新的动画
P84_jQuery-Ajax请求
- 语法:$.ajax({ 本次发送 ajax 的配置项 })
- 配置项:
- url:必填,表示请求地址
- method:选填,默认是 GET,表示请求方式
- data:选填,默认是 ‘空字符串’,表示携带给后端的参数(以对象的形式传递)
- async:选填,默认是 true,表示是否异步
- success:选填,表示请求成功的回调函数
- error:选填,表示请求失败的回调函数
补充
P109_正则表达式
字面量写法
var reg = /abc/
内置构造函数
var reg = new RegExp("abc")
// 测试校验对象是否符合正则表达式 reg 的要求
reg.test(字符串)
P110_元字符-基本元字符
\d
包含一个数字
\D
包含一个非数字
\s
包含一个空白内容(空格、缩进、换行)
\S
包含一个非空白内容
\w
包含一个字母、数字、下划线
\W
包含一个非字母且非数字且非下划线
.
包含一个任意内容(除了换行)
\
转义字符
P111_元字符-边界符
- 规定 “开头/结尾” 必须是什么
开头:^基本元字符
结尾:基本元字符$
P112_元字符-限定符
基本元字符*
包含0~多个基本元字符
基本元字符+
包含1~多个基本元字符
基本元字符?
包含0~1个基本元字符
基本元字符{n}
包含连续n个基本元字符
基本元字符{n,}
包含连续n个及以上的基本元字符
基本元字符{n,m}
包含连续n~m个基本元字符
tip:
- “{ }” 只能修饰它前面紧挨的基本元字符
P113_元字符-特殊符号
(基本元字符)
把其内部的基本元字符看做一个整体
基本元字符1|基本元字符2
包含 “基本元字符1” 或 “基本元字符2”(会把它左边看成一个整体,右边看成一个整体)
[基本元字符1基本元字符2……]
包含其中的一位
基本元字符1-基本元字符2
包含 “基本元字符1” 到 “基本元字符2” 中的一位
[^基本元字符……]
取反(包含非基本元字符中的一位)
P114_正则表达式-捕获exec
reg.exec(字符串)
// datastr = "from 2023-1-1 to 2023-10-5"
var reg = /(\d{4})-(\d{1,2})-(\d{1,2})/g
reg.exec()
获取满足正则表达式要求的内容片段,返回一个数组/ /
只能匹配到符合要求的第一段字符串(懒惰)/ /g
变成全局的,可以匹配到符合要求的所有字符串- 加 “()” 除了整体捕获外还会单独捕获
// 忽略大小写
var reg = /基本元字符/i
P115_正则表达式的特性
懒惰
- 使用全局标识符 “g”
贪婪
{m,n}
有匹配的就会选择捕获n次而不是m次
{m,n}?
非贪婪模式,有匹配的就会选择捕获m次而不是n次
- “?” 可配合限定符使用
P116_正则与字符串方法
字符串.replace(正则, "")
字符串.search(正则)
(“g” 没用)字符串.match(正则)
(返回一个数组)
P155_cookie
tips:
实现记住用户名、密码自动登录
- localStorage + token
- cookie + session
cookie 本地存储
P156-P157_jsonp
-
同源策略:同域名、同端口号、同协议
不符合同源策略的,浏览器为了安全会阻止请求 -
解决跨域问题:
- cors:由后端设置 Access-Control-Allow-Origin: *
- jsonp
-
jsonp 原理:动态创建 script 标签,src 属性指向没有跨域限制。
src 指向一个接口,接口返回的格式一定是 “***()” 函数表达式
mybtn.onclick = function() {
var oscript = document.createElement("script")
oscript.src = "支持 jsonp 格式的接口地址"
document.body.appendChild(oscript)
// 做完所需的操作后删除之前创建的节点
oscript.onload = function() {
oscript.remove()
}
}
- 注意:
- 后端接口形式必须是 “**()”
- 用完之后记得删除
- 缺点:只能 get 请求,不能 post、put、delete