java script
js基础
1.简介
是什么
- 运行在浏览器中的一种编程语言(html,css是一种标记语言)
组成
- ECMAScript:语言基础
- Web APIs:由Dom (页面文档对象模型,操作文档)和Bom(浏览器对象模型,操作浏览器)组成
- MDN网站:搜索每个标签的效果
2.书写位置
-
内部:写在script标签中,写在< /body >上面,内容的最下面(有一定的顺序)
-
外部(script中间不可以写内容,因为会被忽略)

-
内联/行内(在vue框架中会使用这种模式)
点击提交按钮后出现

3.怎么写
注释
- 单行注释 //
快捷键:ctrl+/ - 块级注释 /* */
快捷键:shift + alt + a
结束符
- 英文的;代表这句语句结束,不是必要的,浏览器会自动识别语句结束
4.输入和输出的语法
- 括号中是汉字的话一定要加单引号
输出语法
| 语句 | 作用 |
|---|---|
| document.write | 在浏览器页面中显示文字 |
| alert | 网页弹窗 |
| console.log | 在控制台输出语句 |
-
document.write(‘’)
-
作用:在浏览器页面中显示文字

-
alert(‘’)
-
作用:网页弹窗

-
console.log(’ ')
-
在控制台输出语句,用于程序员调试程序

输入语法
| 语句 | 作用 |
|---|---|
| prompt | 网页弹窗 |
- prompt(’ ')

- 代码按照文档流的顺序依次执行
- alert和prompt会优先于其他执行
5.字面量
- 含义:在计算机中,描述事/物
eg.
100:是数字字面量
‘你好“:是字符串字面量
[ ]:数组字面量
{}:对象字面量
6.变量(variable)
-
含义:用来存储数据的容器
-
不加引号
-
var声明变量:函数作用域,可重复声明(覆盖)
-
let声明变量:块级作用域,不可重复声明
-
const声明常量:块级作用域,不可重复声明,必须初始
-
暂时性死区:变量的作用域中,从代码块开始 到变量声明之前,都属于暂时性死区
-
紫框中的内容就属于变量a的暂时性死区

| 作用域 | 提升行为 | 重复声明 | |
|---|---|---|---|
| let | 块级作用域 | 非提升 | 不可 |
| const | 块级作用域 | 非提升 | 不可 |
| var | 函数作用域/全局作用域 | 可提升,但是返回值为undifined | 可 |
变量的初始化
- 1)let 变量名
2)变量名(标识符) = 字面量 - 声明变量时也可以同时赋值

- 两个变量要分别输出,有汉字一定要加单引号

更新变量
- 一个相同的变量只允许声明一次,如果想重新赋值,直接 变量名 = 字面量 即可

多个变量声明
- 可以这样写,但不提倡

在页面中输入姓名,并且在页面中显示
- 逻辑:输入内容、存放变量、输出内容

- 控制台中的错误提示

变量交换

严格定义
- 内存:用来存放数据的一个大空间
- 变量:在内存这个大空间中的一个小空间
命名规则与规范
规则(必须遵守)
- 只可以用英文字母、数字、下划线、¥组成,且数字不能开头
- 字母严格区分大小写
如age、AGE、Age是三个不同的变量
规范
- 起名要有意义
- 小驼峰命名法:组合单词第二个单词的首字母大写
如:myName
多个变量输入

变量拓展
- var在使用时的缺点
1)var可以先使用,再声明
2)var声明过的变量可以重复声明
3)等等
7.常量
- 用const声明的变量,这个值永远不会改变,不可以再次赋值
- 常量声明的时候必须赋值

8.数据类型
- js属于弱数据类型,即定义后才知道其数据类型
数字类型(number)
- 所有的数字,包括整数、小数等
NaN
- not a number 代表输出错误

字符串类型(string)
-
字符串:由数字、字母、符号等单独组成或混合组成的 一串字符
-
凡是使用双引号、单引号、反引号包裹起来的都叫做字符串,单引号和双引号没有本质区别
-
变量不可以加引号
-
引号可以嵌套(外双内单,外单内双)
-
数字可以不加引号,若添加引号,计算机会将这串数字按字符串处理,此时数字将仅仅作为一个文本使用
1)’ 3 ’ + ’ 2 ’ = ’ 32 ’
两个字符串数字相加,实现的是两个数字的拼接,不止是数字,字母和汉字也可以
2)’ 3 ’ + 2 = 32
一个数字字符串和数字将加减,数字会被自动识别为字符串
模板字符串
- 作用:拼接字符和变量
- 写法:

布尔类型(boolean)
- 作用:表示肯定或否定
- 只有两个值true或者false

未定义类型(undefined)
- 应用场景:如果显示值是undefined,就说明值没有被传送过来

空类型(null)
- 含义:空的、没有、值未知

拓展:存储方式
1)简单数据类型
-
又叫做基本数据类型或值类型
-
在存储时,存储的是一个值
2)复杂数据类型
- 又叫做引用类型
- 在存储时,存储的是一个地址
const a = {name:'佩奇'}
a:变量名
name:属性名(/键名)
佩奇:属性值(/值名)
{name:'佩奇'}:对象字面量
3)栈堆空间分配
- 栈,存储简单数据类型,存储引用数据类型的地址
- 堆,存放引用数据类型的值

9.检测数据类型
- 写法:
1)运算符(typeof 变量名)
2)函数 (typeof (变量名))

10.类型转换
- 原因:js是弱数据类型;表单、输入框转化过来的类型都是字符串类型
隐式转换
- 某些运算符执行时,浏览器自动将类型转换
- +两边只要有一个是字符串,另一个自动转换为字符串
- 减、乘、除都会把数据转换成数字类型
- 小技巧:
1)+作为正号时,可以转换为数字类型
2)任何数据和字符串相加,结果都是字符串

显式转换
- 数字类型是蓝色字体,字符串类型是黑色字体
- Number


- parseInt

- parseFloat

两数之和

表格中打印数据

运算符
- 乘 除 取余(%) 加 减
- 乘 除 取余优先级相同
赋值运算符
- =:将右边的赋值给左边的
- +=
num += 3:num = num + 3(num自加3)
一元运算符
- 只需要一个表达式就可以运算
如:正负号
let i = 1
console.log(++i)
结果是2
console.log(i++)
结果是1,执行完i++后,i的值变为2,如果后面还有一个表达式,如i + 1,那么就是2 + 1 = 3
console.log(++i + 1)
结果是3
console.log(i++ + i)
结果是3当i++执行完,再自增
比较运算符
- 也存在隐式转换
- ==:只判断值是否相等
- == =:全等号,判断值和类型
以后判断相等,用=== - 返回结果只有两个true或false
逻辑运算符
- 符号
&&:逻辑与 一假则假
||:逻辑或 一真则真
!逻辑非 真变假,假变真
判断并页面弹出结果

优先级

- 一元运算符中逻辑非优先级很高

表达式
- 可以被求值的代码
语句
- 一段可以执行的代码,不一定有值
分支结构
- 根据条件选择执行语句
顺序结构
- 从上到下依次执行
if分支
- 用于分支较少的情况
单分支
if (条件){
满足条件所要执行的代码
}
- 括号中的条件只有两个值:true / false,若括号中不是布尔类型,那么浏览器会自动将语句转化为布尔类型,比如3 > 5,为false
- 括号中的若为数字,除了0以外,其他数字均为真
- 除了空字符串,其他均为真
双分支
if (条件){
满足条件所要执行的代码
} else{
满足条件所要执行的代码
}
多分支
if (条件){
代码1
} else if (){
代码2
}else{
代码3
}
- 执行完一个语句就退出
三元运算符
-
语法:条件?满足条件执行的代码:不满足条件执行的代码
-
可以在输出语句中使用,也可以在变量赋值语句中使用
-
也可以作为一个表达式存在于赋值运算符的右边

-
意义相同

switch分支
- 用于分支较多的情况
switch(数据1){
case 值1:
break
case 值2:
break
default:
}
- 找到与数据1全等(===)的值
- break:跳出此次循环,若没有,则会发生case穿透(全部打印一遍)
case后面可以不加括号
如果是输入语法接过来的那么需要转换成数字类型或者将case中的转为字符串类型

判断并页面弹出结果
- 简易计算器

循环结构
- 重复执行的语句
断点调试
- 方法:
1)打开调试工具

while循环
- 不明确循环次数时
- 三要素
1)变量起始值
2)终止条件
3)变量的变化量 - 当条件不满足时,直接退出循环
打印出10个

当一次循环执行完以后,会重新回到while那一行,判断i自增1后是否符合循环条件,如果符合,继续循环
- 输出累加总和,将总和的输出语句放在循环语句的外面,意思是循环结束后再输出,如果将输出语句放在循环里面,那么会将每一次循环得出的sum均输出

输出偶数的和
- 需要先利用if判断语句将偶数筛选出来

一直弹出对话框
- 将网页弹窗的语句写进whille循环中

循环结束
break
- 结束整个循环

continue
- 结束本次循环
i会以3值继续进行循环,但是当i=3时,结束此次循环,下面的代码不再执行,所以会进入一个死循环,因此i++需要放在continue的上面

简易ACM
- 将存款初始值放在循环外面,如果放在循环里面,那么每次循环时存款值会刷新
- 4不可以放在switch里面,if中的break是跳出while循环,switch中的循环是跳出这个switch

for循环
- 明确循环次数时,建议用for
for(变量初始值;变量结束条件;变量变化量){
循环体
}
循环数组
- 换行
- i的结束条件也可以写<= arr.length - 1

- 不要在循环外面给变量赋初值,不然每次循环时,变量的值就会初始化
循环嵌套
- 内层循环执行完外层循环才会开始第二轮
for(i = 1 ; i < 4 ; i++){
for(j = 1 ; j < 6 ; j++){
}
}
换行显示

打印直角形状

九九乘法表

数组(array)
-
作用:一个变量可以存储多个值
-
写法:数组名 = [数据1,数据2,数据3…]
-
输出的值可以是某个值也可以是全部(arr)
-
索引/下标:数组是有序的,每个数组都有自己的编号
-
数组的编号从0开始
-
数组中可以为任何数据[ ‘小明’,1]

-
遍历数组

数组的长度
- 长度=索引号+1

数组求和并求平均值

求最大值
- 引入一个max,先假设最大值就是第一个元素,再将max与其他元素逐个比较

数组操作
- 增:
let arr = [ ]
arr [ 0 ] = 1
arr [ 1 ] = 2 - 删:
- 数组名.pop()
删除数组中的最后一个元素,返回值是删除的元素 - 数组名.shift()
删除数组中的第一个元素,返回值是删除的元素 - 数组名.splice(起始位置–索引号,删除元素个数)
指定删除数组中的第几个元素,包括起始位置的元素,如果不写个数,默认将起始元素及其后面的元素均删掉
-改:
1)给单个元素添加
arr [ 0 ] = ‘修改后的内容’(引号视情况而定)
2)给每个元素添加内容,遍历数组
arr[ i ] = arr [ i ] + ‘内容’(引号视情况而定) - 查:
浏览器的调试功能
新增
- arr.push(‘’,‘’,‘’····)
在原数组后面添加新的元素,返回的是数组长度

- arr.unshift(‘’,‘’,‘’···)
在原数组前面添加新的元素,返回的是数组长度

筛选并组成新数组

柱状图
- 只写其中一个柱子即可
- 外部大盒子的头和尾不用参与循环

冒泡排序

数组排序
升序
//a - b为正数
arr.sort(function (a,b){
return a - b
})
降序
//a - b为负数
arr.sort(function (a,b){
return b - a
})
函数
- 执行特定任务的代码块
- 作用:实现代码复用
//声明函数
function 函数名(){
函数体
}
//调用函数
函数名()
复制多个99乘法表

函数命名规范

函数传参
function 函数名(形参){
函数体
}
函数名(实参)
- 形参(形式上的参数):只在函数内有效,不需要声明
一个范围内的求和

- 当没有实参时,结果会出现NaN,形参默认值时undifined

- 为避免结果出现NaN的情况,可以给形参赋予一个初始值

数组求和
- 实参传给形参的是一个数组
- 形参写成arr = [ ],可以防止函数报错

实参是变量

函数返回值
返回一个值
- 含义:函数执行后的结果是调用者想要拿到的
return 数据
-
return可以作为函数结束的标志,其下面的内容不再执行
-
return后面的数据不可以换行写
-
若没有return,函数的返回值默认是undefined
-
return将x + y返回到a(),即a()=x + y
-
可以将返回值再次声明一下,方便后续使用

返回多个值
return [数据,数据···]
常见问题
- 如果声明了来了两个相容的函数,实行覆盖性原则
- 实参与形参不匹配
实参多于形参,从左往右依次赋值,剩下的没有用
实参少于形参,NaN
作用域
- 含义:限定函数中出现的名字的可用性的代码范围
全局作用域
- 全局变量:函数以外的let变量,在任何区域内都可以访问和修改
局部作用域
- 局部变量:函数中的let变量,只能在当前函数内部访问和修改
- 形参可以看作是局部变量
当函数内部的变量没有声明时,也可以作为全局变量使用,强烈不推荐!!!当外部和内部同时存在相同变量赋值时,遵循覆盖性原则,会出现紊乱
不同作用域下命名冲突
- 采用就近原则,输出在哪个定义域中就执行哪个,若当前作用域中没有,就往上一层作用域中找

匿名函数
函数表达式
let fn = function(){
函数体
}
//函数调用
fn()
- 函数表达式与具名函数的区别
函数表达式的调用必须写在函数的下面,具名函数可以写在除了函数内的任何地方
立即执行函数
//写法一
(function(形参){
函数体
})(实参)
//写法二
(function(){
}())

简易计算器

逻辑中断
-
&&
1)在逻辑与判断中,一假则假,若左边是假,那么右边就不再看了
2)两侧都为真,以最后的真为主 -
||
1)在逻辑非判断中,一真则真,若左边是真,那么右边就不再看了
2)两侧都是真的,取第一个真 -
转换为布尔型
1)"、0、undefined、null、false、NaN转换为布尔值后都是false,其余则为true
2)隐式转换

对象(object)
- 含义:js中的一种数据类型,无序的数据的集合
- 特点:详细的描述某个事物,无序的数据的集合
使用
声明
let 对象名 = { }
//{}里面是对象字面量
组成
属性:特征
方法:功能
let 对象名 = {
属性名:属性值,
方法:函数
}
应用
- 查
1)第一种写法
对象名.属性名
作用:获取函数中的变量
2)第二种写法(属性名中有字符串)
对象名['属性名']

- 改
对象名.属性 = 新值
- 增
对象名.新属性 = 新值
- 删
delete 对象名.属性
方法
- 组成
方法名:函数{
函数体
}
//调用
对象名.方法名()
- 多个方法之间要用,隔开

遍历对象
- 不提倡遍历数组,因为k是字符串
for(let k in 对象名){
console.log(k)//获得属性
console.log(对象名[k])//获得对象值
}
- k=‘num’

数组对象嵌套

与表格结合
- table将js的内容也包裹住,写在表头的下面
- 将表格除表头外的内容放在输出的语句中

内置对象
- 含义:js内部提供的对象
eg.document.write()
Math
- 作用:在js中可以使用数学方法
Math.属性名()

- math.random
随机刷新[ 0~1 )之间的数 - 随机刷新[ 0~10 )之间的整数(上限是几就乘几加1)

随机抽取数组中的一个元素

- 随机生成一个范围内的数


随机抽取数组中的一个元素,且不重复显示

随机抽取一个数,猜数

随机抽取一个数,猜数,设置猜的次数
- 引入一个“开关”
- 逻辑:在前三次机会中,按照循环中的条件判断输出语句,超过三次不正确,循环结束,执行循环下面的if语句,如果三次之内就正确,那么flag被重新赋值,循环下面的if语句就不会执行

根据布尔值输出颜色类型

APIs
- 网页交互效果
- 使用js去操作html和浏览器
1.获取元素
| 方法 | 状态 |
|---|---|
| querySelector | 静态 |
| querySelectorAll | 静态 |
| getElementById | 静态 |
| getElementsByclassName | 动态 |
| getElementsByTagName | 动态 |
| getElementsByName | 动态 |
//querySelectorAll和getElementsByTagName的区别
(1)前者静态,后偶偶这动态
(2)前者可以通过任意的CSS选择器获得元素,后者只可以通过标签获得元素
- 尽量先使用const声明一个量,如果后面发现这个值需要改变,再将其换为let
- let可以换为const,因为只是在原来的基础上进行了修改,并没有改变地址

- 不可以改为const,因为对数组重新赋值,“堆”中的值发生了改变,意味着“栈”中的地址发生了改变


DOM
- Document Object Model一文档对象模型
- 操作网页的内容,可以开发网页内容特效和实现用户交互
DOM树
- 作用:直观的体现文档中标签与标签的关系
DOM对象
-
div在html里面叫标签,用js获取过来就叫做DOM对象
-
document对象:DOM树中最大的一个对象,网页所有的内容都在document里,其次是html对象
获取DOM元素
用CSS选择器的方式获取
//一定要加单引号
//只匹配第一个元素
document.querySelector('CSS选择器')
//匹配所有的,以数组形式输出
document.querySelectorAll('CSS选择器')

- document.querySelectorAll(‘CSS选择器’)
输出结果是一个伪数组
1)有长度有索引值
2)没有pop(),push()等属性
输出每一个
- All才有数组的特性

操作元素内容
- innerText属性
- 不会识别内部标签属性

- innerHTML属性
与上面写法相同,但是可以识别标签属性

随机抽奖

操作元素属性
常用属性
对象.属性 = 值

样式属性
style类型
- 适用于修改样式比较少的情况
- 添加的样式以行内样式展现,会覆盖掉原先的类选择器样式,行内样式权重最高
对象.style.属性名 = ''
//属性名若为多个单词组成,采用小驼峰命名法,backgroundColor
随机调换背景图片
- 如果对象是body,那么更换时直接写成
document.body.style.属性名

className类型
-
同时给一个标签添加多个样式
-
元素.className = '类名' -
如果div之前有一个类名,新值会覆盖旧值
-
如果想保留原来的旧值
'原类名 新类名'

classList类型
属于三个方法,一定加()
//追加一个类名
元素.classList.add('类名')
//删除一个类名
元素.classList.remove('类名')
//切换一个类名
元素.classList.toggle('类名')
//检验一个类名
元素.classList.contains('类名')
-
toggle:有就加上,没有就删掉
-
contains:有就返回true,没有就返回false
表单元素属性
-
innerHTML得不到表单里的内容
-
修改表单里的内容
表单.value = '内容' -
修改表单的样式
表单.type = 'password' -
一律使用布尔值来表示,true表示添加表单属性,false表示移除
-
ipt.checked后面的值只要不是空,就都为真,但是不提倡

-
disabled:失去能力的,如果为true,则失去功能

自定义属性
- 属性以data开头
- 在DOM对象上一律以dataset对象方式获取
- dataset:数据集合

- 获取具体的值(id这两个字母可以随意定义)

定时器-间歇函数
-
间歇函数
每隔一段时间自动执行代码 -
开启定时器
//匿名函数
setInterval(函数,间隔时间)
//有名函数写函数名,没有()
作用:每隔一段时间,调用一次函数
时间单位:毫秒
1s = 1000ms
- 关闭定时器
let 变量名 = setInterval(函数,间隔时间)
clearInterval(变量名)
按钮开关

轮播图自动播放
-
第一个li上的active不可以删除
-
循环滚动的判断条件一定要写在i++的后面

事件监听
- 监测是否有事件发生,如果发生,会产生什么影响
- 例如:搜索框关键字提示,二级菜单等
//现在写法
元素对象.addEventListener('事件类型',要执行的函数)
//传统写法
元素对象.on事件类型 = function () {}
- 同时写了多个相同样式会根据写的顺序先后执行,不会覆盖
- 三要素
1)事件源:获取DOM元素
2)事件类型:鼠标点击、经过等
3)函数:需要做的事情,一定条件下才可以执行
关闭广告
- 外面的盒子和X都需要声明
- 添加属性的时候要加‘ ’

随机点名
- 事件监听 套用 间歇函数

事件类型
鼠标事件
| 类型 | 效果 |
|---|---|
| click | 点击 |
| mouseenter | 鼠标经过 |
| mouseleave | 鼠标离开 |
mouseover和mouerenter的区别:
mouseover有事件冒泡,mouseenter没有事件冒泡
- 利用js自动调用点击事件
- 一定要加(),类似于函数调用
元素对象.事件类型()
轮播图完整版
- 如果两个部分有相同的内容,可以设置一个函数,将相同的部分放入函数中,直接调用

焦点事件
- 表单获得光标
| 类型 | 效果 |
|---|---|
| focus | 获得焦点 |
| blur | 失去焦点 |
- .search的作用是重新定义了一个类选择器,与type=‘search’没有关系,只是为了‘见名知义’

键盘事件
- 检测键盘按下的按键
| 类型 | 效果 |
|---|---|
| keydown | 按键按下触发 |
| keyup | 按键抬起触发 |
文本事件
-
表单输入触发
-
类型:input
-
value属性,显示文本框中的内容

-
依次输出输入的内容

文本域识别文字长度
- 字符串是有长度的
元素名称.value.length

事件对象
- 这个对象中有事件触发的关键信息
- 使用场景:
1)判断用户按下了哪个键,如回车键发布信息
2)判断用户鼠标点击了哪个元素
事件对象获取
元素对象.addEventListener('事件类型',function(e){})
//e就是事件对象

事件对象常用属性
| 属性 | 效果 |
|---|---|
| type | 获取当前事件类型 |
| clientX/clientY | 光标相对于浏览器可见窗口左上角的位置 |
| offsetX/offsetY | 获取光标相对于当前DOM元素左上角的位置 |
| key | 用户按下的按键 |
-
screen,page,client的区别
client:可视窗口
page:整个文档
screen:电脑屏幕
eg.如果浏览器没有占满屏幕,且向上滚动了100px,点击浏览器的左上角
client:(0,0)
page:(0,100)
screen:(80,50) -
key
-
回车键:Enter

发表评论
- 空字符串判断时,全等号两边任选一个写即可

trim方法
- 作用:去除字符串两端的空格



环境对象
- 指的是函数内部一个特殊的变量this,代表当前函数运行时所处的环境

- 粗略规则:谁调用this,this就指向谁

回调函数
- 如果将函数A做为参数传递给函数B时,我们称函数A为回调函数(回头调用)
eg.计时器、事件监听
Tab栏切换
- .item.active选中的是同时包含这两个类名的标签

全选
- :checked伪类选择器


事件流
- 事件完整执行过程中的流动路径(往返)
- 捕获阶段(大—小),冒泡阶段(小— 大)
捕获阶段
- 从根元素开始去执行对应事件(从外到内)
冒泡阶段
- 当一个元素事件被触发时,同样的事件将会在该元素的所有祖先元素中依次被触发。
- 默认情况下存在
- 儿子—爸爸—爷爷

阻止冒泡
-
将事件限制在当前元素内
-
获取到事件对象
-
事件对象.stopPropagation
阻止事件流动,包括捕获
阻止默认行为
- 一个链接一定会跳转
事件对象.preventDefault()
解绑事件
- 本质:移除之前为元素绑定的事件处理函数
- 匿名函数无法解绑
function 函数名(){
}
对象名.removeEventListener('事件类型',函数名)
事件委托
- 引入:A—B
引入一个中间委托人C,A—C—B - 优点:减少注册次数,提高程序性能
- 原理:事件冒泡
给父元素注册事件,触发子元素时,会冒泡到父元素身上
点击li,文字变色


Tab栏切换
- 注意数字类型

其他事件
页面加载事件
-
加载外部资源(图片,CSS,JS)加载完毕时触发的事件(代码从上往下执行,如果将script写在body上面,则会识别错误)
-
事件名:load(加载)
-
(1)监听页面所有资源加载完毕,再执行回调函数
window.addEventListener('load', function () {})
//不仅仅可以写window,也可以针对特定的元素

- (2)不需要等待页面中的图片等加载完成
document.addEventListener('DomContentLoaded', function(){})
页面滚动事件
-
事件名:scroll
-
监听整个页面滚动
window.addEventListener('scrool', function () {})
//也可以针对某个特定元素
获取位置
-
属性:scroolTop / scroolLeft
-
scroolTop:顶部被卷去的距离,得到的是数字型数据,不带单位,可读写

-
页面滚动,实际上是标签滚动

-
指定位置显示和隐藏

-
可赋值
-
页面的滚动条会自动向上滚动这些距离

页面尺寸事件
- 在页面尺寸改变的时候触发事件
window.addEventListener('resize', function () {})
获取元素可见部分宽高
-
不包含边框,margin,滚动条等
-
clientWidth / clientHeight

元素尺寸与位置
尺寸
-
offsetWidth / offsetHeight
-
获取元素的自身宽高,包含元素自身设置的宽高、padding、border
-
获取出来的是数值
-
获取的是可视宽高,如果盒子隐藏,则结果为0
位置
(1)
-
offsetLeft / offsetTop
-
是只读属性,不可以进行赋值操作
-
以最近的有定位的父级元素为参照物,如果父级都没有定位,则以文档左上角为准
顶部导航滑块效果

(2)
-
element.getBoundingClientRect()
-
是一个方法,获得的位置是相对于视口来说的,即眼睛可以看到的
-
作用对象是DOM元素,client的作用对象是事件对象,e.target.clientX这种写法是错误的
e.clientX写法是正确的
电梯导航


日期对象
-
含义:用来表示时间的对象
-
作用:可以得到当前系统的时间
实例化
-
在代码中发现了new关键字时,一般将这个操作称为实例化
-
获得当前时间
const date = new Date()
- 获得指定时间
const date = new Date('2000-1-1')
时间对象方法


显示当前时间
- 方法一

- 方法二

时间戳
-
作用:计算倒计时
-
是指1970年01月01日00时00分00秒起至现在的毫秒数,是唯一的
-
将来的时间戳-现在的时间戳 = 剩余时间毫秒数
-
获取时间戳的方法
1)date.getTime()
2)+new Date()
3)Date.now()
第三种不需要实例化,第二种方法既可以返回当前的时间戳,也可以返回以前的时间戳

倒计时

节点操作
DOM节点
- DOM树里面的每一个内容
- 节点类型:
1)元素节点:body、div,html是根节点
2)属性节点:所有的属性。href
3)文本节点:标签里面的字
查找节点
- 根据元素之间的关系来查找,使用的是属性,因此后面都不需要加()
父节点
子元素.parentNode
多个广告窗口关闭

子节点
-
父元素.childNodes
可以获取父元素中所有子节点,包括空白文本 -
父元素.children
仅获得所有元素节点,得到的是伪数组,得到的是亲儿子,亲儿子里面的内容也会一并或获取过来
兄弟节点
- 上一个兄弟节点
元素名.previousElementSibling - 下一个兄弟节点
元素名.nextElementSibling
增加节点
- 1)创建一个新的节点
2)把创建的新的节点放到指定元素内部
创建节点
-
创造出一个新的网页元素,再添加到网页内
-
元素节点
document.createElement('标签名') -
追加节点
//插入到父元素的最后一个元素
父元素.appendchild(要插入的元素)
- 在body(document.body)里面添加一个元素,添加的元素位于script的下面,body的最后

//插入到父元素中某个子元素的前面
父元素.insertBefore(要插入的元素,在哪个元素前面)

克隆节点
元素.cloneNode(布尔值)
true:包含后代节点一起克隆
false:默认值,只克隆标签

删除节点
- 必须通过父元素来删除子节点
父元素.removeChild(要删除的元素)
M端事件
触屏事件(touch)
-
也叫做触摸事件
-
touch对象代表一个触摸点。触摸点可能是一根手指,也可能是一根触摸笔。
-
触屏事件可响应用户手指(或触控笔)对屏幕或者触控板操作。
| touch事件 | 含义 |
|---|---|
| touchstart | 手指触摸到一个DOM元素时触发 |
| touchmove | 手指在DOM元素上滑动时触发 |
| touchend | 手指离开一个DOM元素时触发 |
js插件
- 含义:别让人写好的代码,我们复制直接用

- 第一个网址,文件下载好后,css和js文件在package里面
- 步骤:
1)下载文件
2)找到js,css文件
3)引入js,css文件
4)将想要的内容的源代码复制粘贴
5)进行想要的修改
学生信息表
- 对数据的增删改查
- 有多个数据,数据是成组添加的,因此,将每个人的数据作为一个数组对象添加到数组里面去
- 提交事件: 会自动跳转,需要阻止默认行为,对象是表单(form)本身,提交按钮是为了触发提交事件1
Windows对象
BOM
- Browser obiect Model浏览器对象模型
- Windows对象包含:navigator、location、document(DOM)、history、screen
- 所有通过var定义在全局作用域中的变量、函数都会变成window对象的属性和方法


定时器-延时函数
- 让代码延迟执行
setTimeout(回调函数,等待的毫秒数)
- 仅执行一次,平时省略window
- 清除延时函数
clearTimeout(函数名)

js执行机制
-
1)从上往下执行
2)js解析器,浏览器的两个引擎
1.渲染引擎(渲染html,css)
2.js解析器(解析js) -
js:单线程,等同于一个事件只可以做一件事
-
浏览器可以执行多线程
-
利用多核CPU的计算能力,HTML5提出Veb Worker标准,允许JavaScript脚本创建多个线程。于是,JS中出现了同步和异步。
-
同步:前一个任务结束后再执行后一个任务,程序的执行顺序与任务的排列顺序是一致的、同步的
-
异步:在做一件事时,这件事执行的时间很长,可以去做另一件事
-
同步任务:都在主线程上执行,形成一个执行栈
-
异步任务(耗时的任务):通过回调函数实现,添加到任务队列里
类型:
1)普通类型:click
2)资源加载:load,error
3)定时器 -
执行机制
1)分类:同步任务—执行栈,异步(耗时)任务—任务队列
2)先执行执行栈中的任务,都执行完后,任务队列中的任内务进入到执行栈中执行 -
由于主线程不断的重复获得任务、执行任务、再获取任务、再执行,所以这种机制被称为事件循环(event loop)。
location对象
- 是window里面的一个对象,‘ window ’可以省略
- 跳转页面
location.href = ‘ 网址 ’
5s自动跳转页面

- 获取?后面的地址
location.search

- 获取#后面的地址
location.hash

常用属性和方法:
刷新:location.reload()
强制刷新:location.reload(true)

navigator对象
navigator.userAgent
检查浏览器打开的计算机(pc/安卓/苹果)的型号
history对象
- 主要管理历史记录
| 方法 | 功能 |
|---|---|
| back() | 后退功能 |
| forward() | 前进功能 |
| go(参数) | 正数:前进;负数:后退 |

本地存储
- 特点:
1)将数据存储到浏览器(/硬盘)中
2)刷新不会丢失
3)容量较大sessionStorage和localStorage均约为5M
localStorage
-
作用:将数据存储到本地(用户自己的电脑),除非手动删除,否则就算关闭也会永久存在
-
特点:
1)同一浏览器可以多窗口共享
2)以键值对的形式存储
增删改查
- 本地存储只可以存储字符串,数字也以字符串的形式存在
localStorage.setItem('key','value')
不加引号会被解读为变量,key始终带着引号,值在复杂数据类型中是变量

- 手动删除,因为图片中是先打印了一遍之后再删除,所以在控制台依旧会显示‘uname’

- 修改数据与增添数据的写法一样,没有这个‘键’就是增,有这个‘键’就是改
sessionStorage
- 关闭浏览器,数据消失
- 特点:与localStorage用法相同
存储复杂数据类型
- 将复杂数据类型转换为JSON字符串类型
JSON.stringify(value) - 将JSON字符串转换为对象
JSON.parse(localStorage.getItem('key '))
拼接字符串
- map()方法和join()方法
map()
- 作用:遍历数组处理数据,并且返回新的数组
- 与forEach的区别:map有返回值,forEach没有返回值
- map也可以省略index
数组名.map(function(ele,index){
console.log(ele) //打印数组元素
console.log(index) //打印所引号
return ele
})

- 如果是复杂数据类型,数据以JOSN字符串的形式存储到本地,用JSON.parse()的方法转换回对象数组(装着对象的数组)的形式
join()
-
作用:将数组中的所有元素转换成一个字符串

-
使用逻辑或判断符可能会导致解析失败,导致arr不是数组,map遍历时会出现错误

-
!!!最好不要将变量名命名为Date,因为Date是内置对象名

-
正确的数组写法

-
提交事件:提交后页面会刷新,需要阻止这一行为
-
提交事件是提交一次,就对数据进行一次渲染,如果写在外面那么就只会渲染一次

-
为什么刷新页面本地存储的数据没有被删除,页面中的数据却被删除了
1)没有触发渲染函数,需要在代码的结尾再次调用render()函数
2)事件委托中的函数调用是在特定事件(submit)触发时才调用,而刷新并不会触发这个事件 -
先进行渲染操作,目的是为了让用户看到结果

正则表达式
-
匹配字符串中字符组合的模式,是一种对象
-
作用:
1)表单验证(匹配)
2)过滤敏感词(替换)
3)提取字符串中我们想要的部分(提取)
检测查找的方法:
test()
- 判断是否有符合规则的字符组合
const str = '1,2,3'
const reg = /2/
console.log(reg.test(str))
返回值是true/false
exec()
-
检索是否有复合规范的字符组合
-
返回值是一个数组,如果没有复合规则的字符组合,返回值为null

元字符
- 具有特殊含义的一类字符
eg.abcdefg… = [a-z]
边界符
| 符号 | 含义 |
|---|---|
| ^ | 以谁为开头 |
| $ | 以谁为结尾 |
- 当^和$同时存在时,只有当字符组合是/ /里的内容才返回true

量词
- 设定某个模式出现的字数
| 符号 | 含义 |
|---|---|
| * | >=0 |
| + | >=1 |
| ? | 0/1 |
- 只要当字符串中值出现不符合“判断规则” ,才结果就是false

| 符号 | 含义 |
|---|---|
| {n} | =n |
| {n,} | >=n |
| {n,m} | n~m |

字符
[ ]
- /[abc]/:a,b,c中出现任何一个就返回true
- /^ [abc]$/:字符里面只可以出现单个的a/b/c,只要出现其他字符就是false

- /[ ^abc ]/:除了abc以外的任何单个字符
- /[a-b]/:匹配26个小写字母的任何单个字符
.
- 匹配除了换行符以外的任何单个字符
预定义
- 某些常见模式的简写

修饰符
- 约束正则规则中的某些细节行为,eg.是否区分大小写、是否支持多行输入
- i:ignore,不区分大小写
g:global,全局搜索
/表达式/修饰符


敏感词替换

注册
- 验证码位移

- 改变表单元素的宽度,保持文字的位置不变

- 定时器、延时函数的调用者(this)指向的是window,,函数中不可以用this来指代函数的对象
- 为什么点击不会执行点击事件里面函数的程序?
a的默认行为是跳转,跳转的行为比执行程序的速度快,就无法显示程序的执行,只要阻止a标签的默认行为即可
(二选一)


- 定义后立刻执行,就不会出现没有5的情况

- if的作用不是不可以点击,而是点击后不会重新执行倒计时

- 使元素的左边缘贴近父元素的右边缘即可

- 错误提示语在页面进行缩放后总是发生变化
将所有的div均设置为由内容撑开,这样定位中的父元素就有了确定的宽


注册页面
- css

- html

- js

登录页面
- 获取点击元素中的文字宽度
e.target:获取到点击的DOM元素(a),e是事件对象,DOM元素需要从事件对象中获取
this:指的是绑定该事件的元素(nav)

- img
- autocomplete表单自动补全功能
放大镜
-
css

-
html

-
js

作用域(补充)
- 规定变量能够被访问的‘范围’
全局作用域
- 写在< script >标签或者js文件中
局部作用域
-
在函数内部声明的变量
-
1)在函数内声明的变量,在外部无法访问
2)函数内声明的变量无法相互访问
3)函数的参数也属于函数内部的变量
4)函数执行完后,内部变量实际被清空了
函数作用域
块作用域
-
用{ }包裹的代码称为代码块
-
1)在{ }中声明的变量有可能无法被访问
2)用let,const声明的变量会产生块作用域,在外界无法被访问,var不会产生
作用域链
-
底层变量的查找机制
-
优先查找当前函数作用域,若没有再查找父级作用域,直至全局作用域
-
1)嵌套关系的作用域串联起来形成作用域链
2)相同作用域链按照从小到大的原则查找变量
3)子作用域可以访问父作用域,但是父作用域不可以访问子作用域 -
(1)fn1作为obj的方法,且是普通函数,this = obj
(2)fn2作为fn1的内部箭头,,this = fn1.this = obj
(3)fn3作为obj的方法,是箭头函数,obj的{}并不是一个作用域,只是将属性和方法封装成了一个对象,所以fn3的this指向的是window
垃圾回收机制(GC)
-
浏览器有自动分配内存和回收内存的机制
-
局部变量不使用时就回收,全局变量一般不回收(关闭回收)
内存的生命周期
- 内存分配:变量、函数等声明
- 内存使用:变量、函数等使用
- 内存回收:内存不再使用,由垃圾回收器自动回收不再使用的内存
- 内存泄漏:内存因为某种原因程序未释放或无法释放
引用计数法
-
引用过一次的加1 ++
-
清除过一次的减1 –
-
如果引用次数是0(null),则释放内存
-
如果是嵌套引用,就是一个函数里两个对象相互引用,那这两个对象的被引用次数永远不会是0,就永远不会被回收
算法说明
- 栈(操作系统):存储基本数据类型,由操作系统自动分配释放函数的参数值、局部变量等
堆(操作系统):存储复杂数据类型,一般由程序员分配释放,如果程序员不释放,由垃圾回收机制回收
垃圾回收算法
标记清除法
- 1)将‘不再使用的对象’定义为‘无法到达的对象’
2)从根部(js中指的是全局变量)出发定时扫描内存中的变量,并进行标记,如果从根部出发可以找到的对象,都是还需要使用的
3)无法由根部出发无法触及的对象被标记为不再使用,稍后进行回收
闭包
-
含义:内层函数+外层函数的变量

-
作用:
1)封闭数据,提供操作,外部也可以访问内部的数据
2)当调用外层函数时,形成一条作用域链(fun 的变量对象 → outer 的变量对象 → 全局变量对象+),内层函数(环境)一直被引用,因此函数就与某些操作(打印…)的环境(数据)关联了起来 -
缺点:可能造成内存泄漏
-
简单写法

-
常见形式

闭包应用
- 作用:实现数据的私有
- 问题:如果i作为全局变量的话,i可以被重新赋值,就会导致函数的调用次数可能不正确

- 使用闭包,实现数据的私有

变量提升
- 含义:浏览器会把当前作用域中var变量的语句提前到当前作用域的最前面(只提升声明,不提升赋值)
- let和const没有变量提升
//两种写法等价
console.log(`这是${num}`)
var num = 1
-------------------------------
var num
console.log(`这是${num}`)
num = 1
- 如果变量被赋值,显示undefined;如果没有被赋值,会报错

函数进阶
函数提升
- 与变量提升作用机制类似,将函数声明提到当前作用域最前面,同样只提升函数声明,不提升函数赋值
- 使函数调用更加灵活
- 函数提升

- 函数表达式

函数参数
动态参数
arguments:函数内部内置的伪数组变量,只有数组中存在

剩余参数
- 特点:
1)…放在最末尾的形参前面,用于表示剩余的参数
2)arr可以是任意的一个词
3)得到的数组是真数组


展开运算符(…)
- 作用:将一个数组进行展开
- 求数组最大值和最小值

- 合并数组

展开运算符和剩余参数的区别 - 展开运算符在数组中使用,剩余参数(…)在函数中使用
箭头函数
- 属于表达式函数,不存在函数提升
//基本语法
const fun = () => {
console.log(1)
}
fun()
- ()内部写形参,=>相当于function

- 当只有一个形参时,声明时的形参小括号可以省略

const fun = x => {
console.log(x)
}
fun(1)
- 当函数体只有一行时,大括号可以省略
const fun = x => console.log(x)
fun(1)
- 当函数体只有一行时,return 也可以省略

const fun = (x) => x + x
console.log(fun(1))
- 箭头函数可以直接返回一个对象(加括号的函数体返回对象字面量表达式)
- 外面的小括号相当于执行函数体时的大括号,虽然函数体只有一行,但是获取的对象外面必须包括大括号,如果省略函数体的大括号的话,会默认对象的大括号是函数体的大括号

箭头函数参数
- 没有动态参数,有剩余参数

this的指向
- 箭头函数不会创造自己的this,箭头函数中的this指的是上一层作用域的this

- 事件回调函数中使用箭头函数中,this指的是window

解构赋值
数组解构
- 将数组的单元值批量赋值给一系列变量的简洁语法
- 基本语法
右侧的单元值赋值给左侧的变量

变量交互
- js前必须加分号
1)立即执行函数
(function(){})();
//或者
;(function(){})()
2)数组解构
- 目的:强调上一行代码执行完毕
let b = 2;
[b, a] = [a, b]
//或者
;[b, a] = [a, b]
函数值解构

- 剩余参数解决变量多,单元值少的情况

- 变量多,单元值少

- 防止出现undefined的情况,可以进行初始赋值

- 按需赋值

- 多维数组
1)普通写法

2)

3)
对象解构
- 如果是一个数组里存储了多个对象,使用map或者forEach遍历数组,每次得到一个item,每次对item进行解构即可
- 将对象属性和方法批量赋值给一系列变量的简洁语法

- 更换属性名,旧名字:新名字

- 如果是对象里面又嵌套了一个对象,那么写的时候一定要带对象名

- 两种写法的区别
1)作用域不同:上面的作用域为局部作用域,下面为全局作用域
2)解构时机不同:上面执行函数时解构,下面在函数外解构,函数执行时直接调用
3)打印值不同:上面的打印值与传入的实参有关,下面的与输入的数据有关


- 因为e包含了多个属性,只要是一个对象,那么它就可以解构,直接结构时,结构名不可以随便起(只能用对应的属性名),只有重命名时才可以随便起而且要规范写法(旧名:新名)

forEach()
- 执行机制 :类似于for循环的进阶,循环index次
- 作用:遍历数组的每个元素
- 与map()的区别:forEach()没有返回值
被遍历的数组.forEach(function(当前数组元素,当前数组索引号){
//函数体
})
- index(索引号)可以省略不写,但是item必须要写

Tab栏切换CSS方法
- active:在鼠标或手指按下时
- focus:在获得焦点时

筛选数组filter()方法
- 与map用法相似,同样可以省略index
- 返回结果是一个数组

const newArr = arr.filter(item => item >= 20)
与上面函数效果一样
深入对象
创建对象的三种方式
用字面量创建
const obj = {
name:'佩奇'
age:'18'
}
用new Object()创建
(1)
const obj = new Object()
obj.name = '佩奇'
(2)
const obj = new Object({obj.name = '佩奇'})
利用构造函数创建
-
说明:是一种特殊的函数,主要用来初始化对象
-
使用场景:不同的变量名,内部存储了具有相同属性名的不同属性值,利用构造函数可以将他们分别写出来(批量创建同类型对象)
-
两个约定(不是必须做):
(1)函数名首字母大写
(2)只能用new来写 -
作用机制:
1)new的作用:自动在Pig里面创建一个空对象{}
2)this指向的是这个名叫girl的空对象
3)函数Pig()中的内容是形参
4)new()中的内容是实参(与形参一一对应)
5)this.name中的name是属性名,可以自定义,而复制符号后面的是参数名 -
new的执行机制:
(1)在函数中创建新对象
(2)this指向新对象(内置规则)
(3)执行函数代码,修改this(添加name属性)
(4)返回新对象

实例成员和静态成员
实例成员
- 定义:实例对象的属性和方法称为实例成员
- 相互独立

//方法(作为对象属性的函数):
const Data = {
name:'小美',
sayHi:function(){
console.log('Hi~~')
}
}
//追加方法
Data.sayBye = function (){
console.log('Bye~~')
}

静态成员
- 构造函数上的属性和方法称为静态成员

内置构造函数
-
基本数据类型本身不是对象,只是原始值,对象由属性和方法组成
-
但是某些基本数据类型有属性和方法

//底层代码,将基本数据类型包装成了复杂数据类型
const name = new String('pink')
Object
- 三个静态方法
(1)Object.keys(对象名) 获得属性名

(2)Object.values(对象名)获得属性值

(3)Object.assign用于对象拷贝 - 使用场景:追加属性,相同的不变,没有的修改或者追加


Arrray
-
方法:
map(),forEach(),join(),reduce() -
reduce(),返回累计处理的结果,常用于求和
数组名.reduce(function (上一个值, 当前值) {},初始值)
//累加规则:有初始值就加初始值,没有初始值就只输出数组总和
//求和规则
1.若没有初始值,将数组元素的第一个值作为上一次之,将第二个元素的值作为当前值;
2.经过第一次循环,得到一个返回值,将这个返回值作为第二次循环的上一个值,元素的第三个值作为当前值,继续进行循环
3.若有初始值,则将初始值作为第一次循环的上一个值,将数组的第一个值作为当前值
//arr = [1,2,3]
//无初始值()
//上一个值 当前值 返回值 (第一次循环)
// 1 2 3
//上一个值 当前值 返回值 (第二次循环)
// 3 3 6
//有初始值 10
//上一个值 当前值 返回值 (第一次循环)
// 10 1 11
//上一个值 当前值 返回值 (第二次循环)
// 11 2 13
//上一个值 当前值 返回值 (第三次循环)
// 13 3 16

- 对象数组求和

- 其他方法
| 方法名 | 作用 |
|---|---|
| join | 拼接字符串 |
| find | 查找元素,返回符合测试条件的第一个数组元素值,如果没有符合条件的则返回undefined |
| every | 检测数组所有元素是否都符合指定条件,如果所有元素都通过检测返回true,否则返回false |
| some | 检测数组中的元素是否满足指定条件,如果数组中有元素满足条件返回true,否则返回false |
| concat | 合并两个数组,返回生成新数组 |
| sort | 对数组单元值排序 |
| splice | 删除或替换原数组单元 |
| reverse | 反转数组 |
| findIndex | 查找元素的索引值 |
- find的使用场景

- every的作用

对象属性值拼接

String
| 方法名 | 作用 |
|---|---|
| length | 获取字符串的长度 |
| split(‘分隔符’) | 将字符串拆分成数组 |
| substring | 字符串截取 |
| startsWith | 检测是否以某字符开头 |
| includes | 判断一个字符串是否包含在另一个字符串中,返回布尔值 |
| toUpperCase | 将字母转换成大写 |
| toLowerCase | 将字母转换成小写 |
| indexOf | 检测是否包含某字符 |
| endsWith | 检测是否以某字符结尾 |
| replace | 用于替换字符串,支持正则匹配 |
| match | 用于查找字符串,支持正则匹配 |
| lastIndexof(‘要找的标识符’) | 从后往前查找指定字符串,返回它在原字符串中最后一次出现的索引位置(结果是数字,包括空格) |
- substring
str.substring(截取的第一个字符的索引号,结束的索引号)
1.当只有开始索引号时,会一直截取到字符串的末尾
2.结束索引号的值不会被截取

- startsWith
str.startsWith(需要检测的字符串, 开始检测的位置)

- includes
str.includes(需要搜索的字符串, 开始检测的位置)

直接转换为字符串

字符串分装


Number
- tofixed()保留小数,遵循四舍五入原则
名字.toFixed(保留几位小数)

- 是否加引号的区别(黑:字符串)

小数的精度问题
0.1 + 0.2 = (0.1 * 100 + 0.2 * 100)/100
页面渲染

深入面向对象
编程思想
面向过程编程
- eg.蛋炒饭(做好每一步,最后混一起炒)
(1)分析步骤
(2)实现步骤
(3)使用步骤
面向对象编程(oop)
-
eg.盖浇饭(将所有东西都做好,最后混一起,直接吃)
-
将事务分解成一个个对象,然后对象之间分工与合作(以对象功能来划分问题,而不是步骤)
-
每一个对象都是功能中心,具有明确的分工
-
优点:
(1)灵活性
(2)代码可复用
(3)容易维护和开发 -
特性:
(1)继承性
(2)封装性
(3)多态性 -
封装性、继承性:通过构造函数实现,创建的新对象相互独立,互不影响,但是构造函数存在内存泄漏问题
原因:当创建两个新对象时,同时也会创建两个新的sayHi函数,在堆空间中开辟了新的内存,即使该函数是函数中共有的

原型
介绍
-
构造函数通过原型分配的函数是所有对象所共享的
-
js规定,每一个构造函数都有一个prototype属性,指向另一个对象,我们也称之为原型对象,这个原型对象可以挂载函数,对象实例化不会多次创建原型上函数
-
将不变的方法直接定义在原型对象身上,这样所有的实例就会共享这些方法
-
获得的是一个对象,这个对象就叫做原型(对象)

-
公共的属性写到构造函数上,公共的方法写到原型对象上

-
构造函数和原型对象中的this都指向的是实例对象

先调用函数再打印的原因是that赋值发生在sayHi函数执行时,而不是实例对象创建时

利用原型求max和sum

constructor属性
-
每一个原型对象都有这个属性
-
这个属性指向该原型对象的构造函数
-
每个原型对象进行单独赋值,会显示constructor属性

-
将方法共同命名再一个原型对象中时,不会显示constructor属性,这时候就要手动添加一个constructor属性,指向原来的构造函数


对象原型
-
构造函数 -> 实例化对象,构造函数 -> 原型对象
为什么实例化对象可以访问原型对象中的属性和方法? -
对象都会有一个属性__ proto__指向构造函数的prototype原型对象,之所以实例化对象可以访问原型对象中的属性和方法,是因为对象有__ proto__原型的存在
-
注意
(1)__ proto__是浏览器非标准属性
(2)[[proto]] === __ proto__
(3)用来表明当前实例对象指向哪个原型对象prototype(原型对象指向对象原型)
(4)__ proto__是一个只读属性
(5)__ proto__里也有一个constructor属性,指向创建该实例对象的构造函数


原型继承
-
通过原型对象实现继承
-
问题:堆栈内存分配原因
因为Girl和Boy添加的是相同的方法,所以在堆内存中,对象的值毫无疑问是相同的,但是在栈空间中,开辟的两个空间的地址是相同的,都是‘data’。因此看似是只给Girl添加了方法,但是实际上改变的是总的对象 -
解决办法:让Girl和Boy的原型对象指向不同的对象
(1)不同的两个对象名中设置相同的属性和属性名
(2)构造函数(构造函数new出来的对象结构一样,但是对象不一样)


-
需要手动指回原来构造函数的原因:当执行
Boy.prototype = new Data()时,构造函数Boy就成了构造函数Data的实例化对象,根据继承性原则,Boy.prototype.constructor就指向了外部的Data构造函数

原型链(查找规则)
- 基于原型对象的继承使得不同构造函数的原型对象关联在一起,并且这种关联的关系是一种链状的结构,我们将原型对象的链状结构关系称为原型链
- 只要是一个对象就有__proto__

- instanceof查找
‘谁 属于 谁 吗’

模态框
-
使用实例对象的属性创建方法,目的是为了实现后续Dom元素与实例对象的绑定
如果使用const modalBoo创建一个div,(1)那么这个modalBoox是局部变量,外部无法访问,(2)而且如果每创建一个实例对象,后续在页面中就会创建几个div盒子

-
有双引号的原因
浏览器会将‘文本+标签’形式中的 文本独立出来,就会给这段文字添加双引号,若这个包裹文字的标签中没有其他标签,就不会用双引号包裹

-
主要思想:面向对象
-
构造函数中的创建div是给div分配内存,但是并不会在页面中显示;open方法中的追加div才是在页面中添加
在页面中添加元素的方法:父元素.append()
特点:(1)在父元素结尾追加;(2)不会覆盖原来的元素;(3)可同时添加多参数(文本+元素+另一个参数)
在页面中删除元素的方法:元素.remove()
特点:(1)将DOM树中的元素彻底删除;(2)没有参数值

-
del.open()可以这样写的原因:del是实例化对象,open方法是挂载在构造函数的prototype属性(原型对象)身上的,当del调用open方法时会依照原型链依次寻找open方法

深浅拷贝
浅拷贝
-
对象:
Object.assign() / […obj]
数组:
Array.prototype.concat() / […arr] -
直接赋值和浅拷贝的去区别:
直接赋值:无论哪种情况,原数据和新数据都会被同时改变,因为赋的值是栈里面的地址;
浅拷贝:如果是单层对象可以实现新旧数据互不影响,但是多层数据就会有影响,单层数据类型直接拷贝的是值 -
均会出现相同的问题:被嵌套的对象里面的内容会被同时改变


深拷贝
递归
- 如果一个函数在其内部仍可调用自己,那么这个函数就是递归函数
- 递归函数会出现‘ 栈溢出 ’,因此必须加退出条件return
- setTimeout实现setInterval的效果

多数据嵌套
- Array必须写在Object前面

引入数据库
- 先引入下载的js文件,才能调用里面的函数

利用JSON
- 原理:先将复杂数据类型转换为简单数据类型,当简单数据类型转换为复杂数据类型时,意味着生成了有一个新对象,即又开辟了一个内存,与原来的数据自然不一样

异常处理
- 提升代码运行的健壮性
throw抛异常
-
Error后()里面的内容不是必须添加
-
Error对象配合throw使用
-
抛异常会终止程序

try/catch捕获异常
-
捕获浏览器提供的错误信息
-
如果报错,代码不会中断,所以需要添加return中断程序,即使添加return,finally中的内容也会执行
-
catch后面括号中的内容是参数,可以自定义,message是参数的一个属性
-
throw可以和catch搭配使用,这样就不用写return了

debugger
-
语法:debugger
-
主要用于断点调试,可以写在感觉代码出错的位置,打开浏览器可以自动跳转到debugger的位置
-
在浏览器页面打开F12,点击‘源代码’,刷新页面,代码会在debugger出停止,并在dubugger处显示高亮
处理this
普通函数
- 谁调用就指向谁,没有明确调用者时指向window
箭头函数
this指向
- 向上查找最近作用域的this
- 注意事项:
(1)事件回调函数不适用,使用普通函数,this值DOM元素,使用箭头函数,this指window
(2)基于原型的面向对象(构造函数,原型函数)
改变this
call
- 语法 :使用call调用函数,同时修改this指向
const obj = {
name:'小美',
age"18
}
function fu(x , y){
return x + y
}
//obj是修改后this的指向,1,2是传入的实参
fu.call(obj,1,2)
applly
- 调用函数,与call不同的是实参需要加[ ],传递的是一个数组
const obj = {
name:'小美',
age"18
}
function fu(x , y){
return x + y
}
//obj是修改后this的指向,1,2是传入的实参
fu.call(obj,[1,2])
-
求最大值
-
必须写为apply(thisArg,[argsArray])

-
bind
-
不调用函数,bind自身就是一个函数,但是this的指向改变
-
优点:不会立即执行
const obj = {
name:'小美'
}
function fun() {
console.log(this)
}
const fn = fun.bind(obj)
fn()


相同点
- 都可以改变this指向
不同点
- call:调用函数,正常传递实参
- apply:调用函数,实参为数组形式
- bind:不调用函数,正常传递实参,不立即执行
使用场景
- call:需要改变this的场景
- apply:与数组有关的情形
- bind:需要改变this,但是不想立即执行
性能优化
防抖
- 单位时间内,频繁触发事件,只执行最后一次
- 使用场景:
搜索框搜索输入、输入验证检测
lodash
//在事件回调函数中写的函数形式,需要带括号
//执行函数就是默认事件回调函数写法中写的函数
//在该时间后才执行一次
_.debounce(执行函数,需要延时的毫秒数)
手写防抖函数
- 思路:
(1):声明定时器
(2):每次触发事件前先判断是否有定时器,若有,则先清除后添加
(3):若没有,则定义定时器到定时器变量里面
(4):函数调用写在定时器里面,若在外面,就是立即执行

节流
- 单位时间内多次执行事件,但是只触发一次
- 使用场景:
高频事件:鼠标移动,页面缩放,页面滚动
//在事件回调函数中写的函数形式,需要带括号
//执行函数就是默认事件回调函数写法中写的函数
//在该时间内就只会执行一次
_.throttle(执行函数,需要延时的毫秒数)
手写节流函数
- 思路:
(1):声明定时器
(2):每次触发事件前先判断是否有定时器,若有,则不开启新定时器
(3):若没有,则将定时器放入定时器变量里
(4):函数掉用写在定时器里面,若在外面,就是立即执行
(5):清除定时器用timer = null而不用clearTimeout(timer),是因为在定时器里面无法清除定时器,定时器的值为1

页面打开时,记录上一次视频播放位置
- 两个事件
ontimeupdate:事件在视频/音频(audio/video)当前的播放位置发生改变时触发
onloadeddata:事件在当前帧的数据加载完成且还没有足够的数据播放视频/音频(audio/video)的下一帧时触发(页面刷新时那个页面)

更多推荐



所有评论(0)