javascript是什么?
-
简称js
-
网页三剑客
- 静态页面(网页合成工程师)
- html 结构
- css 样式
- 动态页面(前端工程师 web前端)
- javascript 行为(交互)
- 静态页面(网页合成工程师)
-
javascript诞生
-
web1.0 可读
-
web2.0
-
web3.0
-
网景(netscape)有一款浏览器叫做navigator(领航者)想要网页有一些可交互的效果
-
请了javacript祖师爷
布兰登.艾奇
10天发明了livescript -
借助java热度去推广livescript 更名为javascript
-
微软公司推出IE 自己参考javascript功能推出了JScript
-
网景把javascript托管给了ECMA(欧洲计算机制造商协会) 由ECMA制定了一个标准 这个标准有一个名称叫做
ECMAScript
简称es -
ECMAscript是将javascript和jscript标准语法统一之后的一个产物
-
es5.0版本
-
-
javascript的构成部分
- ECMAscript标准语法
- DOM
- BOM
- java和javascript什么关系?
javascript的三种写法
- 外部
- 内部
- 内联/行内
注释
- 单行 // 注释内容
- 多行 /* 注释内容 */
- 重要性
- 方便代码的阅读
- 方便代码的维护
变量
-
含义: 变量就是在计算机内存里面以命名的方式存储一个数据, 再我们想要用到这个数据的时候可以根据这个名称找到这个数据 取出来使用
-
存数据的过程
- var 变量名 = 数据;
- 声明变量(定义变量)
- var 变量名
- 赋值
- 变量名 = 数据
-
取数据
- 变量名
-
注意事项
- 只定义(声明)变量 不给这个变量赋值 使用这个变量不会报错 他的值是undefined
- 直接使用一个未定义的变量 这时候会报错 报错信息
变量名 is not defined
-
变量名命名规则和规范
-
规则: 必须要遵循 因为这个是由ecmascript定义的 不遵循就会报错
- 变量名必须是英文a-z A-Z、数字0-9、下划线_、美刀$组成,不能以数字开头(组成部分)
- 严格区分大小写(大小写)
- 不能是关键字和保留字(保留字和关键字)
- 关键字: js正在使用的单词 var
- 保留字: js未来可能会使用到的
- 不能是中文 中间不能有空格
-
规范: 由行业前辈们定义的 建议遵守
- 语义化:见名知意
- 小驼峰命名法: 多个单词组成的 从第二个单词开始 首字母大写
-
-
数据类型
- 基础数据类型: 字符串、数值、布尔值、undefined、null
- 字符串
- ‘’ “”
- 数值
- 0 1 2… 9
- 小数
- 1.1
- 负数
- -1
- 布尔值
- true 真
- false 假
- undefined
- undefined
- null
- null
-
进制
- 十进制
- 数字
- 0 1 2 3 4 5 6 7 8 9
- 二进制
- 0b数字
- 0 1
- 八进制
- 0o数字
- 0 1 2 3 4 5 6 7
- 十六进制
- 0x数字
- 0 1 2 3 4 5 6 7 8 9 a b c d e f
- 十进制
-
检测数据类型
- console.log(数据) 在控制台里面打印一行日志 用于调试
- typeof
- typeof 数据
- typeof(数据)
- 都会返回对应数据类型的英文单词
- 字符串 string
- 数值 number
- 布尔值 boolean
- undefined undefined
- null object
-
prompt方法
- prompt()
-
类型转换(面试题)
- 含义: 把一种类型转换成另一种类型
- 分类
- 自动类型转换(隐式类型转换) 运算符
- 强制类型转换(手动转换)
- 其他类型转数值
- 三个方法
- Number方法 Number(数据)
- parseInt方法 parseInt(数据)
- parseFloat方法 parseFloat(数据)
- 总结
- 布尔值、undefined、null 用Number方法
- 字符串
- 纯数字 用Number方法
- 非纯数字字符串 截取前面的数字部分
- 保留小数 parseFloat
- 不保留小数 parseInt
- 三个方法
- 其他类型转字符串
- 其他类型转布尔
- 其他类型转undefined
- 其他类型转null
-
NaN
- 代表数值类型的非数字
- 含义: not a number 不是一个数字
- NaN是数值类型 用于表示这个数据不是一个数字
- 产生
- 类型转换的过程中 有些数据可以转换成数字的方式显示 有一些数据无法以数字来显示的 用NaN来表示
- 注意事项
- NaN和任何数做任何比较结果都是false
- NaN和任何数做任何运算结果都是NaN
运算符
-
数学运算符
+ - * / %(取余、模)
- 加法遇到字符串,只要一侧有字符串,另一侧会自动转换成字符串,然后拼接;
- 其他的运算都会先将左右的数据转换成数值然后进行数学运算
-
比较运算符
-
比较运算得到的结果是一个布尔值 满足就返回true 不满足返回false
-
多用于判断
-
‘> < == >= <= !=(不等于) =(全等) !’
-
==(相等) ===(恒等)
- 两个等于号只关注值是否相等 值相等就成立
- 三个等于号既关注值是否相等也关注类型是否相同
-
!= !==
-
-
赋值运算符
= += -= *= /= %=
- var a = 1
- a+=1 --> a = a + 1
- a-=b --> a = a - b
-
逻辑运算符
-
&& 并且 且
- 多个条件 每一个条件都需要满足 整个结果才会是满足
- 条件一 && 条件二 && 条件三
-
|| 或者 或
-
! 取反 非
-
逻辑短路
- 编程短路: 有一段代码 写了没有执行 直接跳过
- && 左侧条件为false 右侧不会执行了
- || 左侧条件为true 右侧不会执行了
- 可以利用短路简化判断
-
-
自增自减运算符(一元运算符)
-
自增
- a++ 后置: 符号在后面
- a++ --> a = a + 1
- ++a 前置: 符号在前面
- ++a --> a = a + 1
- a++ 后置: 符号在后面
-
自减
- a-- 后置
- a-- --> a = a - 1
- –a 前置
- –a --> a = a - 1
- a-- 后置
-
前置和后置的区别
- a++
- ++a
- 单纯的只做自增两者没有区别
- 在做自增的同时还参与了其他运算 这时候就有区别
-
-
三元运算符
- 条件 ? 语句1 : 语句2
- 如果条件满足 就执行语句1
- 如果条件不满足 就执行语句2
分支 判断 选择
-
程序运行的三大结构
- 顺序结构: 代码是从上往下 从左往右执行 每一句都会执行
- 选择结构: 代码不是每一句都会执行 会依据某一个条件执行某一段代码
- 循环结构: 代码会重复多次执行
-
选择结构
- 单分支语句
if(条件){ // 只有条件成立的时候才会执行花括号里面代码 }
- 双分支语句
if(条件){ // 只有条件成立的时候才会执行if花括号里面代码 }else{ // 只有条件不成立的时候才会执行else花括号里面的代码 }
- 多分支语句
if(条件01){ // 条件01满足的时候执行 }else if(条件02) { // 条件02满足的时候执行 }else if(条件03){ // 条件03满足的时候执行 } ... else{ // 以上所有条件都不满足执行 }
switch…case 语句
- 语法
switch(变量){
case 可能值1:
语句01
case 可能值2:
语句02
case 可能值3:
语句03
...
default:
默认语句
}
- 会拿这个变量和每一个可能值进行比较 如果变量和可能值相等 就会执行对应 case 后面的语句;default 里面的语句是变量和所有可能值都不相等就会执行
if 语句和 switch 语句区别
- 如果条件是几个固定值 可以用 switch 也可以用 if
- 当条件是一个范围 用 if
- if 没有穿透效果 switch 语句有穿透效果
循环语句
-
含义: 重复执行一段代码
-
构成条件
- 初始化条件
- 条件判断
- 循环体代码
- 条件变化
-
语法
- while 循环
// 初始化条件 var n = 0; // 条件判断 while (n <= 10) { // 所有写在花括号里代码的会重复执行多次 // 循环体代码 console.log(n); // 条件变化 n++; }
- do…while 循环
// 初始化条件 var n = 1; do { // 所有写在花括号里代码的会重复执行多次 // 循环体代码 console.log(n); // 条件变化 n++; } while (n <= 10); // 条件判断
- for 循环
for (初始化条件; 条件判断; 条件变化) { // 循环体代码 } for (var n = 1; n <= 10; n++) { console.log(n); }
break 和 continue 关键字
- break 打断 终止 当循环里面出现了 break 循环就会提前结束
- continue 继续 会跳过本次循环 直接进入下一次循环
for循环和while循环如何选择
- 很多循环既可以用for循环 也可以用while循环实现
- 如果循环次数是固定的 可以用for循环 也可以用while循环
- 如果循环次数不能确定 要重复执行一段代码 只能直到结束的条件 这时候用while
双重for循环
- 循环嵌套
- 不要使用相同的变量名
- 每一次外循环都会等待内循环执行结束
函数 function
-
含义: 函数就是以命名的方式将一段代码存储到一个盒子里面 在需要执行这段代码的时候可以根据这个名称找到这段代码进行执行
-
定义函数
// 形参 形参就是一个变量 这个地方定义变量不需要写var 相当于自动给你写了一个var function 函数名(num1, a, aa){ // 一段代码 return 数据 }
-
调用函数
// 实参 实参就是具体的数据 var 返回值 = 函数名(1,'haha',true)
-
作用
- 简化代码量
- 方便代码的维护和修改
-
函数的参数
- 函数在定义和调用位置的小括号里面是可以写一些数据的
- 实参: 在函数调用位置写的数据,这个数据称为实际参数 简称实参 实参一般就是具体的数据
- 形参: 在函数定义位置写的数据 这个数据称为形式参数 简称形参 形参一般就是一个变量
- 实参会从左往右一一给形参赋值
-
实参和形参的个数关系
- 实参个数和形参个数相等 实参会从左往右一一给形参赋值
- 实参个数小于形参个数 多出形参的值是undefined
- 实参个数大于形参个数 多出实参没有任何作用
-
返回值
- 含义: 函数调用之后得到的结果
- var 新数据 = Number(数据) var 新数据 = parseInt(数据) var 新数据 = parseFloat(数据)
- 函数默认是没有返回值 他的返回值是undefined
- 如果函数需要有一个返回值 可以在函数定义的内部写一个return return后面的数据就会当成函数的返回值
-
返回值的作用
- 函数返回值可以用于下一步的运算或者判断
-
return关键字
- 让函数执行之后有一个返回值
- 可以提前终止函数的执行
-
break和return的区别
- 他们都有结束 终止的意思
- break用于结束循环和switch穿透
- return用于结束函数(只能用于函数的内部)
-
函数定义的两种方式
// 声明式定义
function 函数名(num1, a, aa){
// 一段代码
return 数据
}
// 赋值式定义
var 函数名 = function(num1, a, aa){
// 一段代码
return 数据
}
// 调用的方式相同
函数名(1,2,3)
预解析 预编译 声明提升
- 含义: 浏览器在运行js之前会有一个看不见的编译过程 在编译过程中会提前将某一些代码执行 (什么是预解析)
- 内容:(预解析做了哪些事情)
- 会将声明式的函数提前定义
- 会将var声明的变量提前定义;只是定义提前没有将赋值提前
- 影响:(预解析有什么样的影响)
- 声明式函数可以提前调用
- var声明的变量可以提前使用但是使用的值是undefined
作用域
-
含义: 一个变量或者一个函数起作用的范围
-
分类:
- 全局作用域: 不被任何一个函数所包裹的区域
- 局部作用域: 被函数所包裹的区域
-
变量的分类
- 全局变量: 定义在全局作用域内部
- 全局变量可以在全局也可以在局部使用
- 局部变量: 定义在局部作用域内部
- 局部变量只能在当前局部使用,无法在全局或者其他的局部使用
- 全局变量: 定义在全局作用域内部
-
作用域的访问原则
- 在访问一个变量的时候遵循的原则
- 在一个函数内部使用某一个变量的时候 优先在函数自身查找 自身有就使用自身的
- 自身没有 就会自动往上一级作用域里面查找 上一级有就使用上一级的变量
- 上一级没有就继续往上上一级 一直找到全局作用域 全局作用域有就使用全局的变量
- 全局作用域都没有就会报错 报这个变量没有定义 is not defined
-
作用域的使用原则
- 在改变一个变量的时候遵循的原则(使用谁的改的就是谁的)
- 当我们改变一个函数内部变量 优先会在当前函数内部查找有没有定义过这个变量 如果有定义 改变的是当前函数内部的变量
- 如果当前函数内部没有定义 会往上一级作用域里面查找有没有定义 如果有定义 改变就是上一级作用域里面的变量
- 上一级作用域没有定义 就会往上上一级查找 一直找到全局作用域 全局里面有定义 改变的就是全局的
- 全局没有定义 如果只是给这个变量赋值 会自动在全局定义一个变量 给这个变量赋值;如果是拿这个变量参与运算 这时候就会报错
特殊的函数
- 匿名函数: 没有函数名的函数
function(){
}
- 自执行函数: 在定义的时候会执行一次
(function(){
})()
(function getSum(){
})()
- 递归函数
- 在函数内部调用自身
function getSum(){
console.log(1)
console.log(2)
getSum() // 调用自己
}
getSum()
-
如果递归没有结束条件 就会出现
死递归
报错Maximum call stack size exceeded
-
递归一定要有结束条件 递归函数必须要有出口 可以使用return来结束递归函数的调用
-
递归可以替代循环
- 求和
-
递归一般是在循环无法解决的时候才会使用
- 斐波那契数列
-
递归函数执行步骤
- 传递: 递归函数在调用函数的时候不能够立马得到结果 需要一直往下传递 这个过程就成为传递的过程
- 在传递的过程中 之前没有算完的函数 会进入到调用栈(call stack)里面等待
- 回归: 递归传递到最后一次(结束条件)有一个结果 不是立马结束调用 还会返回算之前没有算完的函数 这个过程称为回归
- 在回归的过程中 不段会有之前没有算完的函数得到结果 这时候算完的函数就会出调用栈
- 传递: 递归函数在调用函数的时候不能够立马得到结果 需要一直往下传递 这个过程就成为传递的过程
-
打断点调试
- 找到源文件–>source–>在源文件某一行打一个断点
- 直接在源文件某一行写一个debugger
-
递归的优化 尾递归算法
数据类型
- 基础数据类型(原始数据类型、简单数据类型)
- number string boolean undefined null
- 复杂数据类型(引用数据类型)
- object array function
对象 object
-
对象是一种数据类型 是一种复杂的数据类型
-
是一种具有
键值对
结构的数据类型 -
创建一个对象
- 字面量的方式
- var 变量名 = {}
- 内置构造函数的方式
- var 变量名 = new Object()
- 字面量的方式
-
添加数据
- 初始化添加数据
var person = { // 左边的叫做键名 简称键 英文key // 右边的叫做值 英文value username: 'jack', age: 19, gender: '男' }
- 动态添加数据
- 点语法
- 对象名.键名 = 值
- 下标法(方括号)
- 对象名[‘键名’] = 值
- 点语法
-
获取数据
- 根据键名找到这个对应的值
- 点语法
- 对象名.键名
- 下标法
- 对象名[‘键名’]
- 当我们访问对象里面一个不存在的key 不会报错 获取到数据是为undefined
-
修改数据
- 修改就是重新赋值
- 因为对象的key具有唯一性
- 点语法
- 对象名.键名 = 值
- 下标法(方括号)
- 对象名[‘键名’] = 值
-
删除数据
- 点语法
- delete 对象名.键名
- 下标法
- delete 对象名[‘键名’]
- 点语法
-
遍历对象
- 遍历: 将对象里面每一个键值对都取出
for(var 变量名 in 对象名){ console.log(变量名) }
数组 array
-
是js的一种数据类型 是复杂数据类型
-
是有序的数据集合
-
数组是有长度 获取数组的长度可以通过
数组名.length
-
有序性体现数组有一个下标(索引)
-
下标是自动生成的 是按照顺序生成的 是从0开始 下标的范围是[0, 长度-1]
-
创建一个数组
- 字面量
- var 数组名 = []
- 内置构造函数
- var 数组名 = new Array()
- 字面量
-
添加数据
- 初始化添加
- var 数组名 = [1,2,3,4]
- var 数组名 = new Array(1,2,3,4)
- 通过索引的方式给数组添加数据
- 数组名[下标] = 数据
- 初始化添加
-
获取数据
- 通过索引的方式获取数组的数据
- 数组名[下标]
- 通过索引的方式获取数组的数据
-
修改数据
- 修改就是重新赋值
- 数组名[下标] = 数据
-
删除数据
- delete 数组名[下标]
-
遍历数组
- for…in
for(var 变量名 in 数组名){ console.log(变量名) }
- for循环
- 因为数组下标是有序 范围是[0, 数组长度-1] 所以可以自己生成这个下标的范围
for(var i=0;i<=数组名.length-1;i++){ console.log(i) console.log(数组名[i]) }
- for…in
js的存储数据方式
-
栈(stack)
-
堆(Heap)
-
值存储和引用存储
- 基础数据类型 值和变量名都是存储在栈里面的 这种存储方式称为值存储
- 复杂数据类型 变量名和地址是存储在栈里面的 具体的数据存在堆里面 可以根据地址找到堆内存空间的数据 这种存储方式称为引用存储
-
值传递和引用传递问题
- 传递: 把一个变量的数据赋值给另一个变量 这个过程叫做传递
- 基础数据类型赋值 一个变量直接把值赋值给另一个变量 这个过程称为值传递 一个变化 另一个不变
- 复杂数据类型赋值 一个变了直接把存储的地址(引用)赋值给另一个变量 这个过程称为引用传递 一个变化 另一个也会变化
-
值比较和引用比较的问题
- 比较: 是否相等
- 基础数据类型之间的比较是拿他们存储的值进行比较 如果两个数据长得一模一样 就是相等的
- 复杂数据类型之间的比较是拿他们存储的地址进行比较 即使两个数据一模一样 地址不一样 也是不相等
排序
冒泡排序思路
- 双重for循环
- 外层决定比较的次数 一共需要比较数组的长度-1次
- 内层是每一次的比较,每一次将相邻两项进行相比
+ 如果前一项大于后一项 交换位置 从小到大
+ 如果前一项小于后一项 交换位置 从大到小
选择排序思路
- 双重for循环
- 外层决定比较的次数 一共需要比较数组的长度-1次
- 内层是每一次的比较,每一次找出相对较大或者较小的数 放到数组的对应位置
+ 从小到大 假设第n位是最小的 找出比他更小的数就记录下标 等到循环结束 把第n小的数放到数组的第n位
+ 从大到小 假设第n位是最大的 找出比他更大的数就记录下标 等到循环结束 把第n大的数放到数组的第n位
数组常用方法
-
数组添加数据
- 数组.push(数据) 往数组的末尾添加一个数据
- 数组.unshift(数据) 往数组的开头添加一个数据
-
获取数组的里面数据(这种取出方式会改变原数组的长度)
- 数组.pop() 会取出数组的末尾的数据
- 数组.shift() 会取出数组的开头的数据
-
删除数组的数据
- 数组.splice(开始的下标, 删除的个数)
-
数组的反转
- 数组.reverse()
-
数组的拼接
- 拼接不会改变参与拼接的数组 会返回一个拼接后的新数组
- var 新数组 = 数组.concat(数组01, 数组02, 数组03…)
-
数组拼接成字符串
- var 字符串 = 数组.join()
-
数组的查找方法
- 固定值匹配
-
数组.indexOf(数据)
- 如果数组里面有这个数据 返回第一次匹配这个数据的下标
- 如果数组里面没有这个数据 固定返回-1
- 有满足这个下标不等于-1
- 没有满足这个下标等于-1
-
数组.lastIndexOf(数据)
- 使用方式同上面的indexOf
- 只是查找的方向不一样 indexOf是从数组开始查找 lastIndexOf是从数组的末尾开始查找
-
数组.includes(数据)
- 如果数组里面有这个数据就返回true
- 如果数组里面没有这个数据就返回false
-
- 范围的匹配
- 数组.find()
- 返回符合条件的第一项匹配的数据
// 如果匹配到了数据 就会返回这一项数据 // 如果没有匹配到数据 就直接返回undefined var data = 数组.find(function(item, index){ // item是数组的每一项数据 // index是数组的下标 // 需要返回一个条件 拿每一项和这个条件进行比较 如果条件满足 循环就结束 如果不满足就继续循环 return item>10 })
- 数组.findIndex()
// 如果匹配到了数据 这个数据在数组的下标 // 如果没有匹配到数据 就直接返回-1 var index = 数组.findIndex(function(item, index){ // item是数组的每一项数据 // index是数组的下标 // 需要返回一个条件 拿每一项和这个条件进行比较 如果条件满足 循环就结束 如果不满足就继续循环 return item>10 })
- indexOf和find和findIndex他们的区别
- indexOf和find*的区别一个是固定值查找 一个是范围查找
- find和findIndex 一个找到匹配到数据本身 一个找到是匹配数据的下标
- 固定值匹配
-
数组去重
- 思路参考代码注释
-
数组的排序方法 sort
-
数组.sort()
-
sort底层排序规则按照字符串的规则 不是按照数字排序的规则
-
需要自定义sort的排序规则
- 给sort函数传入一个参数 这个参数是一个函数类型的
- 这个函数里面自带两个参数 a和b a代表后一项 b代表前一项
- sort底层也是冒泡排序
- 从小到大 前一项大于后一项 需要交换位置 不需要我们自己去换 只需要返回一个小于0的数 就会自动给我们去交换位置
- 从大到小 前一项小于后一项 需要交换位置 不需要我们自己去换 只需要返回一个小于0的数 就会自动给我们去交换位置
-
简写的方式
数组.sort(function(a,b){ return a - b }) 数组.sort(function(a,b){ return b - a })
Math
-
-
js内置的一些数学运算的方法
-
js内置对象
-
圆周率
- Math.PI
-
Math的方法
- Math.abs() 绝对值
- Math.pow() 求多少次方
- Math.sqrt() 求平方根
- Math.max() 求最大值
- Math.min() 求最小值
- Math.random() 求随机数
-
Math的取整
- Math.floor() 向下取整 抹去小数位 得到一个比当前数小的整数
- Math.ceil() 向上取整 抹去小数位 得到一个比当前数大的整数
- Math.round() 四舍五入取整 依据小数位 遵循数学上面的四舍五入算法
Date
-
js内置的构造函数
-
主要用于获取本地计算机时间
-
获取年月日时分秒的步骤
- 创建一个日期对象
- var riqi = new Date()
- 利用日期对象获取年月日 时分秒
var year = riqi.getFullYear() console.log(year) var month = riqi.getMonth() + 1 // 月份是从0开始 0代表1月份 1代表2月份 console.log(month) var date = riqi.getDate() console.log(date) var hour = riqi.getHours() console.log(hour) var min = riqi.getMinutes() console.log(min) var sec = riqi.getSeconds() console.log(sec)
- 利用日期对象获取星期几
var week = riqi.getDay() console.log(week) // 星期返回的是一个数字 0代表星期天 1代表星期一
- 创建一个日期对象
-
通用时间格式
- ‘YYYY-MM-DD hh:mm:ss’
- ‘YYYY/MM/DD hh:mm:ss’
设置日期系列的函数
-
日期对象.setFullYear(年份)
- 将当前时间年份替换成你设定的年份 其他的不变
-
…
时间戳
- 含义: 计算机里面有一个人为规定初始化时间
1970-01-01 00:00:00
, 时间戳就是某一个时间距离计算机初始化时间相差的毫秒数 - 1000毫秒数 = 1秒数
- 获取时间戳的方式
- 创建一个日期对象
- var riqi = new Date()
- 利用日期对象的getTime方法获取
- var 时间戳 = riqi.getTime()
- 创建一个日期对象
计算两个时间差值思路:
- 都需要先将这个字符串格式时间转换成日期对象
- 再获取这个日期对象所对应的时间戳
- 在将两个时间戳相减得到差值就是他们相差的毫秒数
- 需要将某个时间往前或者往后一段时间
- 需要将这个时间转换成时间戳
- 再将得到的时间戳加上或者减去这段时间(转换成毫秒数)得到一个这个时间所对应的时间戳
- 再将这个时间戳转化成日期对象
- 利用
new Date(时间戳)
- 利用
new Date().setTime(时间戳)
- 利用
定时器
-
需要控制代码间隔多久执行一次 或者 延迟多久执行一次就需要用到定时器
-
间隔定时器
- 代码每间隔多少毫秒会执行一次
- 间隔定时器也会有一个延迟的效果 第一次不是上来就会执行 会延迟多少毫秒之后才会间隔执行
// 每间隔多少毫秒会调用这个函数一次 var id值 = setInterval(函数, 毫秒数)
-
延迟定时器
- 代码不是立马执行 会延迟一段时间执行
var id值 = setTimeout(函数, 毫秒数)
-
结束定时器
- 每一个定时器在设置的时候都会返回一个id 可以根据这个id去清除所对应的定时器
- 清除间隔定时器
- clearInterval(id值)
- 清除延迟定时器
- clearTimeout(id值)
同步和异步的概念
-
代码的执行的两种方式
-
同步的方式: 代码执行从上往下 如果上面没有执行结束 下面不会执行 如果上面报错 下面也不会执行
- 学到大部分都是同步的方式
-
异步的方式: js会将耗时比较长的或者耗时无法预估的代码当成异步的任务来执行 凡是js遇到异步的代码会直接跳过 得到所有同步的代码执行结束才会执行异步的代码
- 定时器
前端javascript三大组成部分
-
ECMAScript 标准语法 es5
-
DOM (document object model) 文档对象模型
- 主要是利用js来操作网页的
-
BOM(browser object model) 浏览器对象模型
- 浏览器提供一些方法
BOM
-
浏览器提供了一些方法给我们有机会操作浏览器的某一些内容
-
浏览器将他提供的API放在window上面,window是一个对象,里面有很多自带的数据
-
window是一个全局作用域 所有的全局变量和函数也会自动添加到window对象,使用的时候变量或者函数会自动去window查找
-
弹窗
- window.alert()
- alert() 提示框
- prompt() 弹出输入框
- confirm() 确认框
- 这个弹窗仅仅只在自己练习使用 真正开发项目我们需要自己实现弹窗
-
网页的宽度和高度
- window.innerWidth
- window.innerHeight
-
屏幕分辨率宽度和高度
- window.screen.width
- window.screen.height
浏览器事件
- onload 网页加载完成的事件
```js
window.onload = function(){
// 有一些操作需要等待网页加载完成之后才执行
}
```
- onresize 网页尺寸变化执行的事件
```js
window.onresize = function(){
// 每一次网页尺寸变化都会触发这个事件
// 第一次进入的时候是不会触发
}
```
- onscroll 网页滚动条滚动事件
```js
window.onscroll = function(){
// 只要滚动滚动了就会触发
}
```
- 获取网页地址栏相关的信息
- 输入一个网址–>将网址中域名经过DNS解析IP–>找到服务器
- 一个完整的网址组成部分有哪些
- https://wwww.baidu.com:443/home/a/b?kk=1&ll=44&ffs2=44#jaja
- 协议 http:// https:// file://
- 域名 www.baidu.com www.taobao.com
- 端口号 这个一般被隐藏了 但是他确实存在 :数字 [0, 65535]
- 路径 /home/a/b
- 请求参数 ?kk=1&ll=44&ffs2=44
- 哈希值 #jaja
- 一个网址必须包含
协议+域名+端口号
称为 源
location对象
+ 这个对象里面包含了我们需要的所有地址栏的信息
+ 可以通过这个对象获取地址栏每一个部分
* `location.href`: 获取或设置完整的 URL 地址。
* `location.protocol`: 获取或设置 URL 的协议部分,如 "http:" 或 "https:"。
* `location.host`: 获取或设置 URL 的主机名和端口号部分。
* `location.hostname`: 获取或设置 URL 的主机名部分。
* `location.port`: 获取或设置 URL 的端口号部分。
* `location.pathname`: 获取或设置 URL 的路径部分。
* `location.search`: 获取或设置 URL 的查询参数部分,包括 "?" 符号。
* `location.hash`: 获取或设置 URL
+ 刷新
- location.reload()
+ 跳转
- location.assign(跳转的网址)
- location.href = 跳转的网址
- location.replace(跳转的网址)
- 前两种跳转是会生成记录 后一种相当于将当前的记录覆盖掉 不会产生新的访问记录
- history对象
+ 当前页面的访问记录
+ 访问记录长度
- history.length
+ 前进一个历史记录
- history.forward()
+ 后退一个历史记录
- history.back()
+ 前进或者后退几个历史记录
- history.go(数字)
+ 刷新
- history.go(0)
+ pushState和replaceState 这两个方法都会往历史记录添加一个数据 这种操作会改变地址栏的路径部分 但是不会发生跳转(假动作)
- hitory.pushState(stateObj, '', url)
- hitory.replaceState(stateObj, '', url)
+ history.state可以获取当前历史记录堆栈里面存放的数据 这个数据是pushState或者replaceState传递的第一个参数
-
获取滚动条滚动的宽度和高度
- 高度 scrollTop
- 宽度 scrollLeft
- 注意:此处获取的时候有兼容性问题 有可能是body的滚动条 有可能是html的滚动条
- 兼容性获取
- var 高度 = document.body.scrollTop || document.documentElement.scrollTop
- var 宽度 = document.body.scrollLeft || document.documentElement.scrollLeft
-
设置滚动条的高度和宽度
- 设置高度
- document.body.scrollTop = 100
- document.documentElement.scrollTop = 100
- scrollTo方法
- window.scrollTo(x, y)
- x是设置横向滚动条的宽度
- y是设置纵向滚动条的高度
- window.scrollTo({
left: 滚动的宽度,
top: 滚动的高度,
behavior: ‘auto’/‘smooth’
})
- window.scrollTo(x, y)
- 设置高度
-
打开网页窗口的方式
- window.open(url)
-
定时器
- 延迟定时器
- 间隔定时器
-
本地存储
-
可以在浏览器里面存放一个数据 可以存储5M的数据
- b 一个英文占据1b 一个汉字2b
- 1kb = 1024b
- 1m = 1024kb
- g
- t
-
localStorage
- 存数据
- localStorage.setItem(名称, 数据)
- 获取数据
- var 数据 = localStorage.getItem(名称)
- 删除数据
- localStorage.removeItem(名称)
- 清空所有数据
- localStorage.clear()
- 存数据
-
sessionStorage
- 存数据
- sessionStorage.setItem(名称, 数据)
- 获取数据
- var 数据 = sessionStorage.getItem(名称)
- 删除数据
- sessionStorage.removeItem(名称)
- 存数据
-
区别:
- localStorage是永久存储 除非用户手动清缓存数据才会删除
- sessionStorage是会话级别存储 这种存储只要浏览器一关闭 数据就会自动删除
-
跨页面传参
- 通过本地存储localStorage sessionStorage在一个页面存 在另一个页面取
- 通过地址栏传递参数
DOM(document object model)
获取到页面的标签(元素)
- 根据id名来获取
+ document.getElementById(id名)
- 根据类名来获取
+ document.getElementsByClassName(类名)
- 根据标签名来获取
+ document.getElementsByTagName(标签名)
- 通过选择器获取,只会匹配第一个
+ document.querySelector(css选择器)
- 通过选择器获取,获取所有的
+ document.querySelectorAll(css选择器)
操作元素的样式
- 设置元素的样式
+ 元素.style.css属性名 = css属性值
+ 通过js给元素设置的样式都是行内样式
- 获取元素的样式
+ 元素.style.css属性名(只能取到行内的)
+ getComputedStyle(元素).css属性名
操作元素的类名
-
js通过操作元素类名的方式来控制元素的样式
-
获取元素的类名
- 元素.className
- 元素.classList.value
-
设置元素的类名(会覆盖原有的类名)
- 元素.className = 类名
- 元素.classList.value = 类名
-
新增类名
- 元素.classList.add(类名)
-
删除类名
- 元素.classList.remove(类名)
-
判断有没有类名
- 元素.classList.contains(类名)
操作元素的属性
-
目的: 每一个属性都有一些自带的效果
- 改变class 元素的样式就会发生变化
- 改变图片src 图片就会换一张
- 改变超链接href 地址就会发生变化
- …
-
元素的属性: 标签里面的属性
<div id="header" class="box" style="width:100px"></div>
-
原生的属性
- 标签自带的一些属性
- 获取元素自带的属性
- 元素.属性名
- 元素.id
- 元素.style
- 元素.src
- …
- 元素.属性名
- 设置元素自带的属性
- 元素.属性名 = 值
-
获取所有的属性
- var 属性值 = 元素.getAttribute(属性名)
-
设置所有的属性
- 元素.setAttribute(属性名,属性值)
-
data-属性
- data-名称=1
- 获取data系列的属性值
- 元素.dataset.名称
- 设置data系列的属性值
- 元素.dataset.名称 = 值
操作元素的内容
- 获取元素的内容
- 元素.innerHTML(innerHTML设置内容的时候可以识别字符串里面的标签)
- 元素.innerText(innerText设置内容的时候会直接将字符串里面都当成纯文本)
- 设置元素的内容
- 元素.innerHTML = 内容
- 元素.innerText = 内容
操作输入框的属性值
- 输入框 input textarea select…
- 获取属性值
- 元素.value
- 设置属性值
- 元素.value = 值
操作单选框和多选框的勾选状态
- 获取勾选状态
- 元素.checked 如果是勾选的返回true 如果是没有勾选的返回false
- 设置勾选状态
- 元素.checked = 布尔值
绑定事件
- 元素.on+事件类型 = 事件处理函数
box.onclick = function(){
// 要做的事件
}
获取元素的尺寸
- 真实的宽度
- 元素.offsetWidth
- 元素.clientWidth
- 真实的高度
- 元素.offsetHeight
- 元素.clientHeight
获取元素的偏移
- 偏移:元素左上角点相对于页面左上角点的距离就是偏移
- 元素的偏移距离是有两个方向的 一个是距离页面左边的偏移 一个是距离页面上边的偏移
- 左边的偏移量
- 元素.offsetLeft
- 上边的偏移量
- 元素.offsetTop
获取元素左边框和上边框的宽度
- 左边框宽度
- 元素.clientLeft
- 上边框宽度
- 元素.clientTop
DOM操作
利用js来生成、添加、删除、修改、克隆元素
-
创建一个元素
- document.createElement(标签名)
-
添加元素到页面
- 往父元素最后添加一个子元素
- 父元素.appendChild(子元素)
- 往父元素的某一个子元素前面追加一个子元素
- 父元素.insertBefore(新子元素, 旧子元素)
- 往父元素最后添加一个子元素
-
修改元素
- 修改元素的内容
- innerHTML
- innerText
- value
- 替换元素的标签名
- 父元素.replaceChild(新元素, 旧元素)
- 修改元素的内容
-
删除元素
- 父元素.removeChild(子元素)
-
克隆元素
- 要克隆的元素.cloneNode() 只会克隆当前元素
- 要克隆的元素.cloneNode(true) 既会克隆当前元素 也会克隆子元素
DOM事件
-
事件:由用户行为触发的代码
构成三要素
- 事件源 给哪个元素绑定事件
- 事件类型 用户行为 click dblclick...
- 事件处理函数 要执行代码 就是函数
- 绑定事件
- 事件源.on+事件类型 = 事件处理函数
- 添加事件监听的方式
- 事件源.addEventListener(事件类型, 事件处理函数, 执行机制)
- 默认为false 使用是冒泡机制
- 设置为true 使用是捕获机制
- 事件源.addEventListener(事件类型, 事件处理函数, 执行机制)
on方式和addEventListener的区别
1. on方式只能绑定一个事件处理函数 addEventListener可以支持多个事件处理函数
2. 取消事件方式不同
- removeEventListener()
3. 支持的事件机制不一样(后面讲)addEventListener可以支持两种机制
事件对象(event)
-
含义:事件对象是一个在事件处理函数内部 包含了事件触发的时候详细信息
-
获取event
- 每一个
事件处理函数
里面都会自带一个event,这种可能有一些浏览器获取得到是undefined - 每一个
事件处理函数
默认的第一个形参就是event 这种可能有一些浏览器获取得到是undefined
- 兼容性获取
- var evt = event || e
- 每一个
-
event里面四组坐标
- offsetX offseY 鼠标的位置相对于事件源的左上角坐标
- clientX clientY 鼠标的位置相对于浏览器的左上角坐标
- pageX pageY 鼠标的位置相对于页面的左上角坐标 区别是当页面没有滚动条二者重合 有滚动条就可能不一样
- screenX screenY 鼠标的位置相对于屏幕的左上角坐标
-
event判断键盘按下的按键
- 键盘码
- event.keyCode
- 13 回车键
- 32 空格键
- …
- 键盘码
-
判断组合键
- event.ctrlKey
- event.shiftKey
- event.altKey
- 当你按下功能键不松开再按其他键 这一次对应的key的值为true
- 如果单独按下别的键 这个key为false
事件类型
- 鼠标事件
+ click 单击
+ dblclick 双击
+ contextmenu 右击
+ mouseover 移入
+ mouseout 移出
+ mousemove 移动
+ mousewheel 滚轮滚动
+ mousedown 按下
+ mouseup 抬起
- 键盘事件
+ keydown 按下
+ keyup 抬起
- 表单事件
+ 收集用户信息,提交给后端
+ 注意事项
+ submit
- 这个事件给表单(form)绑定 会在表单提交给后端前一刻触发
+ change
- 值变化事件 给表单控件 input select textarea...
+ input
- 输入事件 给带有可以输入内容的输入框绑定
- 只要用户输入就会触发
+ focus
- 获取焦点 给带有可以点进入输入的输入框绑定
+ blur
- 失去焦点 给带有可以点进入输入的输入框绑定
事件执行机制
-
多个嵌套的元素
绑定同类型的事件
,事件执行的先后顺序称为事件的执行机制(事件传播机制) -
分类:
- 冒泡机制: 由当前触发事件的元素一直往上到window 由内向外(目前大部分浏览器所支持的机制)
- 捕获机制: 由window一直往下到当前触发事件的元素 由外向内
利用事件传播机制 实现事件委托
-
事件委托: 某一个元素无法直接绑定事件 需要借助别人绑定事件来实现这个功能
-
一般多用于动态生成的元素
-
如何实现事件委托?
- 给父元素绑定事件 子元素也会有这个事件
- 在通过目标元素event.target来判断是不是这个子元素 只有是这个子元素才会执行某一段逻辑
- 这样的话给父元素绑定 通过event.target缩小触发的范围实现的效果和直接给这个子元素绑定事件是一样
- 通过目标元素身上类名、标签名、id名
- 父元素必须是页面进入的时候就存在 html写的 不是动态生成
-
事件委托还可以提供事件绑定的性能
-
目标元素
- 当前正在触发事件的元素,一个父元素里面有很多子元素 点击子元素会触发父元素的事件 到底是哪个子元素 可以通过目标元素来确定
- 获取当前点击的子元素 event.target
-
获取元素的标签名
- 元素.tagName 标签名的大写
-
已知一个元素 获取他的父元素
- 元素.parentNode
阻止冒泡
- 如果子元素和父元素绑定了同类型的事件, 触发子元素的事件也会触发父元素的事件,如果我们只想触发子元素的事件 不想触发父元素的事件 这个操作就称为冒泡
- 实现冒泡
- 需要在子元素的事件处理函数内部处理
- event.stopPropagation()
阻止默认事件
- 有一些标签自带了一些行为,如果我们利用js给他添加相同行为,默认行为优先级会大于js给他添加,希望我们自己实现js行为生效,让它自带的行为失效,此时就需要进行阻止默认事件
- 默认事件: html标签自带的行为
- 超链接 即使不加点击事件 点击超链接也会进行跳转
- 表单的按钮提交事件
- 实现
- 在事件处理函数内部
- event.preventDefault()
this关键字
- this出现在事件处理函数里面 this代表的是当前的事件源
- 普通函数内部的this看调用
- 箭头函数内部的this看定义
- 可以强制修改一个普通函数内部的this, 有三种方式可以修改一个函数内部的this指向
- call
- 函数名.call(新this的指向, 参数01, 参数02,…)
- apply
- 函数名.apply(新this的指向, [参数01, 参数02, …])
- bind
- var 新函数 = 函数.bind(新this的指向)
- 新函数(参数01, 参数02, …)
- call
- call、apply、bind的区别
- call、apply在改变函数this的同时会调用这个函数 bind只会改变this 不会调用函数 会返回一个修改this之后的新函数 需要自己去调用这个新函数
- call和apply的传参方式不一样
- call第一个参数是修改this之后的指向 如果函数调用的时候需要传递参数 可以接着第二个参数位置开始传递
- apply第一个参数是修改this之后的指向 如果函数调用的时候需要传递参数 参数是在第二个位置传递一个数组 数组里面对应每一项就是之前的参数
es6
- ECMAscript 简称 es 标准语法
- es5
- es1.0 1997
- es2.0 1998
- es3.0 1999
- es5.0 2008 es3.0–>es3.1–>es5
- 2015 年 6 月 es6 官方称呼这个版本es2015
- 2016 es2016 --> es7
- …
- 2023 es2023 --> es14
let和const
-
let是声明变量的一种新方式
-
let和var的区别
- let有块级作用域的概念
- let不会声明提升 var有声明提升(不能提前使用let变量)
- let不允许重复声明(let声明的时候看有没有定义过)
- let有暂时性死区
-
const是声明常量的一种方式
-
const 常量
- 不允许变化的数据
- 值一旦确定就不允许修改 一旦改变 就会报错
- 常量名建议全大写
- 如果这个数据是基础数据类型 只要改变就会报错 针对于复杂数据类型只要你不改变他的地址(引用)就不会报错
- 也有块级作用域的概念
箭头函数
- 定义函数
- es5(普通函数 带function函数)
- 声明式定义
function 函数名(形参,形参){ }
- 赋值式定义
var 函数名 = function(形参,形参){ }
- 声明式定义
- es6 箭头函数
var 函数名 = (形参,形参) => { }
- es5(普通函数 带function函数)
- 箭头函数简写
- 当箭头函数内部的代码
只有一行
的时候 花括号可以省略不写 - 当箭头函数
只有一个形参
的时候 小括号可以省略不写
- 当箭头函数内部的代码
- 箭头函数解决this指向不固定的问题
- 箭头函数和普通函数的区别
- 内部的this指向不一样
- 箭头函数内部this无法修改
- 箭头函数内部没有arguments
- 箭头函数无法当做构造函数
函数默认参数
- 当调用的时候传递了参数 就会以我们传递参数为准 没有传递就会使用默认值
函数的剩余参数rest parmater
- 箭头函数可以利用剩余参数实现普通函数的arguments功能
- 剩余参数 …参数名
- 剩余参数的注意事项
- 一个函数最多只能有一个剩余参数
- 剩余参数必须在所有确定的后面 只能在最后
解构赋值
- 主要用于取出数组或者对象里面的值将它赋值给一个变量
- var [变量名, 变量名, …] = 数组名
- var {键名:别名, 键名: 别名, 键名} = 对象名
展开运算符
...
- 用于合并数组和对象
模块化语法
-
模块: 在项目开发中每一个文件就是一个独立的模块 由多个模块组成一个整体 构成一个项目
-
模块化管理: 将我们独立每一个文件进行整合
-
css模块化
-
js模块化(esm) es6 module语法
- 导入
- 单个导入
import {a, fn} from '路径'
- 默认导入
import 变量名 from '路径'
- 导出
- 单个导出
export var a = 1 export const fn = ()=>{}
- 默认导出
export default { aaa: 1, fnn: ()=>{} }
- 导入
-
Cannot use import statement outside a module
导入了一个js 这个js用到了import命令 这个命令浏览器是不识别的 需要告诉浏览器 我是使用了import命令 你要帮我解析 在加载这个js的script标签里面添加一个type=module
-
Access to script at 'file:///D:/%E6%95%99%E5%AD%A6/2302/week03/day04/%E4%BB%A3%E7%A0%81/js%E6%A8%A1%E5%9D%97%E5%8C%96/index.js' from origin 'null' has been blocked by CORS policy: Cross origin requests are only supported for protocol schemes: http, data, isolated-app, chrome-extension, chrome, https, chrome-untrusted.
一旦开始type=module模式 本地打开的网页不支持 需要在服务器环境打开这个页面 需要安装live server利用live server打开这个页面即可 -
虽然此时我们已经可以成功在一个js里面加载另一个js 但是注意每一个js都相当于是一个独立的作用域 单纯的导入只是将文件执行了 并不能说就能够使用导入文件里面的数据
-
如果我们想要使用导入文件里面的数据 就要导入文件要导出 在数据前面加上
export
就导出了这个数据 -
导入的时候需要接受数据
作用域
-
es5作用域
- 全局作用域
- 局部作用域
-
es5变量
- 全局变量
- 局部变量
-
es6作用域
- 全局作用域
- 局部作用域
- 块级作用域
- 花括号内部
-
es6变量
- 全局变量
- 局部变量
- 块级变量
- 在块级作用域里面用
let声明
的变量被称为块级变量 块级变量只能在当前块级作用域内部使用
- 在块级作用域里面用