js篇
一.js原型链
1.什么是原型:
任何对象都有一个原型对象,这个原型对象由对象的内置属性_proto_指向它的构造函数的prototype指向的对象(即构造函数的原型对象),即任何对象都是由一个构造函数创建的,但是不是每一个对象都有prototype,只有方法才有prototype。
2. 什么是原型链?
原型链的核心就是依赖对象的_proto_的指向,当自身不存在的属性时,就一层层的扒出创建对象的构造函数,直至到Object时,就没有_proto_指向了。
3. 如何分析原型链?
因为_proto_实质找的是prototype,所以我们只要找这个链条上的构造函数的prototype。其中Object.prototype是没有_proto_属性的,它的__proto__属性==null。
4.原型链继承
原型链是针对原型对象的,在查找实例属性时,现在实例中查找,如果没有找到,再到obj.__proto__(=f1.prototype)原型对象,再到f1.prototype.__proto__(=f2.prototype),依次向上查找。
二.闭包
1.什么是闭包
闭包是指有权访问另一个函数作用域中变量的函数,创建闭包的最常见的方式就是在一个函数内创建另一个函数,创建的函数可以访问到当前函数的局部变量。
2.闭包的特点
1.让外部访问函数内部变量变成可能
2.变量会常驻在内存中
3.可以避免使用全局变量,防止全局变量污染;
3、
好处:可以读取其他函数内部的变量,并将其一直保存在内存中。
坏处:可能会造成内存泄漏或溢出。
三.js执行机制
1.js是一门单线程语言 js的执行机制就是事件循环(Event Loop)
2.
同步任务:在主线程上排队执行任务,只有前一个任务执行完毕,才能执行后一个任务
异步任务:不进入主线程,而是进入"任务队列"的任务,只有"任务队列"通知主 线, 某 个 异步任务可以执行了,该任务才会进入主线程执行。
除了广义的同步任务和异步任务,对任务更精细的定义:
macro-task(宏任务):包括整体代码script,setTimeout,setInterval
micro-task(微任务):Promise,process.nextTick
宏任务中有微任务,一定要将宏任务中的微任务执行完毕,再去执行下一个宏任务。
四.this指向
全局作用域中:this永远指向window
- 如果函数直接被调用 this指向window 函数名()
- 被对象的对象.属性()调用 函数中的this指向这个对象
- 当使用 new 关键字调用函数时,函数中的 this 一定是 JS 创建的新对象。
-
定时器中的this——window
-
bind、call、apply的区别
- 相同点
- 三个都是用于改变this指向;
- 接收的第一个参数都是this要指向的对象;
- 都可以利用后续参数传参。
- 不同点
- call和bind传参相同,多个参数依次传入的;
- apply只有两个参数,第二个参数为数组;
- call和apply都是对函数进行直接调用,而bind方法不会立即调用函数,而是返回一个修改this后的函数。
-
主要应用场景:
1.call经常做继承。
2.apply经常跟数组有关系,比如借助于数学对象实现数组最大值最小值。
3.bind不调用函数,但是海想改变this指向,比如改变定时器内部的this指向。
五.promise
1.Promise 是异步编程的一种解决方案,其实是一个构造函数,自己身上有all、reject、resolve这几个方法,原型上有then、catch等方法。
2.对象的状态不受外界影响。Promise对象代表一个异步操作,有三种状态:pending
(进行中)、fulfilled
(已成功)和rejected
(已失败)。
3.一旦状态改变,就不会再变,任何时候都可以得到这个结果
。Promise对象的状态改变,只有两种可能:从pending变为fulfilled和从pending变为rejected
。
4.new Promise(function (resolve, reject) {
// resolve 表示成功的回调
// reject 表示失败的回调
}).then(function (res) {
// 成功的函数
}).catch(function (err) {
// 失败的函数
})
resolve
函数的目的是将Promise对象状态变成成功状态
,在异步操作成功时调用,将异步操作的结果,作为参数
传递出去。reject
函数的目的是将Promise对象的状态变成失败状态
,在异步操作失败时调用,并将异步操作报出的错误,作为参数
传递出去。
Promise实例生成以后,可以用then方法
分别指定resolved状态
和rejected状态
的回调函数。
5.链式
then
方法返回的是一个新的Promise实例
(注意:不是原来那个Promise实例
)。因此可以采用链式写法
,即then方法后面再调用另一个then方法
6.Promise.all()
方法接受一个数组
作为参数,p1、p2、p3都是 Promise 实例
Promise.allSettled()//返回的都是成功值
六.深拷贝浅拷贝
- 浅拷贝:对于基本类型数据来说,拷贝的是值;对于引用数据来说,拷贝了地址,因此拷贝后的对象和原对象会共用一个内存地址,因此,属性值会同步变化(第二层往后的属性)
- 浅拷贝的方法:手写浅拷贝、Object.assign()、拓展运算符
- 对于引用数据类型来说,就是拷贝原始对象的所有属性与方法,在内存中重新开辟一块内存空间进行存储
- JSON.stringify()
-
如果对象的属性值为简单类型(如Number,String),通过Object.assign({},Obj)得到的新对象为深拷贝;如果属性值为对象或其它引用类型,那对于这个对象而言其实是浅拷贝的。
使用解构赋值和扩展运算符(...)时,你会发现情况和上面是一样的。
七.js设计模式
vue
1.为什么data是个函数并且返回一个对象呢?
data
之所以是一个函数,是因为一个组件可能会多处调用,而每一次调用就会执行data函数
并返回新的数据对象,这样,可以避免多处调用之间的数据污染
。
2.修饰符
3.组件传值方式
- 父组件传值给子组件,子组件使用
props
进行接收 - 子组件传值给父组件,子组件使用
$emit+事件
对父组件进行传值 - 组件中可以使用
$parent
和$children
获取到父组件实例和子组件实例,进而获取数据 - 使用
$attrs
和$listeners
,在对一些组件进行二次封装时可以方便传值,例如A->B->C - 使用
$refs
获取组件实例,进而获取数据 - 使用
Vuex
进行状态管理 - 使用
eventBus
进行跨组件触发事件,进而传递数据 - 使用
provide
和inject
,官方建议我们不要用这个,我在看ElementUI
源码时发现大量使用 - 使用浏览器本地缓存,例如
localStorage
4.路由有哪些模式呢?又有什么不同呢?
- hash模式:通过
#号
后面的内容的更改,触发hashchange
事件,实现路由切换 - history模式:通过
pushState
和replaceState
切换url,实现路由切换,需要后端配合
5.v-if和v-show有何区别?
- 1.
v-if
是通过控制dom元素的删除和生成来实现显隐,每一次显隐都会使组件重新跑一遍生命周期,因为显隐决定了组件的生成和销毁 - 2.
v-show
是通过控制dom元素的css样式来实现显隐,不会销毁 - 3.频繁或者大数量显隐使用
v-show
,否则使用v-if
6.什么是虚拟dom?
使用js算法动态生成的dom叫虚拟dom
7.生命周期
//创建阶段
beforeCreate(){
//骨架屏来占位
//日志上传
},
created(){
//发起ajax请求,【不推荐】因为ajax异步,生命周期同步
//在服务器端渲染的时候,这个函数是最后一个生命周期
//技术胖
},
// 挂载阶段
beforeMount(){
// 可以对一些数据进行格式化
},
mounted(){
// 发起ajax【推荐】前端项目大多数都是运行在浏览器,极少数是服务器渲染
},
// 更新阶段
beforeUpdate(){
// 可以二次对数据进行修改
},
updated(){
// 只能观察到更新的数据
},
// 销毁阶段
beforeDestroy(){
//清除常驻内存的垃圾
//对用户的离开行为进行提示
},
destroyed(){
}
8.slot插槽
1.匿名插槽
2.具名插槽
<slot name="one"></slot>
<template v-slot:one>
<h3 >插槽1</h3>
</template>
<template #two>
<h3 >插槽2</h3>
</template>
3.作用域插槽
<slot name='slot1' :msg="msg" v-bind:user='user'></slot>
<template #slot1='{msg,user}'>
<h2>{{msg}}</h2>
<h2>{{user}}</h2>
</template>
4.nextTick
保证所有dom全部更新完毕之后才会触发,用于获取dom更新后的获取dom1节点数据
5.vuex工作流程
1.store里的state在组件中使用
2.组件使用dispatch调用action派发业务
3.action使用commit调用mutation
4.mutation调用state进行修改
5.当state改变后,store通知组件更新
6.mutation和action区别
mutation式唯一修改state,且只能运行同步代码,action专门用于处理异步操作,只能通过调用mutation修改state
7.state和getter的关系
state相当于组件里的data,getters相当于组件里的computed
getters是基于state计算出来的
8.对象新属性无法更新视图,删除属性无法更新视图,为什么?怎么办?
- 原因:
Object.defineProperty
没有对对象的新属性进行属性劫持 - 对象新属性无法更新视图:使用
Vue.$set(obj, key, value)
,组件中this.$set(obj, key, value)
- 删除属性无法更新视图:使用
Vue.$delete(obj, key)
,组件中this.$delete(obj, key)
9.
Vue的SSR是什么?有什么好处?
SSR
就是服务端渲染- 基于
nodejs serve
服务环境开发,所有html
代码在服务端渲染 - 数据返回给前端,然后前端进行“激活”,即可成为浏览器识别的html代码
SSR
首次加载更快,有更好的用户体验,有更好的seo优化,因为爬虫能看到整个页面的内容,如果是vue项目,由于数据还要经过解析,这就造成爬虫并不会等待你的数据加载完成,所以其实Vue项目的seo体验并不是很好