目录
一、作用域
作用域规定了变量能够被访问的范围,分为局部作用域和全局作用域
1、局部作用域
(1)函数作用域
在函数内部声明的变量只能函数内部访问,外部无法直接访问
(2)块作用域
在JavaScript中使用{ }包裹的代码称为代码块,内部声明的变量外部有可能无法被访问
let和const 会产生块作用域,var不会产生块作用域
2、全局作用域
<script>标签和.js文件的最外层就是全局作用域,其中声明的变量其他任何作用域都可以使用
3、作用域链
作用域链本质上是底层的变量查找机制,在函数被执行时,会优先查找当前函数作用域中查找变量,如果找不到会依次逐级查找父级作用域直到全局作用域(从小到大查找)
子作用域链能够访问父作用域,父作用域无法访问子级作用域
4、垃圾回收机制(GC)
内存不使用时被自动回收
全局变量一般不会回收
程序中分配 的内存由于某种原因程序未释放或无法释放叫做内存泄漏
垃圾回收算法:
(1)引用计数法
因为它们的引用次数永远不会是0
(2)标记清除法
5、闭包
概念:一个函数对周围状态的引用捆绑在一起,内层函数中访问到其外层函数的作用域
闭包 = 内层函数 + 外层函数的变量
作用:封闭数据、提供操作、外部也可以访问函数内部的变量
实现数据私有:
i 不会被修改 ,但会有内存泄漏的问题
6、变量提升
把当前作用域里面var声明的所有变量提升到作用域的最前面
只提升声明,不提升赋值
不推荐使用var
二、函数进阶
1、函数提升
函数在声明之前即可被调用
在当前作用域中,会把所有函数声明提升到当前作用域的最前面
只提升函数声明,不提升函数调用
函数表达式必须先声明和赋值,后调用,否则报错
2、函数参数
(1)动态参数
arguments 是函数内部内置的伪数组变量,它包含了调用函数式传入的所有实参
(2)剩余参数
语法:... 数组名 放入形参,置于最末函数形参,用于获取多余的实参
获取的剩余实参,是一个真数组
提倡使用剩余实参
(3)展开运算符
展开运算符(...),将一个数组展开
3、箭头函数
目的:更简短的函数写法并且不绑定this,箭头函数的语法比函数表达式更简洁
使用场景:箭头函数适用于那些本来需要匿名函数的地方
(1)基本语法
只有一个形参的时候可以省略小括号,只有一行代码的时候可以省略大括号
只有一行代码,可以省略return
箭头函数可以直接返回一个对象
必须加小括号,表示返回对象字面量
(2)箭头函数参数
箭头函数没有arguments动态参数,但是有剩余参数
(3)箭头函数this
箭头函数不会创建自己的this,指向上一级作用域的this指向
DOM事件回调函数为了简便,不推荐使用箭头函数,如果使用,this指向window
三、解构赋值
1、数组解构
数组结构是将数组的单元值快速批量赋值给一系列变量的简洁语法
(1)基本语法
两个变量交换值:
必须加分号:
立即执行函数后边, 使用数组的时候(中括号前面)
(2)变量多,单元值少
多的变量为undefined,防止此情况:
给变量初始化赋值
(3)利用剩余参数解决变量少单元值多的情况,将多的值存在剩余参数数组中
(4)按需导入,忽略某些返回值
(5)支持多维数组的结构
2、对象解构
将对象属性和方法快速批量赋值给一系列变量的简洁语法
(1)语法:
变量名要和属性名一致
(2) 解构数组对象:
(3)多级对象解构
四、遍历数组forEach方法
1、基本语法
不返回值
五、数组筛选filter方法
六、深入对象
1、创建对象三种方式
(1)利用对象字面量创建对象
(2)利用new Object 创建对象
(3)利用构造函数创建对象
2、构造函数
是一种特殊的函数,主要用来初始化对象,可以通过构造函数来快速创建多个类似的对象
命名以大写字母开头
必须用new来使用构造函数
实例化执行过程:
3、实例成员&静态成员
(1)实例成员
通过构造函数创建的对象称为实例对象,实例对象中的属性和方法称为实例成员(实例属性和实例方法)
实例对象相互独立
(2)静态成员
构造函数的属性和方法被称为静态成员(静态属性和静态方法)
七、内置构造函数
1、Object
三个静态方法(静态方法就是只有构造函数Object可以调用的)
(1)Object. keys():获得对象的所有属性名,返回值是数组
(2)Object. values ():获得对象的所有属性值,返回值是数组
(3)Object. assign():对象的拷贝
2、Array
(1)常见方法:
(2)其他方法
find:
every:
(3)伪数组转换为真数组
3、String
(1)substring()
4、Number
(1)toFixed()设置保留小数位的长度
(2)转化为字符串
num.toString()
八、编程思想
1、面向过程介绍
面向过程就是分析出解决问题所需要的步骤,然后用函数把这些步骤一步步实现,使用的时候再一个个的依次调用就可以了
2、面向对象介绍
(1)概念
面向对象是把事物分解成为一个个对象,然后由对象之间分工与合作
(2)oop
封装性、继承性、多态性
九、构造函数
可以通过构造函数实现封装
存在浪费内存的问题
十、原型
1、原型
(1)构造函数通过原型分配的函数是所有对象所共享的
(2)每一个构造函数都有一个prototype属性,指向另一个对象,所以我们也称原型对象
(3)这个对象可以挂载函数,对象实例化不会多次创建原型上的函数,节约内存
(4)可以把那些不变的方法,直接定义在prototype对象上,这样所有的对象实例就可以共享这些方法
(5)构造函数和原型对象中的this都指向实例化的对象
2、constructor属性
constructor属性在原型对象里面
该属性指向该原型对象的构造函数
使用场景:如果不指回constructor,覆盖原来的原型对象,就不确定prototype对象的构造函数是谁了
3、对象原型
对象(不管是什么对象)都会有一个属性:__proto__指向构造函数的prototype原型对象,实例对象可以使用构造函数prototype原型对象的属性和方法就是因为这个属性的存在
只读不能赋值
__proto__对象原型里面也有一个constructor属性,指向构造函数
4、原型继承
(1)封装:抽取出公共部分
5、原型链
基于原型对象的继承使得不同构造函数的原型对象关联在一起,并且这种关联的关系是一种链状的结构,我们将原型对象的链状结构关系称为原型链
原型链-查找规则
十一、深浅拷贝
只针对引用类型
1、浅拷贝
浅拷贝拷贝的是地址
拷贝对象之后,里面的属性值是简单数据类型直接拷贝值,如果属性值是引用数据类型则拷贝的是地址
常见方法:
(1)拷贝对象:Object.assgin() / 展开运算符{···obj}拷贝对象
(2) 拷贝数组:Array.prototype.concat()或者[...arr]
2、深拷贝
深拷贝:拷贝的是对象,不是地址
常见方法:
(1)通过递归实现深拷贝
(2)js库lodash里面cloneDeep内部实现了深拷贝
(3) 通过JSON.stringify()实现
十二、异常处理
1、throw抛异常
异常处理指预估代码执行过程中可能发生的错误,然后最大程度的避免错误的发生导致整个程序无法继续运行
(1)throw抛出异常信息,程序也会终止执行
(2)throw后面跟的是错误提示信息
(3)Error对象配合throw使用,能够设置更详细的错误信息
2、try/catch捕获错误信息
不会中断程序,需要加return中断信息
3、debugger
十三、处理this
1、this指向
(1)普通函数的this指向
严格模式下指向undefined
(2) 箭头函数的this指向
箭头函数的this指向是上一级作用域的this,往上一级找,直到找到有this定义
2、改变this
(1)call()
语法:
(2)apply()
语法:
(3)bind()
语法:
十四、防抖
防抖:单位时间内,频繁触发事件,只执行最后一次
1、lodash提供的防抖来处理
2、手写防抖函数
十五、节流-throttle
节流:单位时间内,频繁触发事件,只执行一次
1、lodash实现节流
2、手写节流函数