JS+Vue 基础和核心常识 应聘常问面试题
模块化,什么是模块化开发?
模块化就是遵守es6的固定语法,把一个大的文件差分成多个小的文件并相互依
赖,这个小的文件就是模块。这种规则就是模块化开发。
1.es6模块完全取代了CommonJs和AMD规范
2.es6的模块会自动采用严格模式。
3.CommonJS是通过,module.exports导出,require导入,只能在node中使用,
node是遵循CommonJS规范
4.module.exports导出和exports导出的区别:如果他们都指向同一个对象,那就
会合并,如果分别指向不同对象,就会遵循module.exports导出的对象
5.export default 默认导出,一个模块中只能有一个默认导出
6.import 导入模块。
7.export 导出模块。
// 怎么读?
import //因抛特
export //e可四抛特
module //毛豆
CommonJS //考木js
default//第佛特
require//瑞快热
promise是什么?可以解决什么问题?
promise 是异步编程的解决方案,解决回调地狱问题的方法,异步的代码同步去写。
回调地狱就是 请求省市区时,先请求省再请求市,然后请求市的时候要根据省
的id来,这样要套一层,请求的回调一层套一层,这就是回调地狱。
promist 是一个构造函数 P要大写 在构造函数写异步代码。
三种状态分别是↓
等待=进行中,已完成=已成功,失败=已失败。
pending(进行中)fulfilled(已成功)rejected(已失败)
pending等待也是初始状态,
如果变成 fulfilled(已成功)就执行代表成功的then的函数,
如果变成rejected(已失败)就执行catch的函数。
race方法:可以处理多个promise请求 只要有一个成功就成功,
all方法:也可以处理多个promise请求, 全部成功就成功。
一旦改变不能再变化 请求成功失败都会以参数的形式返回出来。
//怎么读?
rejected//瑞摘可特
pending//pen定
fulfilled//否飞哦的
race//瑞四
catch//开齿
then//z人刃
你对闭包的理解?
函数内部访问函数外部的变量就是闭包,闭包的作用是将数据私有化,
外部访问函数内部的变量,闭包的缺点是会引起内存的泄露。
“*闭包并不会引起内存泄漏*,只是由于IE9之前的版本对JScript对象
和COM对象使用不同的垃圾收集,从而导致内存无法进行回收,这是IE的
问题,所以闭包和内存泄漏没半毛钱关系。
举个例子↓:
function fn(){
let i = 0
function fn2(){
i++
console.log(i)
}
return fn2
}
var fun = fn()
fun()
什么是防抖,节流,以及他们的区别?
防抖:
防抖就是在事件触发后n秒内只能执行一次这个函数,如果再次执行这个事件就
重新计算秒数,当事件不被触发n秒后执行一次这个函数。
节流就是连续触发一个事件但是在n秒钟只执行一次回调。
举个例子↓:
节流就是技能CD,蓝,冷却, 只要冷却没好你就用不了技能。 防抖就是回城,
只要你被敌人打断就要重来。
说一下你对this指向的理解?
this指向在函数定义时是确定不了的,只有函数执行的时候才能确定this到底指向谁
1.全局作用域或者普通函数中this指向全局对象的window,
2.定时器中,this也指向全局对象的window,
3.方法调用中谁调用this,this就指向谁
4.构造函数中this指向构造函数的实例
什么是作用域,你的理解?
作用域分为全局作用域和局部作用域↓
全局作用域:
就是在全局作用域中声明的变量,任何地方都可以被访问,声明变量时不适用任何关键
字声明的变量为全局变量,为window对象动态添加的属性默认也是全局变量,var不推
荐,尽量少声明全局变量,防止全局变量的污染。
局部作用域分为以下两种↓
函数作用域:
函数内部声明的变量只有在函数内部可以访问,外部无法访问,函数的参数也是函数内
部的变量,当函数执行完之后函数内部的变量就被清空了。
块作用域:
let,const ,{}包裹的代码称为代码块,代码块内部用let声明的变量外部将无法被访
问,let声明的变量会产生块作用域,var不会产生块作用域,不同代码块之间的变量无
法相互访问,推荐使用let 和 const声明变量。
箭头函数和普通函数有什么区别?
1.普通函数存在变量提升,箭头函数没有
2.普通函数this指向,谁调用指向谁,箭头函数是在哪里定义就指向谁
3.普通函数可以当成构造函数,而箭头函数是不可以
4.箭头函数没有arguments,如果要接受所有的参数用...rest
let,var,const的区别?
let 没有变量的提升,有块级作用域,不能重复声明,有暂时性死区
const 没有变量提升,声明的变量为常量,一旦定义值不能改变,有块级作用域
var 有变量的提升,没有块级作用域,可重复声明
- 不使用 `var`
- `const` 优先,`let` 其二
es6的新特性有哪些?
1.新增了块级作用域例如:let,const
2.新增了定义类的语法例如:class
3.新增了一种基本数据类型例如:Symbol
4.新增了变量的结构赋值
5.新增了箭头函数,数组新增了一些api,如 isArray/from/of 等...
6.对象和数组新增了扩展运算符 ... 和模块化 import/export
async函数是什么?和await的区别?
async 函数是什么? 他就是Generator 函数的语法糖
async 是异步的意思,await是等待的意思。
await不能调用async函数,async函数调用与普通函数
没有区别。await只能在async中使用。
//怎么读?
Generator// 津里瑞特
return 的作用?
return 后面的代码不会被执行,return只能返回一个值,
函数如果有return 返回return后面的值并且只能返回一个值,
如果没有return 返回undefined
对象的创建方式有哪些?
通过字面量, new方式,构造函数(首字母大写),新增了类(class)创建
1.字面量:var obj={属性:属性值}
2.new:var obj=new Object()
3.构造函数↓:
function Fn(name,age){
this.name=name,
this.age=age
}
var obj=new Fn('小明',18)
4.类class ↓:
class fn{
constructor(name,age){
this.name=name,
this.age=age
}
}
var obj=new fn('小明',18)
new做了几件事?
通过new创建了一个新的对象和属性。
将构造函数的作用域赋值给新对象所以此时的this指向新对象。
执行构造函数的代码,为整个新对象添加属性,如果函数有返回值这个值是非
空对象就返回这个对象否则返回新对象。
什么是原型链,你的理解?
任何对象都有原型对象,也就是prototype属性,所有的对象都是通过new来创建的,任
何原型对象也是一个对象,拥有_proto_属性,这样一层一层向上找的过程就形成了链式
结构,这就是原型链。
什么是原型?
每一个构造函数都有一个prototype属性,指向原型,这就是原型对象。
构造函数存在哪些问题?
每创建一个对象,就会创建一个方法,生成一个新的内存空间,方法功能都是相同的,
就造成了资源的浪费。
什么是递归?
递归就是函数自己调用自己,写出递归公式找到终止条件。缺点:会导致内存泄露,内存泄露
就是使用过的方法或变量无法被垃圾回收机制回收,垃圾回收机制是自动把我们使用过不需要
的变量,方法回收并释放内存,节省性能消耗。
Vue的数据更新流程
生成的新的dom结构和旧的虚拟dom结构对比,利用diff算法找不同,只更新变化的部分
(重绘/回流)到页面这个过程也叫打补丁。
好处:
提高了更新dom的性能不用把页面删除重新渲染
虚拟dom只包含必要的属性没有真实dom上面的几百个属性
什么是重绘/回流?
重绘:不影响布局,只是页面的标签发生改变。
回流:当浏览器必须重新处理一部分或全部页面时就会触发回流。
回流必定引发重绘,但重绘不一定引发回流
diff算法如何比较新旧虚拟dom元素?
同级比较:
根元素改变:删除重新创建整个dom树
根元素未变:属性改变,Dom复用,只更新属性
v-for的更新检测理解?
子元素或者内容改变diff分两种情况比较
有key值 按key比较 无key值 就地更新
key值的要求是?
唯一不重复的字符串或数字
key如何使用? 有id用id没有id用下标
key的好处
配合虚拟dom提高更新的性能
vue是如何提高更新性能的?
vue采用了虚拟Dom结合diff算法提高了vue的性能
虚拟Dom
什么是虚拟DOM:虚拟dom本质上是一个js对象保存DOM关键信息
虚拟DOM的好处↓
1.提高DOM更新的性能,不频繁操作真实DOM
2.在内存中找到变化的部分,再更新真实DOM(打补丁)
mixins是什么?可以做什么?
混入(mixins) 分发vue组件中可复用的功能,一个混入对象可以包含任意组件选项,例
如:data,computed,methods 当组件使用混入对象时,所有混入对象的选项将被混合
进入该组件本身的选项。
1.多个组件都引入该混入,一个组件中改动了mixins中的数据,另一个引入了mixins的组
件不会受到影响
2.data数据冲突:mixin中的data数据和组件的data数据冲突时,组件中的data覆盖mixin
中的数据。
3.生命周期函数:由于生命周期函数命名是统一的,所以不算冲突,vue会先执行混入里面的
代码再执行组件中的代码,就相当于合并了。
混入(mixins)的优缺点
优点:提高代码的复用性,只需要修改一个地方其他组件都会改变。
缺点:命名冲突,滥用的话后期难以维护,排查不方便
插槽
插槽可以将子组件中的数据传递给父组件,父组件在通过slot标签修改组件的内容以及逻辑
操作。通过slot标签也可以接收写在组件标签内的数据
匿名插槽:
组件使用slot占位,使用组件时<组件名></组件名>中间使用slot 内写内容。
具名插槽:
在slot上定义name属性,使用组件时,在template上通过v-slot:name属性值
给对应的slot传递标签 v-slot:可以简写为#号
作用域插槽:
在子组件中用slot标签括起来绑定name属性和值
在父组件中的子组件标签上通过template绑定#name值 或v-slot="name值"
如何获取DOM元素?
通过id或者ref属性获取原生Dom元素,通过ref可以获取组件实例
$nextTick 是什么?如何使用?
$nextTick是处理异步dom元素的,DOM更新完执行$nextTick,直接通过$refs操作dom元素无法
获取到dom元素,因为dom元素是异步更新的必须用$nextTick才可以。
代码示例↓:
使用时:在标签中绑定ref=‘值’ 在事件中↓
this.$nextTick(()=>{
this.$refs.值.focus()//实现自动获取焦点
})
//怎么读?
## nextTick //耐可替可
组件name属性如何使用?以及好处有哪些?
我们封装组件的时候,组件名不能随意写,使用驼峰命名法,自己定义组件名,
name属性和组件名一致,让使用者有统一的前缀(zhui)风格。获取组件自身
什么是单向数据流?
数据从父组件传递到子组件,子组件没有权利修改父组件,如果要修改可以通知
父组件去修改。
获取Dom的方式有哪些有什么区别?
获取Dom元素的方式有两种:
1.通过ref属性获取:
给标签绑定ref属性,通过this.$refs.值可以获取获取到dom元素
给组件标签绑定ref,通过this.$refs.值可以获取到组件实例
2.通过document获取:
给标签绑定id或class类名或直接获取标签,
通过document.getElementByid获取,
和document.querySelector //快瑞四唻可特
以及document.querySelectorAll //快瑞四唻可特奥
3.他们的区别就是:
document获取没有组件之分,范围广泛,this.$ref找的是整个组件,只能
在当前组件中获取
diff算法如何比较新旧虚拟Dom
同级比较:
如果根元素变化删除重新创建整个Dom树
如果根元素未变:属性改变Dom复用,只更新属性。
call、apply、bind修改this指向
call、apply、bind都可以改变函数内部的this指向。
call和apply会调用函数,并且改变函数的内部的this指向。
call和apply参数传递的方式是不一样的:
call参数是以列表的方式传递,apply参数是以数组的方式传递。
bind不会调用函数,可以改变函数内部this指向。
//怎么读?
call //靠
apply//阿破类
bind//半的
垃圾回收机制是什么?
垃圾回收机制就是为了防止内存泄露,当我们使用过的函数以及变量,
垃圾回收机制会自动帮我们回收并释放内存,缓解内存压力。
内存泄露就是我们不需要的内存还存在没有被释放就会导致垃圾回收机制无法回收。
什么是内存泄露?
内存泄露就是我们不使用的内存还存在内存当中,导致垃圾回收机制无法进行回收,
一次内存泄露可能对我们没有影响,但是多次内存泄露会导致性能下限。这就是我对内存泄露的理解。
生命周期
初始化阶段:
new Vue实例化,初始化事件和生命周期函数,钩子函数执行beforeCreate,
钩子函数执行完成实例创建created
挂载阶段:
编辑模板-是否有el选项:
如果有继续检查template选项,返回return函数。生命周期函数执行beforeMount,
真实Dom挂载完毕执行mounted。
如果没有,编译el选项对应的标签作为template,把虚拟Dom和渲染的数据一并挂到
真实Dom上,真实Dom挂载完毕执行mounted。
更新阶段:
data数据改变 更新Dom之前,生命周期钩子函数执行beforeUpdate,虚拟Dom重新渲染,
打补丁到真实Dom,生命周期函数执行updated。此时如果数据继续改变重复执行这个循环
销毁阶段:
当$destory被调用,比如组件Dom被移除v-if,生命周期钩子函数执行beforeDestory,
卸载事件监听器,手动销毁定时器,生命周期钩子函数执行Destoryed。
什么是作用域链?
函数内部创建新的函数,就产生了新的函数作用域,作用域就产生了嵌套关系
作用域链的本质 是底层的变量查找机制,函数被执行时 会优先查找当前函数
作用域中的变量,如果找不到则会
逐级查找父级作用域直到全局作用域 ,全局找不到 变量返回undefined 函数调用报错
1:子作用域能够访问父作用域 父作用域无法访问子作用域
继承是什么?如何实现?
1.继承简单来说就是让子类继承父类的属性或方法。
2.通过extends结合super实现继承,子类必须在constructor方法中调用super,super必须
在子类this之前去调用,在继承中如果实例化子类输出一个方法,先看子类有没有这个方法,
有就执行子类方法,如果没有就去父类查找,有就执行父类的方法,如果还没有调用就报错。
//怎么读?
constructor//肯四chua可特
super//苏婆
extends//艾克斯淡四
继承简单来说就是让子类继承父类的属性或者方法。
我们常用的继承有四种,分别是,call继承,原型继承,class类继承,call+原型混合继。
1.call继承是在子类中调用call方法,修改this指向,让this指向父类的属性和方法,这样
就可以在子类访问父类的属性和方法,但是call有个缺点,就是不能继承原型上的属性和方法
2.原型继承就是将父类的实例放在子类的原型上,这样就可以通过子类实例去继承父类的属性
和方法,缺点就是原型实例的父类祖先原型改变,实例就会改变。
3.混合继承就是call+原型继承,混合继承的缺点就是被父类调用两次,浪费资源。
4.class继承的关键字是extends,子类通过extends来继承父类的属性和方法,子类通过sup
er关键字,访问父类的属性方法,super必须在子类this之前去调用,添加方法的话可以在
constructor下面直接调用
//怎么读?
constructor//肯四chua可特
extends//艾克斯淡四
call//靠
响应式总结
1.所谓的响应式就是指拦截对象属性和方法,插入一些我们想要做的事。
2.js中实现响应式拦截的方法Object.defineProperty和Proxy劫持对象整体+惰性处理,
对象代理。
3.vue中date的数据,不管层级多深,不管会不会用到这个数据,都会进行递归响应式处理
,如非必要尽量不要添加太多冗(rong)余的数据在data中。
//怎么读?
defineProperty//弟饭po揉po蹄
深浅拷贝的理解?
深拷贝:
深拷贝开辟的是一个新的栈,两个对象属性完全相同,但是对应两个不同的地址,
修改一个对象的属性另一个对象的属性不会改变。
浅拷贝:
拷贝的是外层,内层拷贝的是引用地址,如果属性是基本类型,拷贝的就是基本
类型的值,如果属性是引用类型,拷贝的就是内存地址。
Set和Map的使用,以及理解。
Set本质是一个构造函数,用来生成set数据结构,由于set是构造函数所以首字母要大写。
Set函数可以接收数组并可以自动去重。
Set实例的属性和方法↓
.constructor:构造函数,默认就是Set函数。
.size:返回Set实例的成员总数量。
.add:添加某个值,返回Set结构本身
.delete:删除某个值,返回一个布尔值,表示是否成功。
.has:返回一个布尔值,表示该值是否是Set的成员。
.clear:清除所有成员,没有返回值
Map是Es6中新增的数据结构↓
map类似于对象,单在普通对象的key必须是字符串或者数字,而Map的key值可以使任意数据类型...
size:获取成员数量
set:设置成员key和value
get:获取成员的属性
has:判断成员是否存在
delete:删除成员
clear:清空所有
Vuex中的五大核心以及使用方式
state:储存数据状态 //四嘚特 state获取
getters:类似于计算属性 //盖特四 getters
mutations:在这里写逻辑操作类似于方法 //木有忒申
actions:异步执行的代码 //阿可申四
modules:模块化利用模块化写vuex数据 //毛豆四
使用分为两种,一种直接获取行内,一种映射方式。
store //四道儿
dispatch//底四怕吃
commit//可米特