简单了解对象
- 什么是对象
- 首先排除男女朋友, 我们这是正经编程
- 对象是一个 复杂数据类型, 也叫做 引用数据类型
- 虽然我们说是复杂类型, 但是也没有很复杂, 只不过是存储了一些基本数据类型的集合
var obj = {
num: 100,
str: 'hello',
boo: true
}
- 这里的 {} 和函数中的 {} 不一样, 函数内部书写代码, 对象里面是书写数据的
- 对象就是一个键值对的集合
- 什么是键值对?
- 对象 obj 中, num 是键, 100 是值
- 对象 obj 中, str 是键, 'hello' 是值
- 对象 obj 中, boo 是键, true 是值
- 其实就是我们准备一个房子, 把我们想要的数据放进去, 然后把房子的地址给到变量名, 当我们需要某一个数据的时候, 就可以根据变量名里面存储的地址找到对应的房子, 然后去房子里面找到对应的数据
- 什么是键值对?
创建对象
- 字面量方式创建对象
- 语法:
var obj = {} var obj1 = {键值对, 键值对}
- 语法:
- 内置构造函数创建
- 语法:
var obj = new Object()
- 语法:
- 对象内对于 键(key) 的要求
- 推荐使用符合变量命名规则和规范的名字
- 可以使用纯数字当作 键名
- 这种情况下该属性会排列在最前面
- 可以使用任何特殊符号
- 使用特殊符号的时候,在书写时需要被引号包裹
对象数据类型的操作(增删改查)两种语法
- 点语法
var obj = {} obj.name = 'qianfeng' // 增 obj.name = 'qianfeng123' // 改 console.log(obj.name) // 查 delete obj.name // 删 - 中括号语法(数组语法)
var obj = {} obj['name'] = 'qianfeng' // 增 obj['name'] = 'qianfeng123123' // 改 console.log(obj['name']) // 查 delete obj['name'] // 删 - 两者的差异
- 符合变量命名规范与规则的情况,两者并无差异
- 操作不符合变量命名规范与规则的名称时,比如纯数字或者带有特殊符号的,就只能用中括号语法
- 涉及变量相关的时候,只能使用中括号语法
for in 循环遍历对象
for (var k in obj) {
console.log('我执行了', k, obj[k])
}
数组数据类型
- 什么是数组
- 数组字面意思就是存放数字的一个组合, 但这么说太过于片面, 更完善的说法应该是
数组是存放一些数据的集合 - 简单来说我们把数据放到一个盒子中, 这个盒子就是数组, 注意数字内的数据是有顺序的
- 数组字面意思就是存放数字的一个组合, 但这么说太过于片面, 更完善的说法应该是
var arr = [1, 2, 3, 'qwe', 'abc', true, false, undefined, null]
// 我们把一堆数据存放到一个盒子中, 这就叫做数组 对应我们上述的 数组是存放一些数据的集合
创建数组数据类型
- 使用字面量的方式创建数组
// 创建一个空数组
var arr = [];
// 创建一个有内容的数组
var arr1 = [1, 2, 3]
- 内置构造函数创建数组
// 创建一个空数组
var arr = new Array()
// 创建一个有长度的数组
var arr1 = new Array(10)
// 创建一个有内容的数组
var arr2 = nee Array(1, 2, 3)
数组的 length 属性
length 就是长度的意思, 代表数组内有多少个成员(数据)
var arr = [1, 2, 3]
console.log(arr.length) // 3
var arr1 = [4, 5]
console.log(arr1.length) // 2
数组的 索引 概念
- 索引也叫做下标, 就是指一个数据在这个数组内排列在第几个位置上
- 注意: 在所有的语言中, 索引(下标)都是从0开始的
var arr = ['hello', 'world']
// 在这个数组中, 第一个数据(元素)是 'hello', 那么它的下标就是 0, 后续的 'world', 下标为1
// 想要获取数组中某一个位置上的数据(元素), 可以直接 数组名[下标]
console.log(arr[0], arr[1])
for 循环遍历数组
遍历数组就是想办法拿到数组的每一个元素, 通常我们可以通过下标获取到元素的某一项, 所以我们只需要想办法拿到数组的所有下标即可
var arr = [1, 2, 3, 'qwe', 'abc', true, false, undefined, null]
for (var i = 0; i < arr.length; i++) {
console.log(arr[i])
}
数组基本操作案例
- 冒泡排序
var arr = [9, 6, 3, 1, 4, 7, 8, 2, 5];
console.log('原始数组: ', arr)
for (var i = 0; i < arr.length - 1; i++) {
for (var j = 0; j < arr.length - 1 - i; j++) {
if (arr[j] > arr[j + 1]) {
var temp = arr[j]
arr[j] = arr[j + 1]
arr[j + 1] = temp
}
}
}
console.log('交换后的数组: ', arr)
- 选择排序
var arr = [9, 6, 3, 1, 4, 7, 8, 2, 5];
console.log('原始数组: ', arr)
for (var j = 0; j < arr.length; j++) {
// 1. 假定数组中的第 0 个是最小数字的索引
var minIndex = j
// 2. 遍历数组找到数组中最小的哪一项的下标将其替换之前记录的索引
for (var i = j; i < arr.length; i++) {
if (arr[i] < arr[minIndex]) {
minIndex = i
}
}
// 3. 遍历结束, 找到最小的索引, 将两个位置的数据对换
var temp = arr[j]
arr[j] = arr[minIndex]
arr[minIndex] = temp
}
console.log('排序结束后: ', arr)
数组常用方法
- push; pop; unshift; shift;
- push
- 语法:
数组名.push(数据) - 作用: 向数组末尾添加数据
- 返回值: 追加数据后, 数组最新的长度
- 语法:
- pop
- 语法:
数组名.pop() - 作用: 删除数组最后一条数据
- 返回值: 被删除的数据
- 语法:
- unshift
- 语法:
数组名.unshift(数据) - 作用: 向数组开头添加数据
- 返回值: 添加数据后, 数组最新的长度
- 语法:
- shift
- 语法:
数组名.shift() - 作用: 删除数组第一条数据
- 返回值: 被删除的数据
- 语法:
- push
- reverse; sort; splice; slice; concat; join; indexOf; lastIndexOf
-
reverse
- 语法:
数组名.reverse() - 作用: 反转数组
- 返回值: 反转后的数组
- 语法:
-
sort
- 语法:
数组名.sort(); 数组名.sort((a, b) => a - b); 数组名.sort((a, b) => b - a)- 不传参数: 会将数据转换为字符串后, 一位一位的对比
- 回调函数内进行 a - b, 那么会按照数字大小升序排序
- 回调函数内进行 b - a, 那么会按照数字大小降序排序
- 作用: 根据参数对数组数据实现排序
- 返回值: 排序后的数组
- 语法:
-
splice
- 语法:
数组名.splice(开始索引, 多少个); 数组名.splice(开始索引, 多少个, 插入数据1, 插入数据2, ...) - 作用: 截取数组部分内容, 并选择性插入内容
- 返回值: 截取出来的部分内容组成的新数组
- 语法:
-
slice
- 语法:
数组名.slice(开始索引, 结束索引) - 参数:
- 包前不包后, 包含开始索引位置数据, 不包含结束索引位置数据
- 不写开始索引, 默认是 0, 结束索引不写, 默认是 length
- 可以填写负整数, 表示倒数第几个, 其实就是 length + 负整数
- 作用: 截取数组部分内容
- 返回值: 截取出来的部分内容组成的新数组
- 与 splice 的差异
- 参数含义不同
- splice 会改变原数组, slice 不会
- 语法:
-
concat
- 语法:
原始数组.concat(数组1, 数组2, 数据, ...) - 作用: 进行数据拼接, 把参数的所有数组或数据, 拼接在原始数组身上
- 返回值: 拼接好的数组
- 语法:
-
join
- 语法:
数组名.join('连接符') - 作用: 使用连接符, 把数组内的每一个数据连接成一个字符串(不写的话默认使用 逗号)
- 返回值: 连接好的字符串
- 语法:
-
indexOf
- 语法:
数组名.indexOf(要检查的数据); 数组名.indexOf(要检查的数据, 开始索引) - 作用: 从前到后检查该数据第一次在该数组内出现的索引位置
- 返回值: 如果在数组内找到了该数据, 那么会返回该数据第一次出现的索引位置, 没找到返回 -1
- 语法:
-
lastIndexOf
- 语法:
数组名.lastIndexOf(要检查的数据); 数组名.lastIndexOf(要检查的数据, 开始索引) - 作用: 从后向前检索该数据第一次在该数组内出现的位置
- 返回值: 如果在数组内找到了该数据, 那么会返回该数据第一次出现的索引位置, 没找到返回 -1
- 语法:
-
- forEach; map; filter; find; findIndex; every; some; reduce;
- forEach
- 语法:
数组.forEach(function (item, index, origin) {})- item: 数组的每一项
- index: 数组的每一项对应的下标
- origin: 原始数组
- 作用: 遍历数组
- 返回值: 没有(undefined)
- 注意: 手写 return 也没用
- 语法:
- map
- 语法:
数组.map(function (item, index, origin) {})- item: 数组的每一项
- index: 数组的每一项对应的下标
- origin: 原始数组
- 作用: 映射数组
- 返回值: 和数组长度一样的数组, 只不过内部数据经过映射加工
- 注意: 映射条件以 return 的形式书写
- 语法:
- filter
- 语法:
数组.filter(function (item, index, origin) {})- item: 数组的每一项
- index: 数组的每一项对应的下标
- origin: 原始数组
- 作用: 过滤数组
- 返回值: 返回一个新数组, 内部存储的是原始数组内过滤出来的部分数据
- 注意: 过滤条件以 return 的形式书写
- 语法:
- find
- 语法:
数组.find(function (item, index, origin) {})- item: 数组的每一项
- index: 数组的每一项对应的下标
- origin: 原始数组
- 作用: 在数组内查找满足条件的第一项
- 返回值: 找到的数据
- 注意: 查找条件以 return 的形式书写
- 语法:
- findIndex
- 语法:
数组.findIndex(function (item, index, origin) {})- item: 数组的每一项
- index: 数组的每一项对应的下标
- origin: 原始数组
- 作用: 在数组内查找满足条件的第一项的下标
- 返回值: 找到的数据
- 注意: 查找条件以 return 的形式书写
- 语法:
- every
- 语法:
数组.every(function (item, index, origin) {})- item: 数组的每一项
- index: 数组的每一项对应的下标
- origin: 原始数组
- 作用: 判断数组内是否每一个都满足条件
- 返回值: 一个布尔值
- 注意: 判断条件以 return 的形式书写
- 语法:
- some
- 语法:
数组.find(function (item, index, origin) {})- item: 数组的每一项
- index: 数组的每一项对应的下标
- origin: 原始数组
- 作用: 判断数组内是否有一个符合条件的
- 返回值: 一个布尔值
- 注意: 判断条件以 return 的形式书写
- 语法:
- reduce
- 语法:
数组.reduce(function (prev, item, index, origin) {}, init)- prev: 表示初始值或者上一次的运算结果
- item: 表示数组的每一项
- index: 表示数组的每一项索引
- origin: 原始数组
- 作用: 用来实现叠加效果
- 返回值: 最终叠加结果
- 注意:
- 叠加条件以 return 的形式书写
- prev 的值, 如果你传递了 init, 就是 init 的值, 如果没有传递 init, 那么就是
数组[0]的值 - 如果传递了 init, 循环执行 length 次, 如果没有传递 init, 循环执行 length - 1 次
- 语法:
- forEach
数据类型之间的区别
存储的区别
- 基本数据类型存储在 栈内存中, 比如:
string; number; undefined; null; boolean; - 复杂数据类型(引用数据类型)
- 将数据本体存放在 堆内存中, 比如对象或者数组, 然后将指向该堆内存的地址, 存放在数组名或者对象名中
- 数组名或者对象名存放在栈内存中
赋值的区别
- 基本数据类型:赋值以后,两个变量没有关系了, 相当于将我自己的某一个东西, 复制一份给到你, 然后你的是你的, 我的是我的
- 复杂数据类型:赋值以后,两个变量操作一个存储空间, 相当于我将我房间的钥匙复制给你一份, 你可以自由进出该房间或者对这个房间的布局做一些调整, 我也可以自由进出该房间并且也可以对这个房间的布局做调整
- 两种数据类型存储的区别
- 基础数据类型直接存储在 栈内存中
- 复杂数据类型会将数据本体存在堆内存中,变量名存储在堆内存中,变量名内部存储着指向堆内存的地址
比较的区别
- 基本数据类型是
值的比较
var a = 1
var b = 2
console.log(a == b) // false, 因为两个变量的值是 1 和 2, 所以对比结果为 false
- 复杂数据类型是
存储地址的比较
var obj1 = {a: 1}
var obj2 = obj1
var obj3 = {a: 1}
console.log(obj1 === obj2) // 两个变量的存储地址相同, 所以为true
console.log(obj1 === obj3) // 两个变量的存储地址不相同, 所以为false
传参的区别
- 基本数据类型: 将值拷贝一份传递给形参, 在函数内修改不会影响外界
- 复杂数据类型: 将存储地址赋值给形参, 在函数内修改会影响外界
-
数组去重案例
严格模式(了解)
- JS 是一个相对不是很严谨的语言, 在开发的时候一些代码也不是很严格, 严格模式就是对开发的时候写的代码做了一些要求
如何开启严格模式
- 要开启严格模式, 直接在代码最开始的位置写上字符串 'use strict'
严格模式的规则
- 声明变量必须有
var关键字 - 函数的形参不可以重复
字符串
创建字符串(了解)
- 字面量
- 构造函数创建
var str1 = 'hello'
var str2 = new String('hello')
ASCII 字符集(了解)
- 计算机只能存储二进制数据
0101010 - 我们的 大写字母; 小写字母; 符号 之类的内容也是由二进制数字组成的
- 或者说 我们的字母符号这些东西写都有一个对应的编号, 然后计算机存储的时候是存储的这些编号,不过我们看到的时候, 是通过这些编号解析成我们看到的内容
- 所以我们计算机存储的字母符号之类的并不是存储了这个字母, 而是存储了这个字母对应的编号, 然后给我们看到的时候是通过这个编号找到了对应的字母给我们看
unicode 编码
- ASCII 只有 128 个字符的编码结构, 这是因为他出现的比较早, 而且是美国发明的, 所以在早期这些内容完全足够
- 但是这个世界要存储的东西就不够, 比如我们的汉字, 所以就出现了
unicode编码, 也叫(万国码, 统一码) - unicode 和 ASCII 一样的对照表, 只不过存的东西特别多, 基本包含了世界上大部分国家的文字, 所以我们的文字在存储的时候 都是按照 unicode 编码转换成了数字进行存储
- 我们的 UTF-8 就是一种 8 位的 unicode 字符集
一些操作字符串的常用方法
-
charAt/charCodeAt/toLowerCase/toUpperCase- charAt
- 语法:
变量.charAt(索引) - 作用: 找到字符串中指定索引位置的内容然后返回
- 返回值: 字符串中指定索引位置的内容
- 语法:
- charCodeAt
- 语法:
变量.charCodeAt(索引) - 作用: 找到字符串中指定索引位置的 unicode 编码然后返回
- 返回值: 字符串中指定索引位置的 unicode 编码
- 语法:
- toLowerCase
- 语法:
变量.toLowerCase() - 作用: 将字符串转换为小写
- 返回值: 转小写后的字符串
- 语法:
- toUpperCase
- 语法:
变量.toUpperCase() - 作用: 将字符串转换为大写
- 返回值: 转大写后的字符串
- 语法:
- charAt
-
substr/substring/slice- substr
- 语法:
变量.substr(开始索引, 截取多少个) - 作用: 截取字符串
- 返回值: 截取出来的字符串
- 语法:
- substring
- 语法:
变量.substr(开始索引, 结束索引) - 作用: 截取字符串
- 返回值: 截取出来的字符串
- 注意: 参数包前不包后
- 语法:
- slice
- 语法:
变量.slice(开始索引, 结束索引) - 作用: 截取字符串
- 返回值: 截取出来的字符串
- 注意: 参数包前不包后
- 语法:
- substr
-
concat/indexOf/lastIndexOf/split- concat
- 语法:
变量.concat(字符串1, 字符串2) - 作用: 拼接字符串
- 返回值: 拼接好的字符串
- 语法:
- indexOf
- 语法:
变量.indexOf(查找的字符, 开始索引) - 作用: 查找当前字符串中是否包含指定字符
- 返回值: 找到返回第一次出现的首字母索引位置, 找不到就返回 -1
- 语法:
- lastIndexOf
- 语法:
变量.lastIndexOf(查找的字符, 开始索引) - 作用: 查找当前字符串中是否包含指定字符 (从后往前)
- 返回值: 找到返回第一次出现的首字母索引位置, 找不到就返回 -1
- 语法:
- split
- 语法:
变量.split('分隔符') - 作用: 把字符串按照分隔符分开为几段内容
- 返回值: 将字符串分割后以数组的形式分隔
- 语法:
- concat
-
trim/trimStart/trimEnd- trim
- 语法:
变量.trim() - 作用: 把字符串左右空格去除
- 返回值: 去除空格后的字符串
- 语法:
- trimStart(trimLeft)
- 语法:
变量.trimStart() - 语法:
变量.trimLeft() - 作用: 把字符串左边空格去除
- 返回值: 去除左边空格后的字符串
- 语法:
- trimEnd(trimRight)
- 语法:
变量.trimEnd() - 语法:
变量.trimRight() - 作用: 把字符串右边空格去除
- 返回值: 去除右边空格后的字符串
- 语法:
- trim
-
includes/startsWith/endsWith/repalce- includes
- 语法: 字符串.includes(字符串片段)
- 作用: 该字符串中是否包含该字符串片段
- 返回值: 一个布尔值
- true: 包含
- false: 不包含
- startsWith
- 语法: 字符串.startsWith(字符串片段)
- 作用: 判断该字符串是否以该字符串片段开头
- 返回值: 一个布尔值
- true: 是开头
- false: 不是开头
- endsWith
- 语法: 字符串.endsWith(字符串片段)
- 作用: 判断该字符串是否以该字符串片段结尾
- 返回值: 一个布尔值
- true: 是结尾
- false: 不是结尾
- includes
其他格式字符串
- 查询字符串
- JSON 字符串
-
BOM 和 DOM
- 从今天开始 我们就开始学习使用 JS 去操作 浏览器 和 页面中的 HTML 元素
BOM 的概念和常用 API
- BOM(Browser Object Model): 浏览器对象模型
- 其实就是操作浏览器的一些能力
- 我们可以操作哪些内容?
- 获取浏览器的相关信息(窗口大小)
- 操作浏览器进行页面的跳转
- 获取当前浏览器地址栏的信息
- 操作浏览器的滚动条
- 浏览器的信息(浏览器的版本)
- 让浏览器出现一个弹出框(alert/prompt/confirm)
- ...
- BOM 的核心就是 window 对象
- window 是浏览器内置的一个对象, 里面包含着操作浏览器的方法
获取浏览器窗口的尺寸
- innerHeight 和 innerWidth
- 作用: 获取浏览器窗口的高度和宽度(包含滚动条)
- 语法:
window.innerHeight; window.innerWidth
浏览器的弹出层
- confirm
- 有一个询问信息和两个按钮
- 点击确定返回 true
- 点击取消返回 false
- 有一个询问信息和两个按钮
- alert
- prompt
浏览器的地址信息
- 在 window 中 有一个对象叫做 location, 他是专门用来存储浏览器地址栏内的信息
location.href
- location.href 专门存储浏览器地址栏内 url 地址的信息
- 语法:
var url = window.location.href - 我们也可以给这个属性赋值, 这样就会跳转到我们复制的地址了
window.location.href = 'https://www.baidu.com'
location.reload
- location.reload 会重新加载页面, 相当于刷新
- 注意: 不要写在全局内, 否则浏览器会一直刷新
window.location.reload()
浏览器的历史记录
- window 中有一个对象叫做 history 他专门用来存储历史记录信息
history.back
- history.back 用来回退历史纪录的, 就是回到前一个页面, 相当于浏览器左上角的 ← 按钮
- 注意: 我们需要有上一条记录, 不然就一直在这个页面 不会回退
window.history.back()
history.forward
- history.forward 是去到下一个历史记录里面, 也就是去到下一个页面, 就相当于 浏览器左上角的 → 按钮
- 注意: 前提是我们之前有过回退操作, 不然的话我们现在就是在最后一个页面, 没有下一个
window.history.forward()
浏览器的版本信息(了解)
- window 中的 navigator 可以获取到浏览器的信息
浏览器的 onload 事件
- 该事件会在页面所有资源加载完毕后执行
window.onload = function () {
console.log('页面已经加载完毕')
}
- 在浏览器中, 把 JS 写在 head 中, JS 在加载时 DOM 还没加载完, 可能会导致获取 DOM 时出现问题, 但是如果把代码放在 onload 事件中, 则不会出现问题
- 如果把 JS 写在 body 底部, 则写不写 onload 都一样
浏览器的 onscroll 事件
- 当浏览器的滚动条滚动时会触发该事件, 或者鼠标滚轮滚动时触发
window.onscroll = function () {
console.log('浏览器滚动了')
}
浏览器的滚动距离
- 浏览器的内容可以滚动, 那么我们就可以获取到浏览器滚动的距离
- 但是需要思考一个问题
- 浏览器真的滚动了吗?
- 其实浏览器没有滚动, 一直在那里, 滚动的是浏览器的页面
- 所以说:
其实浏览器没动, 只不过页面向上走了
- 所以这个已经不能单纯的算是浏览器的内容了, 而是我们页面的内容
- 所以不再是使用 window 对象了, 而是使用 document 对象
scrollTop
- 获取的事页面向上滚动的距离
- 两种方式
document.body.scrollTopdocument.documentElement.scrollTop
- 两种方式
window.onscroll = function () {
console.log(document.body.scrollTop)
console.log(document.documentElement.scrollTop)
}
- 区别
- IE 浏览器(了解)
- 没有
DOCTYPE声明的时候, 用这两个都行 - 有
DOCTYPE声明的时候, 只能用document.documentElement.scrollTop
- 没有
- Chorme 和 FireFox
- 没有
DOCTYPE声明的时候, 用document.body.scrollTop - 有
DOCTYPE声明的时候, 用document.documentElement.scrollTop
- 没有
- Safari
- 两个都不用, 使用一个单独的方法
window.pageYOffset
- 两个都不用, 使用一个单独的方法
- IE 浏览器(了解)
scrollLeft
- 获取页面向左滚动的距离
document.body.scrollLeftdocument.documentElement.scrollLeft
window.onscroll = function () {
console.log(document.body.scrollLeft)
console.log(document.documentElement.scrollLeft)
}
- 区别
- 参考 scrollTop
浏览器的本地存储
- localStorage
- 浏览器本地存储, 持久存储, 一旦存储永久存在
- 只能存基础数据类型(一般为字符串), 不能存储复杂数据类型
- 可以跨页面通讯
// 增 window.localStorage.setItem(key, value) // 删 window.localStorage.removeItem(key) // 清除 window.localStorage.clear() /** * 查 * 有 ---> 返回对应的 value * 没有 ---> 返回 Null */ window.localStorage.getItem(key) - sessionStorage
- 浏览器的本地存储, 临时存储, 关闭浏览器以后, 存储内容自动消失
- 想要跨页面通讯, 必须是从本页面跳转的才可以
// 增 window.sessionStorage.setItem(key, value) // 删 window.sessionStorage.removeItem(key) // 清除 window.sessionStorage.clear() /** * 查 * 有 ---> 返回对应的 value * 没有 ---> 返回 Null */ window.sessionStorage.getItem(key) - cookie
- 只能存储字符串, 有固定格式
- key=value; key2=value2; key3=value3
- 存储大小有限制
- 4KB左右
- 存储有时效性
- 默认是会话级别时效, 但是可以手动设置过期时间
- 操作必须依赖服务器
- 本地打开的也页面时不能操作 cookie
- 要求页面必须在服务器打开
- 跟随前后端请求自动携带
- 只要 cookie 空间中有内容的时候
- 会在该页面和后端交互的过程中自动携带
- 前后端操作
- 前端可以使用 JS 来操作
- 任意一个后端语言都可以操作
- 存储依赖域名
- 哪一个域名存储, 那一个域名使用
- 不能跨域名通讯
- 只能存储字符串, 有固定格式
// 设置 cookie
document.cookie = 'a=100'
// 设置一条带有过期时间的 cookie
var time = new Date()
document.cookie = 'a=100;expires=' + time
// 设置一条 30s 以后过期的 cookie
var time = new Date()
time.setTime(time.getTime() - 1000 * 60 * 60 * 8 + 1000 * 30)
document.cookie = 'a=100;expires=' + time
// 获取 cookie
document.cookie
本地存储的区别 (面试必问)
- 出现时间
- cookie: 有 JS 就有了
- storage: H5 出现后才有
- 存储大小
- cookie: 4k 左右
- storage: 20MB 左右
- 前后端交互
- cookie: 会随着当前页面的请求自动携带
- storage: 不会跟随请求自动携带
- 前后端操作
- cookie: 前后端语言都可以操作
- storage: 只能前端 JS 操作
- 过期时间
- cookie: 默认是会话, 可以手动设置过期时间
- storage: 不能手动设置
- localStorage 和 sessionStorage 的区别
- 过期时间
- localStorage: 永久存储, 除非手动清除
- sessionStorage: 临时存储
- 跨页面通讯
- localStorage: 直接跨页面通讯
- sessionStorage: 只能是当前窗口跳转的页面才可以通讯
- 共同点
- 只能存储字符串, 不能存储复杂数据类型
- 存储其他数据类型的时候, 获取回来的也是 字符串类型
- 过期时间
DOM 的基本概念及操作
- DOM(Document Object Model): 文档对象模型
- 其实就是操作 html 中的标签的一些能力
- 我们可以操作哪些内容
- 获取一个元素
- 移除一个元素
- 创建一个元素
- 向页面中添加一个元素
- 给元素绑定一些事件
- 获取元素的属性
- 给元素添加一些 css 样式
- ...
- DOM 的核心对象就是 document 对象
- document 对象是浏览器内置的一个对象, 里面存储这专门用来操作元素的各种方法
- DOM: 页面中的标签, 我们通过 JS 获取到以后, 就把这个对象叫做 DOM 对象
获取非常规元素
- document.documentElement
- document.head
- document.body
// 1. html
var htmlEle = document.documentElement
console.log(htmlEle)
// 2. head
var headEle = document.head
console.log(headEle)
// 3. body
var bodyEle = document.body
console.log(bodyEle)
获取常规元素
- 通过 JS 代码来获取页面中的标签, 获取后我们就可以操作这些标签
getElementById
- getElementById 是通过标签的 ID 名称来获取标签的
- 因为页面中的 ID 是唯一的, 所以获取到的就是一个元素
<body>
<div id="box"></div>
<script>
var box = document.getElementById('box')
console.log(box) // 页面中 ID 为 box 的标签
</script>
</body>
getElementsByClassName
- getElementsByClassName 是通过标签的 class 名称来获取标签的
- 因为页面中可能会有多个元素的 class 名称一样, 所以获取到的是一组元素
- 哪怕页面中只有一个, 获取到的也是一组元素, 只不过这一组元素只有一个 DOM 元素
<body>
<div calss="box"></div>
<script>
var box = document.getElementsByClassName('box')
console.log(box) // [<div></div>]
console.log(box[0]) // <div></div>
</script>
</body>
- 注意!!! getElementsByClassName 是一组长得很像数组的数据解构, 但它不是数组, 我们叫这种数据结构为:
伪数组 - 这一组数据也是按照索引排列的, 所以我们想要准确的拿到这个 div, 需要用索引来获取
getElementsByTagName
- getElementsByTagName 是通过标签的 标签名称 来获取标签饿
- 因为页面中可能有多个元素的标签名称一样, 所以获取到的是一组元素
- 哪怕只有一个这个标签名, 获取到的也是一组数据, 只不过一组数据中只有一个 DOM 元素
<body>
<div></div>
<script>
var box = document.getElementsByTagName('div')
console.log(box) // [<div></div>]
console.log(box[0]) // <div></div>
</script>
</body>
- 和 getElementsByClassName 一样, 获取到的是一个长得很像数组的元素
- 必须要用索引才能准确地到 DOM 元素
querySelector
- querySelector 是按照选择器的方式来获取元素
- 也就是说, 按照我们写 css 的时候的选择器来获取
- 这个方法只能获取到一个元素, 并且是页面中第一个满足条件的元素
console.log(document.querySelector('div')) // 获取页面中第一个 div 元素
console.log(document.querySelector('.box')) // 获取页面中第一个 有 box 类名的元素
console.log(document.querySelector('#box')) // 获取页面中第一个 id 名为 box 的元素
querySelectorAll
- querySelectorAll 是按照选择器的方式来获取元素
- 这个方法能获取到所有满足条件的元素, 以一个伪数组的形式返回
console.log(document.querySelectAll('div')) // 获取页面中的所有的 div 元素
console.log(document.querySelectAll('.div')) // 获取页面中的所有的 类名为 box 的元素
- 获取道德是一组数据, 也是需要用索引来获取到准确的每一个 DOM 元素
操作属性
- 我们获取到元素后, 可以直接操作 DOM的属性, 然后直接把效果展示在页面上
innerHTML
- 获取元素内部的 HTML 解构
<div>
<p>
<span>hello</span>
</p>
</div>
var div = document.querySelector('div')
console.log(div.innerHTML) // <p><span>hello</span></p>
- 设置元素内部的 HTML 解构
<div></div>
var div = document.querySelector('div')
div.innerHTML = '<p><span>hello</span></p>'
innerText
- 获取元素内部的文本(只能获取到文本, 获取不到 html 标签)
<div>
<p>
<span>hello</span>
</p>
</div>
var div = document.querySelector('div')
console.log(div.innerHTML) // hello
- 设置元素内部的 HTML 解构
<div></div>
var div = document.querySelector('div')
div.innerHTML = '<p><span>hello</span></p>'
- 会把 '
hello
' 当作一段文本出现在 div 元素内, 而不会吧 p 解析成标签
getAttribute
- 获取元素的某个属性(包括自定义属性)
<div a="100" class="box"></div>
var div = document.querySelector('div')
console.log(div.getAttribute('a')) // 100
console.log(div.getAttribute('calss')) // box
setAttribute
- 给元素设置的一个属性(包括自定义属性)
<div></div>
var div = document.querySelector('div')
console.log(div.setAttribute('a', 100))
console.log(div.setAttribute('calss', box))
removeAttribute
- 直接移出元素的某个属性
<div a="100" class="box"></div>
var div = document.querySelector('div')
console.log(div.removeAttribute('calss'))
H5 自定义属性
- 在 H5 自定义属性中
data-表示该属性是一个自定义属性 data-以后的内容才是属性名=后面的内容才叫做属性值- 每一个元素身上天生自带一个属性, 叫做 dataset, 是一个类似对象的数据结构
- 内部记录的是该元素身上所有
data-开头的自定义属性 - 对于该元素 H5 自定义属性的操作, 就是对这个数据结构的操作(对象操作语法)
<div data-a="100" class="box"></div>
var oDiv = document.querySelector('div')
// 增
oDiv.dataset.age = 18
// 删
delete oDiv.dataset.a
// 查
console.log(oDiv.dataset.age)
style
- 专门用来个元素添加 css 样式的
- 添加的都是行内样式
<div></div>
var div = document.querySelector('div')
div.style.width = '100px'
div.style.hright = '100px'
div.style.backgroundColor = 'pink'
className
- 专门用来操作元素的 类名
<div class='box'></div>
var div = document.querySelector('div')
console.log(div.className) // box
div.calssName = 'ceshi'
console.log(div.calssName) // ceshi
- 在设置的时候, 不管之前有没有类名, 都会全部被设置的值覆盖
-
进制转换(了解)与保留小数(掌握)
- 十进制转换为其他进制
十进制数组.toString(其他进制的数)
var num = 100
num.toString(2) // 将 10 进制的 100, 转换为 2 进制的数, 得到了: '1100100'
num.toString(36) // 将 10 进制的 100, 转换为 36 进制的数, 得到了: '2s'
- 其他进制转换为十进制
var num = parseInt(数字, 将数字视为几进制的数字然后转换为10进制的数字)
var num = parseInt(100, 2) // 将100视为2进制的数, 然后将其转换为十进制的数字, 得到了: 4
var num = parseInt(100, 16) // 将100视为16进制的数, 然后将其转换为十进制的数字, 得到了: 256
- 保留小数 toFixed, 保留小数时四舍五入, 且返回的是字符串
var num = 100.123456789
var num1 = num.toFixed(2) // 100.12
var num2 = num.toFixed(4) // 100.1235
Math 与 Date
- Math 给我们提供了操作数据的一些方法, 是 JS 内置的一个对象
- Date 给我们提供了操作时间的一些方法, 是 JS 内置的一个对象
数学方法
- random / round / ceil / floor / abs
- random
- 语法:
Math.random() - 作用: 得到一个随机数, 每次生成的数字都不一样, 但一定是0~1之间的,包含0 不包含1
- 语法:
- round
- 语法:
Math.round(数字) - 作用: 将一个小数 四舍五入 变成整数
- 语法:
- ceil
- 语法:
Math.ceil(数字) - 作用: 将一个小数 向上取整
- 语法:
- floor
- 语法:
Math.floor(数字) - 作用: 将一个小数, 向下取整
- 语法:
- abs
- 语法:
Math.abs(数字) - 作用: 返回一个数字的绝对值
- 语法:
- random
- sqrt / pow / max / min / PI
- sqrt
- 语法:
Math.sqrt(数字) - 作用: 求平方根
- 语法:
- pow
- 语法:
Math.pow(基数, 幂) - 作用: 返回基数的几次幂
- 语法:
- max
- 语法:
Math.max(数字1, 数字2, 数字3, 数字4) - 作用: 返回最大值
- 语法:
- min
- 语法:
Math.min(数字1, 数字2, 数字3, 数字4) - 作用: 返回最小值
- 语法:
- PI
- 语法:
Math.PI() - 作用: 得到 π
- 语法:
- sqrt
- 封装函数: 范围内的随机整数
时间对象
时间对象的创建
- 语法:
var timer = new Date() - 不传参
- 默认返回当前时间
var timer = new Date() console.log(timer) // Fri Oct 07 2022 08:52:29 GMT+0800 (中国标准时间) - 传参
- 可以获取到一个你传递进去的时间
var timer = new Date('2022-01-06 12:12:12') console.log(timer) // Thu Jan 06 2022 12:12:12 GMT+0800 (中国标准时间)- 传递两个数字, 第一个为年, 第二个为月
var timer = new Date(2022, 00) // 注意 月份从 0 开始计数, 0表示1月, 11表示12月 console.log(timer) // Sat Jan 01 2022 00:00:00 GMT+0800 (中国标准时间)- 传递三个数字, 前两个不变, 第三个表示该月份的第几天, 从1到31
var timer = new Date(2022, 00, 31) // 注意 月份从 0 开始计数, 0表示1月, 11表示12月 console.log(timer) // Mon Jan 31 2022 00:00:00 GMT+0800 (中国标准时间)- 传递四个数字, 前三个不变, 第四个表示当天的几点, 0-23
var timer = new Date(2022, 00, 31, 23) // 注意 月份从 0 开始计数, 0表示1月, 11表示12月 console.log(timer) // Mon Jan 31 2022 23:00:00 GMT+0800 (中国标准时间)- 传递五个数字, 前四个不变, 第五个为该小时的多少分钟, 0-59
var timer = new Date(2022, 00, 31, 23, 59) // 注意 月份从 0 开始计数, 0表示1月, 11表示12月 console.log(timer) // Mon Jan 31 2022 23:59:00 GMT+0800 (中国标准时间)- 传递六个参数, 前五个不变, 第六个表示该分钟的多少秒, 0-59
var timer = new Date(2022, 00, 31, 23, 59, 59) // 注意 月份从 0 开始计数, 0表示1月, 11表示12月 console.log(timer) // Mon Jan 31 2022 23:59:59 GMT+0800 (中国标准时间)- 传递字符串的形式
console.log(new Date('2019')) // Tue Jan 01 2019 08:00:00 GMT+0800 (中国标准时间) console.log(new Date('2019-02')) // Fri Feb 01 2019 08:00:00 GMT+0800 (中国标准时间) console.log(new Date('2019-02-28')) // Thu Feb 28 2019 08:00:00 GMT+0800 (中国标准时间) console.log(new Date('2019-02-28 13:')) // Thu Feb 28 2019 13:00:00 GMT+0800 (中国标准时间) console.log(new Date('2019-02-28 13:13:')) // Thu Feb 28 2019 13:13:00 GMT+0800 (中国标准时间) console.log(new Date('2019-02-28 13:13:13')) // Thu Feb 28 2019 13:13:13 GMT+0800 (中国标准时间)
将日期对象格式化成指定内容
- 我们得到的时间字符串是:
Thu Feb 28 2019 13:13:13 GMT+0800 (中国标准时间) - 我们得到这个日期中是那年或者那天, 需要靠截取字符串的形式得到
- 但是现在 JS 为我们提供了一系列的方法来得到里面的指定内容
getFullYear
得到指定字符串中的那一年
var timer = new Date(2022, 00, 31, 23, 59, 59)
console.log(timer) // Mon Jan 31 2022 23:59:59 GMT+0800 (中国标准时间)
console.log(timer.getFullYear()) // 2022
getMonth
得到指定字符串中的那一月, 月的计数从 0 开始
var timer = new Date(2022, 00, 31, 23, 59, 59)
console.log(timer) // Mon Jan 31 2022 23:59:59 GMT+0800 (中国标准时间)
console.log(timer.getMonth()) // 0
getDate
得到指定字符串中的那一日
var timer = new Date(2022, 00, 31, 23, 59, 59)
console.log(timer) // Mon Jan 31 2022 23:59:59 GMT+0800 (中国标准时间)
console.log(timer.getDate()) // 31
getHours
得到指定字符串的那小时
var timer = new Date(2022, 00, 31, 23, 59, 59)
console.log(timer) // Mon Jan 31 2022 23:59:59 GMT+0800 (中国标准时间)
console.log(timer.getHours()) // 23
getMinutes
得到指定字符串中的那分钟
var timer = new Date(2022, 00, 31, 23, 59, 59)
console.log(timer) // Mon Jan 31 2022 23:59:59 GMT+0800 (中国标准时间)
console.log(timer.getMinutes()) // 59
getSeconds
得到指定字符串中的那秒钟
var timer = new Date(2022, 00, 31, 23, 59, 59)
console.log(timer) // Mon Jan 31 2022 23:59:59 GMT+0800 (中国标准时间)
console.log(timer.getSeconds()) // 59
getDay
获取当前日期是一周中的 第几天(周日是0, 周六是6)
var timer = new Date(2022, 00, 31, 23, 59, 59)
console.log(timer) // Mon Jan 31 2022 23:59:59 GMT+0800 (中国标准时间)
console.log(timer.getDay()) // 1
getTime
按照 格林威治时间计算 从1970 年 1 月 1 日 0 时 0 分 0 秒 到现在(或指定日期)的毫秒数
var timer = new Date(2022, 00, 31, 23, 59, 59)
console.log(timer) // Mon Jan 31 2022 23:59:59 GMT+0800 (中国标准时间)
console.log(timer.getTime()) // 1554681622000
设置相关
setFullYear()
- 语法:
时间对象.setFullYear(年份信息) - 作用: 修改该时间对象内的 年份信息
var time = new Date()
timer.setFullYear(2008)
console.log(timer.getFullYear())
setMonth()
- 语法:
时间对象.setMonth(月份信息) - 作用: 修改该时间对象内的 月份信息
var time = new Date()
timer.setMonth(2)
console.log(timer.getMonth())
setDate()
- 语法:
时间对象.setDate(日期信息) - 作用: 修改该时间对象内的 日期信息
var time = new Date()
timer.setDate(4)
console.log(timer.getDate())
setHours()
- 语法:
时间对象.setHours(小时信息) - 作用: 修改该时间对象内的 小时信息
var time = new Date()
timer.setHours(12)
console.log(timer.getHours())
setMinutes()
- 语法:
时间对象.setMinutes(分钟信息) - 作用: 修改该时间对象内的 分钟信息
var time = new Date()
timer.setMinutes(45)
console.log(timer.getMinutes())
setSeconds()
- 语法:
时间对象.setSecond(秒钟信息) - 作用: 修改该时间对象内的 秒钟信息
var time = new Date()
timer.setSeconds(20)
console.log(timer.getSeconds())
setMilliseconds()
- 语法:
时间对象.setMilliseconds(毫秒信息) - 作用: 修改该时间对象内的 毫秒信息
var time = new Date()
timer.setMilliseconds(857)
console.log(timer.getMilliseconds())
setTime()
- 语法:
时间对象.setTime(毫秒信息) - 作用: 使用时间戳信息直接定位时间对象
var time = new Date()
timer.setTime(1440004004531)
console.log(timer)
定时器
- 两种定时器的介绍和作用 ( setTimeout / setInterval )
- setInterval 计时器, 每间隔固定的时间执行一次 语法: setInterval(函数, 数字) 函数: 每间隔多少时间执行的代码 数字: 间隔时间, 单位是毫秒
- setTimeout 倒计时器, 在指定时间到达后, 执行一次
- 语法: setTimeout(函数, 数字) 函数: 一段时间后执行的代码 数字: 间隔时间, 单位是毫秒
- 定时器的返回值及意义
- 返回值不区分定时器种类, 用于表示你这个定时器是页面中的第几个定时器
- 作用: 用来关闭定时器
- 关闭定时器
- 不区分定时器种类, 只要给出正确的定时器返回值就可以关闭
- 语法:
- clearTimeout(定时器返回值)
- clearInterval(定时器返回值)
简单的代码异步执行机制
- 什么是非异步执行代码
- 按照从上到下的顺序, 从左到右的顺序, 依次执行每一行代码
- 上一行代码没有执行完毕, 不会执行下一行代码
- 什么是异步执行代码
- 当代码遇到异步任务的时候, 会把该代码放在 异步队列 内等待
- 所有的同步代码执行完毕后, 再开始执行 异步队列内的代码
- 什么是异步任务
- 两种定时器都是异步任务
- 可以理解为, 限制性定时器外面的代码, 然后执行定时器里边的代码