41道精简前端必备面试题(置顶中)

35 篇文章 1 订阅
22 篇文章 0 订阅

Vue偷懒必备      参考手册       面试题库

 


1.组件通信

  • 父传递子如何传递
  •  (1)在父组件的子组件标签上绑定一个属性,挂载要传输的变量
  •  (2)在子组件中通过props来接受数据,props可以是数组也可以是对象,接受的数据可以直接使用 props:["属性 名"] props:{属性名:数据类型}
  • 子传递父如何传递
  • (1)在父组件的子组件标签上自定义一个事件,然后调用需要的方法
    (2)在子组件的方法中通过 this.$emit("事件")来触发在父组件中定义的事件,数据是以参数的形式进行传递的

  • 兄弟组件如何通信
  •       (1)在src中新建一个Bus.js的文件,然后导出一个空的vue实例
         (2)在传输数据的一方引入Bus.js  然后通过Bus.$emit(“事件名”,"参数")来派发事件,数据是以$emit()的参数形式来传递
         (3)在接受的数据的一方 引入 Bus.js 然后通过 Bus.$on("事件名",(data)=>{data是接受的数据})

2.自定义指令

   

  • 【全局指令】
    使用 Vue.diretive()来全局注册指令。
    【局部指令】
    也可以注册局部指令,组件或 Vue 构造函数中接受一个 directives 的选项。

    钩子函数。指令定义函数提供了几个钩子函数(可选)。

  • 钩子函数
  • 有哪些钩子函数,及自定义指令的使用场景                                                                                                                                                                                                                                                       
  • bind(){} 只调用一次,指令第一次绑定到元素时调用
  • inserted(){}被绑定元素插入父节点时调用
  • update(){}被绑定元素所在的模板更新时调用,而不论绑定值是否变化
  • componentUpdated(){}被绑定元素所在模板完成一次更新周期时调用
  • unbind(){}只调用一次, 指令与元素解绑时调用
  • 指令钩子函数会被传入以下参数:

    el:指令所绑定的元素,可以用来直接操作 DOM 在每个函数中,第一个参数el ,表示被绑定了指令的那个元素,这个 el 参数,是一个原生的JS对象,。
    binding:一个对象,包含以下属性:
    name:指令名,不包括 v- 前缀。
    value:指令的绑定值,例如:v-my-directive=“1 + 1” 中,绑定值为 2。

  •   vue自定义指令

3.Vue中双向数据绑定是如何实现

 

vue.js是采用数据劫持结合发布者-订阅者模式的方式,通过Object.defineProperty()来劫持各个属性的settergetter,在数据变动时发布消息给订阅者,触发相应的监听回调来渲染视图。

  • 第一步: 需要observer的数据对象进行递归遍历,包括子属性对象的属性,都加上 setter和getter
    这样的话,给这个对象的某个值赋值,就会触发setter,那么就能监听到了数据变化

    第二步: compile解析模板指令,将模板中的变量替换成数据,然后初始化渲染页面视图,并将每个指令对应的节点绑定更新函数,添加监听数据的订阅者,一旦数据有变动,收到通知,更新视图

    第三步: Watcher订阅者是ObserverCompile之间通信的桥梁,主要做的事情是:
    1、在自身实例化时往属性订阅器(dep)里面添加自己
    2、自身必须有一个update()方法
    3、待属性变动dep.notice()通知时,能调用自身的update()方法,并触发Compile中绑定的回调,则功成身退。

    第四步: MVVM作为数据绑定的入口,整合Observer、Compile和Watcher三者,通过Observer来监听自己的model数据变化,通过Compile来解析编译模板指令,最终利用Watcher搭起Observer和Compile之间的通信桥梁,达到数据变化 -> 视图更新;视图交互变化(input) -> 数据model变更的双向绑定效果。

  • Object.defineProperty(obj, prop, descriptor)

    参数:

    obj: 必需。目标对象;
    prop: 必需。需定义或修改的属性的名字;
    descriptor: 必需。目标属性所拥有的特性;

4.简述虚拟DOM和React diff算法

  • 虚拟dom是利用js描述元素与元素的关系
  • 好处:是可以快速的渲染和高效的更新元素,提高浏览器的性能
  • diff算法
  • 优点:最终表现在DOM上的修改只是部分的变更,可以保证高效的渲染,提高网页的性能
  • 缺点:首次渲染大量DOM时,由于多了一层虚拟DOM的计算,会比innerHtml慢一点
  • keep-alive是vue提供给我们的一个组件,用来在路由切换的时候保存我们的组件状态
  • 当我们在切换路由需要保存失活组件的状态的时候需要用到,比如我浏览淘宝滑动的中间位置,然后又去购物车页面,再回到首页的时候能够保存住我刚才滑动的位置

    简述虚拟DOM和React diff算法

https://blog.csdn.net/qq_37430247/article/details/110621729

5.keep-alive是什么

keep-alive是Vue提供给我们一个内置组件,他可以用来保存我们路由切换时组件的状态

 1. 全局保存在App.vue中  <keep-alive>把routerView保存起来
​
  2. 部分缓存  
       1、router.js中设置要缓存的页面
       {
                 path: '/child1',
                 name: 'Child1',
                 component: Child1,
                 meta:{
                      keepAlive:true
                 }
       }
       },
       2、用v-if来显示router-view是否在keep-alive中出现
       <keep-alive>
            <router-view v-if="$route.meta.keepAlive"></router-view>
       </keep-alive> 
       <router-view v-if="!$route.meta.keepAlive"></router-view>

6.生命周期共有几个?分别在什么时候使用?

  • 1.创建 beforeCreate() 在执行这个钩子的时候 只有一些实例本身的事件和生命周期函数 用户自定义不能使用 created() 最早开始使用 data和methods中数据的钩子
  • 2.挂载 beforeMount() 指令已经解析完毕 内存中已经生成dom数 mounted()dom已经渲染完毕 页面和内存的数据已经同步
  • 3.更新 beforeUpdate() 当data的数据发生改变会执行这个钩子 内存中数据是新的 页面是旧的 updated() 内存和页面都是新的
  • 4.销毁 beforeDestroy()即将销毁 data和methods中的数据此时还是可以使用的,可以做一些释放内存的操作 destroyed()已经销毁完毕
  • activated(组件激活时):和上面的beforeDestroy和destroyed用法差不多,但是如果我们需要一个实例,在销毁后再次出现的话,用 beforeDestroy和destroyed的话,就太浪费性能了。实例被激活时使用,用于重复激活一个实例的时候
  • deactivated(组件未激活时):实例没有被激活时。
  • errorCaptured(错误调用):当捕获一个来自后代组件的错误时被调用

7.路由守卫

路由钩子函数有三种分别为 全局守卫 单个路由守卫 组件内部守卫

  • 全局守卫钩子 beforeEach
  • 单个路由守卫 beforeEnter
  • 组件内部守卫 beforeRouteEnter   beforeRouteUpdate    beforeRouteLeave 

  • to 对象 去哪儿 from 对象 从哪来 next 函数 next()==next(true) 继续执行 不写next==next(false)终止执行 next(path)跳转

8.vuex是什么

  • state 存储数据 在组件中的使用 this.$store.state.属性名
  • mutations 直接操作state中的数据 在组件中的使用 this.$store.commit("方法名",参数)
  • actions 可以实现异步操作 在actions中操作mutations中的数据 在组件使用 this.$store.dispatch("方法名",参数)
  • getters 类似于计算属性可以对state中数据进行逻辑计算 在组件中 this.$store.getters.方法名
  • modules 将state分模块

9.闭包

函数嵌套函数 当内部函数访问外部函数变量时 就产生了闭包

内部函数可以直接访问外部函数的内部变量或参数
变量或参数不会被垃圾回收机制回收

10.原型和原型链

  • 原型的概念

  • javascript的所有对象都包含一个 proto 属性 这个属性对应的就是自身的原型 JavaScript的函数对象,
  • 除了原型 proto 属性之外 还有 prototype 属性 当函数对象作为构造函数创建实例时,该 prototype 属性值将被作为实例对象原型 proto
  • 原型链的概念
  • 当一个对象调用自身不存在的属性或方法时,就会去自己 proto 关联的前辈 prototype 对象上去找 
  • 如果没找到就接着往上找 直到找到属性或方法 找不到就 返回 undefined 这就是原型链

 

11.作用域

  • js中首先有一个最外层的作用域,全局作用域

  • js中可以通过函数来创建一个独立作用域称为函数作用域,函数可以嵌套,所以作用域也可以嵌套;

  • es6中新增了块级作用域(大括号,比如:if{},for(){},while(){}…) es6作用域,只适用于const,let ;

12.继承

  • Es5中的继承有:

  • 原型继承父类的实例作为子类的原型

  • 构造函数继承:在子类中使用call方法调用父类的方法并将父类的this改成子类的this

    不能继承原型属性/方法,只能继承父类的实例属性和方法

  • 组合继承既能调用父类的实例属性又能调用父类的原型属性

    由于调用了两次父类,所以产生了两份实例

    函数可以复用

  • Es6有class继承
  • class就相当于Es5中的构造函数

  • class中定义方法是前后不能加function,全部都定义在class的prototype属性中

  • class中只能定义方法不能定义对象变量等

  • class默认是严格模式

  • 子类中调用extends方法可以调用父类的属性,用eat调用父类的方法

  •  

  • 13.深拷贝浅拷贝

    图片描述

  • 浅拷贝只复制指向某个对象的指针,不复制对象本身(引用),新旧对象还是共享同一块内存。
  • 深拷贝会另外创造一个一模一样的对象(拷贝的是全部,新对象跟原对象不共享内存,修改新对象不会改到原对象。

 

14.let,const,var的区别

15.解构赋值

  • 解构赋值语法是一种 Javascript 表达式。通过解构赋值, 可以将属性/值从对象或数组中取出,赋值给其他变量。

16.箭头函数和普通函数的区别

 为了解决普通函数this指向问题

  • 匿名函数,不能作为构造函数,不能使用new,

    箭头函数相当于匿名函数,并且简化了函数定义。箭头函数有两种格式:一种只包含一个表达式,连{ … }和return都省略掉。还有一种可以包含多条语句,这时候就不能省略{ … }和return。

  • 箭头函数内没有arguments,可以用展开运算符…解决,arguments是参数的集合, 是一个类数组/伪数组体现在他不能调用数组的方法

  • 箭头函数的this,始终指向父级上下文(箭头函数的this取决于定义位置父级的上下文,跟使用位置没关系,普通函数this指向调用的那个对象)

  • 箭头函数不能通过call() 、 apply() 、bind()方法直接修改它的this指向。(call、aaply、bind会默认忽略第一个参数,但是可以正常传参)

  • 箭头函数没有原型属性

18.什么是promise

19.async和await

他们的优点

  • 方便联机调用,依次发生的场景

  • 同步代码编写方式,从上到下执行

  • 多个参数传递,跟promise不一样,可以当做普通变量来处理,也可以当做块级变量,想怎么用就怎么用,想定义几个变量就定义几个

  • 同步代码和异步代码可以一起编写,不用纠结同步和异步的区别,把异步封装成一个promise对象放在await后面

  • 是对promise的优化,

20.Vue 自定义组件及组件疯装

  • 自定义组件分为三步
  • 引用组件     注册组件   使用组件
  • Vue组件封装(以封装一个button组件为例)
  • 1/在components文件内创建一个button文件,文件内创建一个index.vue文件,在index.vue文件内写的是原型(包含组件的名字,应用的最底层的HTML标签,分别根据什么条件显示什么功能),同时该文件导出的数据为一个对象。
  • 2/在button文件下建立一个index.js文件,文件内对新构建组件的名字进行注册
  • 3/ 与button文件同级建立一个index.js文件,对组件进行注册,同时也注册进install中,在导出时,不仅要引出全局的,而且单个的也要引出,便于局部或全局引用。
  • 4/要在main.js中进行引用
  • 5/到这里,组件便是封装完成了,在App.vue中可以进行使用了

21.Vue项目的开发流程

  • 首先,拿到项目我们应该分析下项目的需求以及思路
  • 其次还要有一个GIT远程仓库,给团队提供便携的开发
  • 然后再看看项目里面的一个大体的开发功能以便做好准备
  • 例如登录:
  • 先必须要有一个表单,然后是按钮,绑定v-model
  • 然后在mehods中定义事件,在mounted中调用接口,在data中定义数据
  • 调用接口拿到数据,然后用状态码判断是否登录成功,成功则跳转到首页,同时存到localstorage中
  • 接着在路由中通过token/localstorage设置路由守卫,达到登录鉴权的目的

22.输入url到页面加载完成发生了什么

  • DNS解析

  • TCP连接

  • 发送HTTP请求

  • 服务器响应请求并返回相应的数据

  • 浏览器解析渲染页面

  • 连接结束

原文:https://blog.csdn.net/qq_37430247/article/details/112002255

 

拓展:

三次握手,四次挥手   https://blog.csdn.net/qq_36903042/article/details/102656641     (终极奥秘)

http协议是什么?

23.HTTP 状态码

  • 1 临时响应
  • 2 成功
  • 3 重定向
  • 4 请求错误
  • 5.服务器错误

23.vue项目打包

一、修改请求静态资源的路径
打开config下的index.js文件,修改assetsPublicPath的值,从‘/’改为‘./’。即从根路径改为相对路径。

build: {
    // Template for index.html
    index: path.resolve(__dirname, '../dist/index.html'),

    // Paths
    assetsRoot: path.resolve(__dirname, '../dist'),
    assetsSubDirectory: 'static',
    assetsPublicPath: './',
 }

二、修改本地图片的路径
打开build下的utils.js文件,增加 publicPath:’…/…/’

if (options.extract) {
  return ExtractTextPlugin.extract({
    use: loaders,
    fallback: 'vue-style-loader',
    publicPath:'../../'
  })
} else {
  return ['vue-style-loader'].concat(loaders)
}

三、在终端运行npm run build。

25.防抖和节流

防抖: 触发高频事件后 定时器内函数只会执行一次,如果定时器内高频事件再次被触发,则重新计算时间
场景:
按钮提交场景:防止多次提交按钮,只执行最后提交的一次。

节流 :高频事件触发,在定时器内只会执行一次,所以节流会稀释函数的执行效率。
1.拖拽场景:固定时间内只执行一次,防止超高频次触发位置变动

2.缩放场景:监控浏览器 resize

3.动画场景:避免短时间内多次触发动画引起性能问题

26.数组去重

indexOf

 
function newArr(array){ 
    //一个新的数组 
    var arrs = []; 
    //遍历当前数组 
    for(var i = 0; i < array.length; i++){ 
        //如果临时数组里没有当前数组的当前值,则把当前值push到新数组里面 
        if (arrs.indexOf(array[i]) == -1){ 
            arrs.push(array[i])
        }; 
    } 
    return arrs; 
}
 
var arr = [1,1,2,5,5,6,8,9,8];
 
console.log(newArr(arr))

Set

function newArr(arr){
    return Array.from(new Set(arr))
}
 
var arr = [1,1,2,9,6,9,6,3,1,4,5];
 
console.log(newArr(arr))

利用递归去重

24.Git指令
git init 初始化git仓库
git status 查看文件状态
git add 文件列表 追踪文件
git commit -m 提交信息 向仓库中提交代码
git log 查看提交记录
覆盖工作目录中的文件: git checkout --文件名
将文件从暂存区中删除: git r m --cached 文件名

git branch 查看分支

git branch 分支名称 创建分支

git checkout 分支名称 切换分支

git merge 来源分支 合并分支 (必须在master分支上才能合并d)

git branch -d 分支名称 删除分支(分支被合并后才允许删除)(-D 强制删除)

将本地仓库推送到远程仓库: git push 项目链接

Git 添加远程仓库origin (origin是仓库别名): git remote add 仓库名 项目链接

git push origin master
git push -u origin master

-u 将推送地址和分支保存,下次推送输入git push即可

25.什么是盒子模型?

在我们HTML页面中,每一个元素都可以被看作一个盒子,而这个盒子由:内容区(content)、填充区(padding)、边框区(border)、外边界区(margin)四部分组成。

26.什么是内存泄漏

程序的运行需要内存。只要程序提出要求,操作系统或者运行时就必须供给内存。

对于持续运行的服务进程,必须及时释放不再用到的内存。否则,内存占用越来越高,轻则影响系统性能,重则导致进程崩溃。

27.原生Ajax的创建过程

1.创建xhr 核心对象
2.调用open 准备发送
3.如果是post请求,必须设置请求头。
4.调用send 发送请求 (如果不需要参数,就写null)
5.监听异步回调
备注:如果是post请求,想要传json格式数据。

28.事件冒泡

事件冒泡:事件冒泡会从当前触发的事件目标一级一级往上传递,依次触发,直到document为止。
事件捕获:事件捕获会从document开始触发,一级一级往下传递,依次触发,直到真正事件目标为止。

29.阻止事件冒泡

1.event.stopPropagation();
事件处理过程中,阻止了事件冒泡,但不会阻击默认行为
2.return false;
事件处理过程中,阻止了事件冒泡,也阻止了默认行为

还有一种有冒泡有关的:
3.event.preventDefault();
它的作用是:事件处理过程中,不阻击事件冒泡,但阻击默认行为

30.箭头函数与普通函数区别

箭头函数是匿名函数不能作为构造函数不能使用new
箭头函数不绑定arguments,需要用运算符解决…解决
箭头函数不绑定this,会捕获其所在的this值,作为自己的this值
箭头函数通过call()或apply()调用一个函数,只传入了一个参数,对this并没有影响.
箭头函数没有原型属性

 

31.跨域解决问题

  1. jsonp

  2. 代理跨域

  3. cors

  4. html5 中的 window.postMessage

  5. 反向代理

  6. 哈希

32.单向数据流和双向绑定

1.Vue 在不同组件间强制使用单向数据流,父组件可以向子组件传递数据,但是子组件不能直接修改父组件的状态。

2.数据的双向绑定
主要由MVVM框架实现,主要由三部分组成View、ViewModel和Model组成,其中view和model不能直接进行通信,他们通过中间件ViewModel来进行通信。

33.图片懒加载

对页面加载速度影响最大的就是图片,一张普通的图片可以达到几M的大小。当页面图片很多时,页面的加载速度缓慢,几S钟内页面没有加载完成,也许会失去很多的用户。

所以,对于图片过多的页面,为了提高加载速度, 我们需要将页面内未出现在可视区域内的图片先不做加载, 等到访问到可视区域后再去加载。这样子对于页面加载性能会有很大的提升,也提高了用户体验。

34.nextTick的理解

使用nextTick的原因:Vue是异步修改DOM的,并且不鼓励开发者直接接触DOM,但是有时候需要必须对数据更改后的DOM元素做相应的处理,但是获取到的DOM数据并不是更改后的数据,这时候就需要this.$nextTick();
原理:Vue通过异步队列控制DOM更新和nextTick回调函数先后执行的方式。

35.判断数据类型的4种方法

instanceof

typeof

object.prototype.toString()

constructor构造函数

https://blog.csdn.net/qq_37430247/article/details/111504352

36.Vue 组件中 data 为什么必须是函数?

  • 使每个组件闭包
  • 容易互相影响
    其实就是一个原因,实例化出来的根组件只有一个,你可以将它写成对象,或者是返回一个对象的函数。但是子组件不够健壮,容易在内存的地址中互相影响,就像我们常用的深浅拷贝所能解决的那样。所以为了防止意外的发生,是不被允许在子组件中使用对象来写data。

当data选项是一个函数的时候,每个实例可以维护一份被返回对象的独立的拷贝,这样各个实例中的data不会相互影响,是独立的。

 

37.mvc和mvvm的区别?(个人总结)

mvc:model模型  view视图   controller控制器

视图请求数据到控制器,控制器向模型获取数据后,模型返回数据到视图渲染

mvvm:model数据  view视图UI  viewmodel控制器 

两者不同的之处在于后者mvvm在处理返回数据时,不需要在将数据传到控制器到视图渲染,这个时候是自动的(双向数据绑定),一端更新,另一端自动更新

https://blog.csdn.net/qq_37430247/article/details/111830286

38.JS中判断数据类型的方法有几种?

最常见的判断方法:typeof

判断已知对象类型的方法: instanceof

根据对象的constructor判断: constructor 

完美的解决方案:Object.prototype.toString.call() 

无敌万能的方法:jquery.type()

39.深度监听

data:{

     return(){

      form:{id:1,name:marry}

        }

},

watch:{

1.监听对象

     form:{

     handler(a,b){

                //代码块   

                }

deep:true   // 默认值是 false,代表是否深度监听

immediate:true   //代表在wacth里立即先去执行handler方法

},

2.监听对象中的一个属性(用字符串)

"form.name":{

     handler(a,b){

                //代码块   

                }

deep:true   // 默认值是 false,代表是否深度监听

immediate:true     //代表在wacth里立即先去执行handler方法

}

}

https://blog.csdn.net/wandoumm/article/details/80259908

40.object.defineproperty()

Object.defineProperty() 方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回此对象。

object.defineproperty(obj,prop,descriptor)有三个参数:

object:必需。目标对象 

propName:必需。需定义或修改的属性的名字

descriptor:必需。目标属性所拥有的特性

https://blog.csdn.net/u011884290/article/details/51941605?

详解object.defineproperty()

41、 sessionStorage localStorage cookie 的区别

1.localStorage 生命周期是永久,这意味着除非用户显示在浏览器提供的UI 上清除 localStorage 信息,否则这些信息将永远存在。存放数据大小为一般为5MB,而且它仅在客户端(即浏览器)中保存,不参与和服务器的通信。
2.sessionStorage 仅在当前会话下有效,关闭页面或浏览器后被清除。存 放数据大小为一般为 5MB,而且它仅在客户端(即浏览器)中保存,不参与和服务器的通信。源生接口可以接受,亦可再次封装来对 Object 和 Array 有更好的支持。

作用域不同
不同浏览器无法共享 localStorage 或 sessionStorage 中的信息。相同浏览器的不同页面间可以共享相同的 localStorage(页面属于相同域名和端口),但是不同页面或标签页间无法共享 sessionStorage 的信息。这里需要注意的是,页面及标
3.cookie 的优点:具有极高的扩展性和可用性
1.通过良好的编程,控制保存在 cookie 中的 session 对象的大小。
2.通过加密和安全传输技术,减少 cookie 被破解的可能性。
3.只有在 cookie 中存放不敏感的数据,即使被盗取也不会有很大的损失。
4.控制 cookie 的生命期,使之不会永远有效。这样的话偷盗者很可能拿到的就是一个过期的 cookie。
4.cookie 的缺点:
1.cookie 的长度和数量的限制。每个 domain 最多只能有 20 条 cookie,每个cookie 长度不能超过 4KB。否则会被截掉。
2.安全性问题。如果 cookie 被人拦掉了,那个人就可以获取到所有 session
信息。加密的话也不起什么作用。
3.有些状态不可能保存在客户端。例如,为了防止重复提交表单,我们需要在服务端保存一个计数器。若吧计数器保存在客户端,则起不到什么作用。 localStorage、sessionStorage、Cookie 共同点:都是保存在浏览器端,且同
源的。

42.原型链,继承和promise

继承和promise

 

  • 2
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值