JavaScript初识
1、组成
- BOM:JS操作 “浏览器” 发生变化的属性和方法
- DOM:JS操作 “文档流” 发生变化的属性和方法
- ECMAScript:JS的语法和标准
2、JavaScript的数据类型
- 基本数据类型:Number、String、Boolean(true/false)、Undefined、Null
- 引用数据类型:Object、Function、Array
- 数据存储的区别:
- 栈内存:基本数据类型,直接把值存在栈内存里面
- 堆内存:引用数据类型,将地址存在栈内存,数据存在堆内存里面
- 检测基本数据类型:typeof
3、JavaScript的数据类型转换
- 转数值:Number(内容)、parseInt(内容)、parseFloat(内容)
- 转字符串:String(内容)、内容.toString()
- 转布尔:Boolean(内容) // 只有“ 0、NaN、空字符串(’ ') 、undefined、null ”转换为false
ES语法规范
1、关键字
- 声明变量的关键字
- var :es6以前声明变量,可以重复声明变量,不会报错
- let : es6新增的关键字,用来取代var,比var的好处 有块级作用域
- const :声明常量
- 声明函数的关键字
- function : 声明函数
- 声明类的关键字
- class : 声明类
2、运算符
- 算数运算符: +、-、*、/、%(取余)、**(取幂)
- 赋值运算符:=(赋值)、+=、-=、*=、/=、%=
- 比较运算符:>、<、>=、<=、= =、= = =、!=、!==
- 逻辑运算符:&&(与/且)、||(或)、!(取反)
- 自增自减运算符:++、–
console.log(a++) // 先使用 在运算
console.log(++a) // 先运算 在使用
let h += a // 相当于 h = h + a
a == b // 比较值,不比较类型
a === b // 全等 值和类型都有相等
a && b // a是true 且 b也是true
a || b // 如果a是true 直接返回true 如果a不是true 判断,b是true,也返回true, 否则返回false。
!a // 取反
3、条件分支语句
- if
if (条件) {
/* 满足此条件执行的代码 */
} else if (条件) {
/* 满足此条件执行的代码 */
} else {
/* 以上条件都不满足 执行的代码 */
}
- switch
switch (形参) {
case 选项1:
/* 形参 = 选项1 执行的代码 */
break;
case 选项2:
/* 形参 = 选项2 执行的代码 */
break;
default:
/* 以上都不满足 执行这里的代码 */
}
4、循环结构语句
- for 循环
const arr = ['a', 'b', 'c']
// 满足几次 这个循环的代码就会执行几次
for (let i = 0; i < arr.length; i++) {
console.log(arr[i]) // arr[i] 代表每一次的值。 这个循环转3圈,每一圈的值。
}
- while 循环 和 do while 循环
const arr = ['a', 'b', 'c']
// 和for循环差不多 只是写法不同 让我们多一种选择而已
let i = 0;
while (i < arr.length) {
console.log(arr[i])
i++
}
// 和while循环一样 只是先执行一次,再判断。
let i = 0;
do {
console.log(arr[i])
i++
} while (i < arr.length)
- for in 循环
# 循环数组
const arr = ['a', 'b', 'c']
for (let index in arr) {
console.log(index, arr[index])
}
# 注意:
1. 循环数组,index出来是 索引: 0 1 2
2. 取值的话,就是: arr[0] arr[1] arr[2]
# 循环对象
const user = {
name: '小貂蝉',
age: 18,
email: 'dc@qq.com'
}
for (let key in user) {
console.log(key, user[key])
}
# 注意:
1. 循环对象,key是出来的键名: name, age, email
2. 取值就是: user['name'] user['age'] user['email']
3. 对象取值,如果key是变量,必须使用 对象[key],不能 user.key
- for of 循环
const arr = ['a', 'b', 'c']
for (let v of arr) {
console.log(v)
}
# 注意:
1. 循环数组,出来的是: 每一项的值
2. 不能用来循环对象
5、循环控制语句
循环控制语句 'break'
+ 当在一个循环里面执行到 break 关键字的时候
+ 会直接结束整个循环
循环控制语句 'continue'
+ 使用在循环里面的关键字
+ 当代码执行到 continue 关键字的时候,会结束循环得本次,继续下一次
循环控制语句 'JS 标记语法'
+ 直接在循环的开始位置做一个 标记
名字:
+ 当你准备跳出的时候
break 标记
案例-------
hrea:
for (let i = 0; i < 9; i++) {
for (let j = 0; j < 9; j++) {
if (i === 3 && j === 5) {
console.log(111);
break hrea
}
}
console.log(i);
}
----------
6、三目运算
语法:
条件 ? 结果1 :结果2 //条件是true 走结果1 否则,走结果2
7、函数
- 【1】声明式函数
function 函数名 (形参1,形参2){
/* 代码块 */
}
- 【2】函数表达式
const 变量 = function (形参1,形参2){
/* 代码块 */
}
- 【3】箭头函数
const 变量 = (形参1,形参2) => {
/* 代码块 */
}
注意:
1.如果形参只有1个,可以省略()
2.如果{}只有1句代码,可以省略{},且必须省略return
3.箭头函数没有 arguments
4.箭头函数不能 new
5.箭头函数的 this,指向上一级作用域
- 【4】递归函数
概念:函数的一种应用方式
递:一层一层的进去
归:一层一层的回来
本质:一个函数自己调用自己
=> 当达到设置的终点的时候
=> 再归回来,归使用 return
注意:** 写递归先写停 **
例:5的阶乘 5*4*3*2*1
function fn(n) {
if(n===1){
//终点位置出现
return 1
}
//递进去
return n * fn(n-1)
}
let b = fn(5)
console.log(b);
8、内置对象
Array
- 属性
- length:获取数组的长度
- 方法
reverse() // 反转数组的顺序,作用:反转 push() // 在数组后面添加元素,作用:添加元素 pop() // 删除数组最后一个元素,作用:删除元素 unshift() // 前面添加一个元素,作用:添加元素 shift() // 前面删除一个元素,作用:删除元素 join('连接符号') // 数组转字符串,作用:转字符串 indexOf() // 查找元素所在的位置,作用:找元素索引 lastIndexOf() // 反向查看元素所在位置 includes() // 查看是否包含指定元素,作用:找元素 flat(数字/Infinity) // 降维 作用:多维数组,转1维数组 Infinity(无穷) splice(开始索引,删多少个,替换数据1,替换数据2...) // 添加、删除、修改元素 sort(function (a,b){ return a-b}) // 排序 forEach(function (item,index) {}) // 循环,没有返回值 map(function (item,index) {}) // 循环,把每次的结果,放入一个新数组,最后返回这个新数组 filter(function (item,index) {}) // 过滤,把每一次满足条件的元素,放入一个新数组,返回这个新数组 every(function (item,index) {}) // 每一个都满足,就返回true,否则,返回false some(function (item,index) {}) // 只要1个满足,就返回true,否则返回false findIndex(function (item) {}) // 找索引 find(function (item) {}) // 找元素 // 不改变原数组 content() // 连接两个或多个数组,作用:连接数组,合并数组 slice() // 切割数组,截取元素
String
- 方法
charAt(索引) // 根据索引,查找字符 charCodeAt(索引) // 获取UTF-8编码 concat('字符串') // 拼接字符串 includes('字符串') // 查询是否包含 indexOf('字符串') // 查找字符的索引 replace('要被替换的字符','替换成的字符') // 替换 slice(开始索引,结束索引) // 截取 split('切割符号') // 字符串转数组 substr(开始索引,多少个) // 截取 substring(开始索引,结束索引) // 截取 toLowerCase() // 转小写 toUpperCase() // 转大写 trim() // 取两头空白 search('字符串') // 查找字符串里面有没有匹配的字符串片段 // 不常用 big() / small() // 字体大/小 bold() // 加粗 fontsize(尺寸) // 字体大小 fontcolor(颜色) // 字体颜色
Date
- 方法
// 创建时间对象 let time = new Date() // 系统时间 let time = new Date('年-月-日 时:分:秒') // 创建指定日期 // 获取时间对象信息的方法 getFullYear() // 获取年 getMonth() // 获取月 0~11 getDate() // 获取天 0~31 getHours() // 获取小时 getMinutes() // 获取分钟 getSeconds() // 获取秒 getDay() // 获取星期 0~6 getTime() // 获取 时间戳
Math
- 方法
Math.PI() // 圆周率 3.1415926... Math.abs() // 绝对值 |-10|->10 Math.ceil() // 向上取整 Math.floor() // 向下取整 Math.max() // 取最大值 Math.min() // 取最小值 Math.random() // 取随机数 0~1 Math.round() // 四舍五入 Math.floor(Math.random()*(max-min+1)+min) // 生成指定范围的随机整数
Number
- 方法
toFiexd(数值) // 保留小数点位数
Object
- 方法
keys() // 取出所有的key,放入一个数组 assign() // 合并多个对象
9、JSON格式
JSON.parse() // 字符串 --> 数组/对象
JSON.stringify() // 数组/对象 --> 字符串
10、本地存储
// 永久缓存(localStorage,只能手动删除)
localStorage.setTime('名字','值') // 存储
localStorage.getTime('名字') // 获取
localStorage.removeTime('名字') // 删除指定数据
localStorage.clear() // 清除所有数据
// 临时缓存(sessionStorage,关闭浏览器)
sessionStorage.setTime('名字','值') // 存储
sessionStorage.getTime('名字') // 获取
sessionStorage.removeTime('名字') // 删除指定数据
sessionStorage.clear() // 清除所有数据
共同点:
只能存储字符串格式的数据
想存储对象数据结构,转换成json格式存储
11、定时器
// JS 的定时器
setTimenout(函数,时间ms) // 延时定时器
setInterval(函数,时间ms) // 间隔定时器
// 关闭定时器(不分定时器种类)
clearTimeout()
clearInterval()
JavaScript高级特性【es5】
1、作用域
- 概念:标识符访问的"范围"。
- 作用域链:从里往外,逐级向上查找,找到就使用,找不到就报错
- 作用域分类:
- 全局作用域(window)
- 局部作用域(函数)
- 块级作用域({})
2、闭包
- 概念:函数跨作用域访问变量,形成闭包,闭包是一种作用域的体现
- 写法:父函数嵌套子函数,子函数访问父函数的变量,把子函数返回或挂在全局
- 作用:解决循环定时器问题,解决循环事件绑定问题,实现早期的模块化
- 优缺点:优点是把变量隐藏在内部,避免全局污染。缺点是:过多使用闭包,变量常驻内存,不会被释放,造成内存开销过大,甚至内存泄漏。
3、原型
- 概念
- 【1】每个函数都有一个属性
prototype
,就是原型【显示原型】 - 【2】添加在原型上的属性和方法,被所有实例对象共享
- 【3】实例对象都有一个属性
__proto__
,指向构造函数的prototype
- 【4】原型
prototype
上有一个属性constructor
, 指向构造函数本身。
- 【1】每个函数都有一个属性
- 作用
- 添加共享方法
4、原型链
- 概念
- 【1】原型
prototype
本身也是实例对象,也有__proto__
, 指向Object的prototype
- 【2】
Object.prototype
也是实例对象,也有__proto__
, 指向null
Object.prototype
也有属性constructor
,指向构造函数本身。
- 【1】原型
- 作用
- 添加共享方法
5、this
- 7种指向
- 全局 -> window
- 函数 -> 调用者
- 对象方法 -> 调用者
- 构造函数 -> 实例对象
- 事件绑定 -> 事件源
- 定时器 -> window
- 箭头函数 -> 上一级
- 改变指向方法
- call()
函数.call(this的指向目标,参数1,参数2)
- apply()
函数.apply(this的指向目标,[参数1,参数2])
- bind()
let 新函数 = 函数.bind(this的指向目标) # 注意 当我们调用新函数,新函数中的this,就永远指向之前绑定的 目标
6、类型检测
- typeof 检测基本类型
typeof 'abc' // string typeof true // boolean typeof 10 // number typeof undefined // undefined typeof function(){} // function typeof Symbol() //symbol typeof null // object typeof {} // object typeof [] // object
- instanceof 检测引用类型
[] instanceof Array // true {} instanceof Object // true new Date() instanceof Data // true
- Object.prototype.toString.call() 检测所有类型
Object.prototype.toString.call('abc') // [Object String] Object.prototype.toString.call(10) // [Object Number] Object.prototype.toString.call(true) // [Object Boolean] Object.prototype.toString.call(undefined) // [Object Undefined] Object.prototype.toString.call(null) // [Object Null] Object.prototype.toString.call(Symbol()) // [Object Symbol] Object.prototype.toString.call(function () {}) // [Object Function] Object.prototype.toString.call([]) // [Object Array] Object.prototype.toString.call({}) // [Object Object]
- Array.isArray() 检测是否是数组
7、深拷贝&浅拷贝
- 浅拷贝
- for in 循环
let 对象1 ={ 属性名:属性值 ... } let 对象2 = {} for (let key in 对象1){ 对象2[key] = 对象1[key] }
- Object.assign
let 对象1 = { 属性名:属性值 ... } let 对象2 = Object.assign({},对象1)
- 扩展运算符
let 对象1 = { 属性名:属性值 ... } let 对象2 = { ...对象1 }
- 深拷贝
- JSON.stringify()
- JSON.parse()
let 对象1 = { 属性名:属性值 属性名:{ key:value } } let 对象2 = JSON.parse( JSON.stringify(对象1) )
ES6
1、解构
// 解构赋值的时候,使用 : 进行重命名
# 解构对象
const {变量1,变量2} = 对象
# 解构数组
const [变量1,变量2] = 数组
# 解构函数参数
function 函数名({变量1, 变量2}) {}
function 函数名([变量1, 变量2]) {}
2、扩展运算符
# 展开字符串
...字符串
# 展开数组
...数组
# 合并数字
[...数组1, ...数组2]
# 浅拷贝数组
const 新数组 = [...要拷贝的数组]
# 浅拷贝对象
const 新对象 = {...要拷贝的对象}
# 合并对象
const 新对象 = {...对象1,...对象2}
# rest参数
function 函数名(形参1,...rest) {}
# 伪数组变为真数组
const 真数组 = [...伪数组]
3、模板字符串
# 语法
`${表达式}`
# 注意:
1. 表达式:有唯一返回值。
4、对象的简洁写法
const 对象 = {
name, // key和value相同,省略
属性名() {} // 方法省略 :function
}
5、class
# 类的写法
class 类名 {
// 相当于在构造函数中写: this.属性名 = 属性值
属性名=属性值
// 构造函数
constructor() {}
// 原型方法
方法名() {}
// 静态方法
static 方法名() {}
}
# 继承
class A {}
class B extends A {
constructor() {
super()
this.属性名=属性值
}
}
6、模块化语法
# 方式一
export 要导出的东西
import {xx, yy} from '路径或模块名'
# 方式二
export default {} // 注意: 1个js文件中,只能写1次
import 变量 from '路径或模块名'
7、Promise
- 基本语法
new Promise((resolve, reject) => { if (成功) { resolve('一些成功数据') // 传递给下一个then } else { reject('一些失败数据') // 传递给下一个catch } }).then((data) => { // data就是上一步resolve()里面的数据 }).catch((err) => { // err就是上一步 reject()里面的数据 })
- 解决回调地狱【回调的代码,编成从上往下扁平的代码】
# 回调地狱 axios.get(url1).then((res) => { axios.get(url2).then((res) => { axios.get(url3).then((res) => { }) }) }) # Promise解决代码 new Promise((resolve) => { axios.get(url1).then((res) => { resolve(res.data) }) }).then((data) => { return new Promise((resolve) => { axios.get(url2).then((res) => { resolve(res.data) }) }) }).then((data) => { return new Promise((resolve) => { axios.get(url3).then((res) => { resolve(res.data) }) }) }).then((data) => { console.log(data) })
8、Async和Await
概念:
-
async
:声明函数中有异步代码 -
await
:等待Promise结果async function 函数名() { let 右侧resolve的结果 = await Promise的函数调用 }
-
解决回调地狱
# 回调地狱 axios.get(url1).then((res) => { axios.get(url2).then((res) => { axios.get(url3).then((res) => { }) }) }) # async和await解决回调地狱 async function getData() { let 结果1 = await axios.get(url1) let 结果2 = await axios.get(url2) let 结果3 = await axios.get(url3) } getData()
BOM
1、location(浏览器地址栏)
# 属性 http://www.baidu.com:443/img/logo.png?user=admin&id=666#pid=555
href // 完整地址 location.href="" 进行跳转
origin // 协议 + 域名 + 端口 http://www.baidu.com:443
host // 域名 + 端口 www.baidu.com:443
hostname // 域名 www.baidu.com
port // 端口 443
pathname // 路径 /img/logo.png
search // 参数 ?user=admin&id=666
hash // #pid=555
protocol // 协议 http
location.href // 当前地址栏地址
location.search // 当前地址栏查询字符串
location.reload() // 刷新页面
2、history(操作历史记录)
history.go() // 跳转
history.back() // 向后
history.forward() // 向前
3、navigator(获取浏览器信息)
navigator.userAgent() // 获取用户代理信息
navigator.language() // 获取语言
4、screen(获取屏幕信息)
screen.width() // 宽度
screen.height() // 高度
5、window(浏览器窗口对象)
window.alert() // 弹窗
window.setTimeout() // 定时器
window.onscroll = function () {} // 滚动条滚动
window.onresize = function () {} // 窗口大小发生变化
window.confirm() // 弹出确认框
window.onload = function (){} // 页面加载完毕
window.open() // 打开某个网址
// 浏览器窗口尺寸(可视窗口)
window.innerWidth() // 宽
window.innerHeight() // 高
DOM
1、操作节点
- 获取节点
# H5 document.querySelector('选择器名') document.querySelectorAll('选择器名') # H4 document.getElementById('id名') document.getElementsByName('name名') document.getElementsByClassName('类名') document.getElementsByTagName('标签名')
- 删除节点
dom.remove() // 把节点本身删除掉 dom.removeChild() // 把节点的儿子删除 dom.innerHTML = "" // 清空节点 dom.innerText = "" // 清空节点内容 dom.textContent = "" // 清空节点内容
- 修改节点
dom.innerHTML = '新的内容' dom.innerText = "新的内容" dom.textContent = "新的内容"
- 添加节点
const 节点 = document.createElement('节点标签名') dom.appendChild(节点)
2、操作样式
- 直接操作style
dom.style.css属性名 = '新的值'
- 操作类名
dom.className = "新的类名"
3、操作属性
# H4操作属性
# 标准属性
dom.属性名 // 获取 dom.id
dom.属性名 = '新的属性值' // 修改 dom.id = 'box'
# 自定义属性
dom.getAttribute('属性名') // 获取自定义属性的值
dom.setAttribute('属性名', '新的属性值') // 修改自定义属性的值
dom.removeAttribute('属性名') // 删除自定义属性的值
# H5操作属性
# 自定义属性(data-属性名)
dom.dataset.属性名 // 获取
dom.dataset.属性名 = '新的值' // 设置
4、DOM事件
- 绑定事件
dom.addEventListener(事件类型, function () { /* 事件处理函数 */ })
- 事件类型
dom.addEventListener(事件类型, function () { /* 事件处理函数 */ }) # 事件类型 // 鼠标事件 click // 点击 dblclick // 双击 contextmenu // 鼠标右键单击 mousedown // 某个鼠标按键被按下 mouseup // 某个鼠标按键被松开 mousemove // 鼠标被移动 mouseout // 鼠标从某元素移开 mouseover // 鼠标被移到某元素之上 mousewheel // 滚轮滚动事件 // 键盘事件 keydown // 键盘按下 keypress // 某个键盘的键被按下或按住 keyup // 某个键盘的键被松开 // 浏览器事件 load // 页面加载完毕 scroll // 滚动 resize // 窗口尺寸改变 offline // 网络断开 online // 网络恢复 hashchange // 哈希值改变了 // 表单事件 focus // 聚焦 change // 输入框的值发生变化 submit // 提交 input // 输入 blur // 失焦 reset // 重置事件,点击 reset 按钮,才能触发 // 触摸事件(移动端) touchstart // 触摸开始 touchmove // 触摸移动 touchend // 触摸结束
- 事件源
dom.addEventListener(事件类型, function (e) { /* 事件处理函数 */ e就是事件对象 里面有一些有用的信息 e.target 事件源 e.preventDefault() // 阻止默认行文 e.stopPropagation() // 阻止冒泡 })
- 事件委托(事件委派、事件代理)
- 概念:给子绑定的事件,绑定在父上面
Ajax
- 原生ajax
- get方式
// 1. 创建ajax对象 const xhr = new XMLHttpRequest() // 2. 配置方式和地址 xhr.open('get', url?参数名=参数值) // 3. 发送请求 xhr.send() // 4. 监听状态变化 接收数据 xhr.onreadystatechange = function () { if (xhr.readyState === 4 && xhr.status === 200) { var data = xhr.responseText; } }
- post方式
// 1. 创建ajax对象 const xhr = new XMLHttpRequest() // 2. 配置方式和地址 xhr.open('post', url) // 3. 设置请求头 xhr.setRequestHeader('Content-Type', 'applciation/x-www-form-urlencode') // 4. 发送请求 xhr.send('参数名=参数值') // 5. 监听状态变化 接收数据 xhr.onreadystatechange = function () { if (xhr.readyState === 4 && xhr.status === 200) { var data = xhr.responseText; } }
- axios
- get方式
# 方式一 axios.get(url?参数名=参数值).then(res => { // res.data就是数据 }).catch(err => { // err是错误信息 }) # 方式二 axios.get(url, { parmas: { 参数名:参数值 } }).then(res => { // res.data就是数据 }).catch(err => { // err是错误信息 })
- post方式
axios.get(url, { 参数名:参数值 }).then(res => { // res.data就是数据 }).catch(err => { // err是错误信息 })
- get和post的区别
- get参数在地址栏,游览器有限制地址栏长度,所以不能传递太多参数,post可以。
- get参数在地址栏,post参数在请求体
- get不安全,参数暴露在地址来,post相对安全。
- get不需要设置请求头(有些时候也需要),post需要设置。