js
1. 闭包的理解
闭包就是函数嵌套函数,一个函数有权访问另一个函数作用域中的变量。
本质上,闭包就是将内部函数与外部函数连接起来的桥梁。
闭包还有一个 特性内容函数可以其所在的外部函数中声明的变量与参数,及时外部函数被返回。
闭包的优点
变量可以重复使用,且不会污染变量。
变量长期存储在内存当中
变量的私有化
有效的保护了函数内容的变量
闭包的缺点
使用闭包会把函数中的变量保存在内存当中,非常消耗内存,不能滥用闭包。
在不兼容的游览器中使用会导致内存泄漏。(内存泄漏:不是用的变量,没有及时的清除就是内存泄漏)(解决方案:垃圾回收机制,清除长期不使用的对象)
闭包使用到跨域访问时,会使闭包的性能从损耗(解决方法:把跨域变量放入局部作用域中,直接访问局部变量)
闭包的适用场景
数据隐藏:因为用户级别的问题,没法对data数据进行直接的更改。
for循环和定时器的使用
函数的防抖与节流
2. 作用域
作用域分:全局作用域,局部作用域,es6新增的块级作用域
全局作用域是指:变量定义在函数的外部,全局使用
局部作用域是指:变量只能在函数内部访问
块级作用域是指:{},if语句和for循环语句,适用于const,let。
作用域链:是指从最内部的作用域向最外部,查找变量的过程,生成的链式叫做作用域链。
注意:尽量不要使用全局变量,因为容易导致全局的污染,命名冲突。
3.原型与原型链
每个构造函数都有一个prototype叫做显示原型
每个实例对象都有一个__proto__叫做隐式原型
通常实例对象的隐式原型指向它自身构造函数的显示原型。
每个prototype都有一个constructor属性,指向它关联的构造函数。
原型链:每个对象都有一个prototype属性,当我们访问一个对象的属性时,查找不存在时,就去它的__proto__去找,去找它原型的原型,一直找到0bject.prototype,它也有一个__proto__属性值为null。
4.继承
es5的继承
继承分原型链继承,借用构造函数继承,组合继承:原型链继承+借用构造函数
原型链继承:父类实例作为子类的原型
借用构造函数继承:子类使用call方法调用父类的方法,将父类的this修改为子类的this,把父类的属性复制一份给子类。
组合继承:子类既能调用父类中的实例属性,也能调用父类的原型属性,继承属性与方法。
es6的继承
利用class定义类,使用extends关键字来继承父类的属性与方法,不使用new关键字和function来定义函数。
类
es5的class类
先定义一个构造函数,是通过new操作符来完成
es6的class类
es6引入了class关键字,使用class关键字定义类,使得JavaScript在对象的写法更为节俭,更像是一种面向对象的写法。
变量提升
class不存在变量提升,需要先定义再使用,es6不会进行类的声明提升到代码头部,es5会有变量的提升,先使用后定义。
5.深拷贝与浅拷贝
在我们处理复杂的对象时,我们想要其对象的属性值时,就需要使用深拷贝与浅拷贝。
深拷贝
深拷贝是层层拷贝
首先需要创建一个新的对象或数组,把原对象或原数组中的属性值拷贝到新对象和新数组中。
浅拷贝
浅拷贝是只拷贝一层
首先需要把原对象或原数组的属性值引用赋值到,新对象和新数组中
所谓深拷贝和浅拷贝都进行复制,主要是复制出来的新对象和原对象是否会互相影响,修改一个另一个是否会改变。
可以使用for in ,object.assign(),扩展运算符,递归等递归函数进行深拷贝。
es6
promise
promise是异步编程的解决方案,解决地域回调,可以链式调用。
promise是一个容器,用来保存未结束事件的结果(通常用来做异步操作)
promise是一个对象,用来获取异步操作最终的状态
promise是一个构造函数,对外统一的API,自身有all(),resolve(),reject()方法,原型上有then(),catch()等方法
promise的两个特点:
1.promise状态不受外界影响,且有三个状态 pending初始状态、fulfilled 成功状态、rejected失败状态,只有异步操作的结果可以决定是哪一种状态,其它操作无效。
2.promise状态一旦改变,就不可以再变状态不可逆,pending到fulfilled状态,或pending到rejected状态。
promise使用
使用new关键字生成一个promise对象,这个函数有两个参数分布是resolve和reject,这两个函数就是回调函数。
resolve()异步操作成功时调用
reject()异步操作失败时调用
then()函数执行到成功时使用
catch()函数执行到失败时调用,该方法不会报错,只是执行异常
all()所有异步操作都完成时才会执行
race()执行异步操作只要有一个执行,就会执行该方法
async/await
async/await是一种同步编写方式,异步操作,两者必须一起使用才会生效
async字面理解是异步,它与普通函数使用方式一致,它能生成一个函数,
把async这个关键字放到一个函数前面,这个函数就会变成异步函数。
await字面理解是等待,它用来等待async函数的执行。
优点:
它会依次执行
同步代码的编写方式
多个参数传递
同步代码异步代码一起编写
async/await对promise有优化
使用场景
async通常用来做异步操作
第一步ajax调用接口,再调用ajax的接口,达到异步操作。
vue
vue双向数据绑定
采用数据劫持结合发布订阅者的模式,通过object.dineproperty()来劫持各个属性的setter,getter在数据变动时发布消息给订阅者,触发相应的监听回调来渲染视图,变更数据。
vue的数据绑定将MVVM作为数据绑定的入口,综合observer,compile和watcher三者,通过compile来解析模版指令,最终利用watcher搭起observer和compile之间的桥梁,达到数据变化,数据更新,model数据变更时达到双向绑定的效果。
**数据劫持:**当我们访问或设置对象的属性的时候,都会触发相对应的函数,然后函数里返回属性的值。当我们触发函数做一些操作,这就是劫持操作。
vitral dom (虚拟dom)
虚拟dom,就是用对象的方式取代真实的dom操作,把真实的dome操作放入内存中,在内存中的对象做模拟操作。当页面打开游览器会解析HTML元素,构造一颗dom树,将所有状态,保存起来,在内存中模拟真实的dom操作,操作完成后又会生成一颗dom树,两颗dom树做比较,根据diff算法比较两颗dom树不同的地方,只渲染一次不同的地方。
virtual dom的优点:
最终表现在dom上的修改只更改部分,保证高效的渲染。
提高了性能。
缺点:
渲染了大量的dom后,由于多了一层虚拟dom的计算,会比innerHTML插入的更慢
组件通信
1.父传子:就是在父组件中的子组件标签上绑定一个属性,属性上挂载需要传递的数据,在子组件通过props来接收数据。
2.子传父:在父组件中的子组件标签上绑定一个自定义事件,给这个事件挂载需要调用的方法,在子组件的方法通过this.
e
m
i
t
来
调
用
这
个
方
法
。
∗
∗
3.
兄
弟
组
件
∗
∗
:
在
s
r
c
中
新
建
一
个
b
u
s
.
j
s
文
件
,
然
后
导
入
空
的
v
u
e
实
例
。
在
传
输
数
据
的
一
方
,
通
过
b
u
s
.
emit来调用这个方法。 **3.兄弟组件**:在src中新建一个bus.js文件,然后导入空的vue实例。 在传输数据的一方,通过bus.
emit来调用这个方法。∗∗3.兄弟组件∗∗:在src中新建一个bus.js文件,然后导入空的vue实例。在传输数据的一方,通过bus.emit来派发事件,数据以参数的形式传递。
在接收数据的一方,通过bus.$on来接收数据
vuex
vuex:是一个专为vue.js应用程序开发的状态管理模式,它采用了集中式存储数据和保存所有的组件状态,通过vuex可以为我们解决了组件之间的数据共享的问题,后期方便我们管理以及后期的维护。
vuex的五个核心:
state:存放状态,存储数据
getters:计算属性,通过this.
s
t
o
r
e
.
g
e
t
t
e
r
s
来
获
取
s
t
a
t
e
里
的
数
据
m
u
t
a
t
i
o
n
s
:
唯
一
能
改
变
s
t
a
t
e
的
状
态
,
通
过
提
交
m
u
t
a
t
i
o
n
s
来
改
变
,
t
h
i
s
.
store.getters来获取state里的数据 mutations:唯一能改变state的状态,通过提交mutations来改变,this.
store.getters来获取state里的数据mutations:唯一能改变state的状态,通过提交mutations来改变,this.store.commit()
action:异步的mutations,可以通过dispatch来分发state的数据。
model:让数据模块化
基本使用新建store文件,在main文件引入
数据持久化vuex里存储数据,页面一刷新就会丢失。
解决方法:存放在localstorage或者sessionstorage里,进入页面时会判断是否丢失,丢失回去localstorage和sessionstorage里去取。
安装vuex-persistedstate插件,进行持久化的配置。
vuex的运行机制
在组件中通过dispatch来调用actions中的方法,在actions中通过commit来调用mutations中的方法,在mutations中可以直接操作state中的数据,state的数据只要改变就会响应到组件中。
keep-alive
keep-alive标签是vue的内置组件,能在组件切换时把组件状态保存到内存中,它就是为了取消组件的销毁函数,防止重复渲染dom。
全部缓存:就是用keep-alive将router-view包裹起来。
部分缓存:就是在路由文件里
{
path: '/child1',
name: 'Child1',
component: Child1,
meta:{
keepAlive:true
}
}
}
具体用法:列表页面和详情页面,就是在用户经常跳转页面频率过高,组件使用keep-alive进行缓存,用户每次返回列表,就能直接从缓存中拿出,不是重新渲染。
自定义组件
创建子组件文件,创建组件模版,然后定义props里的数据,实现子组件的逻辑代码,封装组件,在父组件中import引入,在父组件
自定义指令
就是在操作模版时自己定义指令,
自定义指分为全局自定义指令,局部自定义指令。
使用vue.directive{ 指令 }进行全局自定义指令
自定义指令钩子函数:
inserted:被绑定元素插入父节点时调用。
bind:只调用一次,指令第一次绑定到元素时调用。
unbind:只调用一次,指令与元素解绑时调用。
update:被绑定元素所在模版更新时调用。
componentupdated:被绑定元素所在模版完成一次周期性跟新时调用。
自定义指令使用场景:
1.下拉菜单:点击下拉菜单本省不会隐藏菜单点,点击下拉菜单以为的区域会隐藏菜单。
2.相对时间的转换:微博,朋友圈,QQ空间发布动态后的相对时间,几分钟,刚刚。