前端面试题

1.闭包

闭包:
定义 当一个函数的返回值是另外一个函数,而返回的函数如果调用了父函数的内部变量,且返回的那个函数在外部被执行,就产生了闭包.

闭包的三个特性
1:函数套函数
2:内部函数可以直接访问外部函数的内部变量或参数
3:变量或参数不会被垃圾回收机制回收

闭包的优点:
1:变量长期驻扎在内存中
2:避免全局变量的污染
3:私有成员的存在

闭包的缺点
常驻内存 增大内存的使用量 使用不当会造成内存的泄露.

调用方式:
//1:直接调用
a()()//内部函数的执行

//2:通过赋值在调用var f = a(); f()

2.作用域

作用域分为全局作用域和局部作用域

全局作用域:变量在函数或者代码块{ }外定义,即为全局作用域。

局部作用域:在函数内部定义的变量,就是局部作用域。局部作用域内,对外是封闭的,从外层的作用域无法直接访问函数内部的作用域

作用域链:自由变量的向上级作用域一层一层查找,直到找到为止,最高找到全局作用域,就形成了作用域链。

3.继承

class继承:

class 相当于es5中构造函数

class中定义方法时,前后不能加function

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

class和方法内默认都是严格模式

ES5中继承:原形链继承+构造函数继承

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

缺点: 引用类型值的属性会被所有实例共享。

借用构造函数继承:在子类,使用call()调用父类方法,并将父类的this修改为子类的this.就是把父类的实例属性复制了一份放到子类的函数内

优点:
1 可以传递参数
2 解决了原型中所有实例共享的问题

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

4.原型

原形链:

每个函数都有一个prototype,叫做显示原型
每个实例都有一个_proto_,叫做隐式原型
实例的隐式原型指向构造的显示原型

prototype constructor protp三者之前区别关系?

实例化和原型对象的constructor属性指向构造函数

构造函数prototype指向原型对象

实例化对象的_proto_指向原型对象

5.promise 手写异步加载图片

promise是一个容器,里面保存异步操作的结果

promise是一个对象,可以获取异步操作的最终状态(成功/失败)

promise是一个构造函数,对外提供统一的API自身上有all,reject,resolve等方法,原型上有then,catch方法

promise两大特点

promise对象状态不受外界影响

promise的状态一旦改变,不会在变,任何时候都可以得到这个结果,状态不可逆,只能由pending变成fulfilled或者pending变成rejected

三种状态:pending初始状态 fulflled成功状态 rejected失败状态


function loadImg(src){
    return new Promise((resove,reject)=>{
        const img = document.createElement('img')
        img.onload = ()=>{
            resove(img)
        }
        img.onerror = ()=>{
            let err = new Error('图片加载失败')
            reject(err)
        }
        img.src = src
    })
}

const url = 'https://qiniu.img.newtechcollege.com/c70fc3da'
const url2 = 'http://qiniu.newtechcollege.com/6dd24cb4'

loadImg(url).then(img => {
    console.log(img.width)
    return img
}).then(img=>{
    console.log(img.height)
    return loadImg(url2)
}).then(img => {
    console.log(img.src)
    return img
}).then(img=>{
    console.log(img.height)
})

6.async/await

async 是“异步”的简写, async 用于声明一个异步的 function

await 可以认为是 async wait 的简写,await 用于等待一个异步方法执行完成。

特点:

asayc的用法,它作为一个关键字放到函数前面,这样普通函数就变为了异步函数
异步async函数调用,跟普通函数的使用方式一样
异步async函数返回一个promise对象
async函数配合await关键字使用是异步方法,但是阻塞式的

7.双向数据绑定

vue的双向数据绑定只要是采用数据劫持结合开发者和订阅者方式 通过Object.defineProperty()来劫持各个属性的setter,getter, 在数据变动时发布消息给订阅者,触发相应监听回调

vue的数据双向绑定 将MVVM作为数据绑定的入口,整合Observer,Compile和Watcher三者。 通过Observer来监听自己的model的数据变化,通过Compile来解析模板指令。

8.vitral Dom

virtual-dom(简称vdom)的概念得益于react的出现react这个框架的非常重要的特性之一。

在vue的整个应用生命周期当中,每次需要更新视图的时候便会使用vdom

vdom算法是基于snabbdom算法所做的修改。

实现
①用js对象构造一个虚拟的dom树,插入到文档中;
②状态变更时,记录新树和旧树的差异;
③把上面的差异构建到真正的dom中

9.vuex

Vuex 是适用于 Vue.js 应用的状态管理库,为应用中的所有组件提供集中式状态存储与操作,保证了所有状态以可预测的方式进行修改。

优点 当state中定义一个数据后,可以在所在项目的任何组件中进行获取,修改,修改可以得到全局的变更

运行机制:vue提供数据来驱动试图,通过dispath派发actions,通过commit调用mutations的方法,修改state的数据

①state:定义初始数据。

②mutations:更改Vuex的store中的状态的唯一方法是提交mutation

③getters:可以对 state 进行计算操作,它就是 store 的计算属性虽然在组件内也可以做计算属性

④actions:异步操作初始数据,其实就是调用mutations里面的方法。

⑤module:面对复杂的应用程序,当管理的状态比较多时;我们需要将vuex的store对象分割成模块(modules)。

10.keep-alive?

<keep-alive> 标签:是Vue的内置组件,在组件切换过程中将状态保留在内存中,取消组件的销毁函数,防止重复渲染DOM

当用它包裹 <router-view> 时,会缓存不活动的组件实例,而不是销毁它们。

<transition> 相似,它自身不会渲染一个 DOM 元素。

使用 <keep-alive> 组件后即可使用 activated() 和 deactivated() 这两个生命周期函数

11.组建通信?

父组件传到子组件 通过props属性给子组件通信的

子组件向父组件传值 父组件通过自定义事件,接受子组件传递来的参数,子组件通过$emit触发父组件上的自定义事件发送参数

ref通信:ref可以为自己的dom做出独有的标记,利用this.$refs来获取从而操作

兄弟通信:bus事件

  1. 在其中一个组件的 挂载钩子函数上做事件的声明
  2. 在另一个组件中通过bus.$emit("")来触发这个自定义事件

12.自定义组件

在子组件中创建模板,在props中接受父组件传递的数据,在父组件中引入子组件,然后在components中创建子组件,挂载到父组件的template中

props 父传子使用 $emit(参1,参2)子传父时使用 参1是自定义的事件名,参2是要传递的数据,在父组件的子组件中绑定自定义事件名,调用一个函数,函数的形参就是传递的数据

13.自定义指令

自定义指令分为:全局自定义指令,局部自定义指令。

钩子函数

一个指令定义对象可以提供如下几个钩子函数 (均为可选):
inserted:被绑定元素插入父节点时调用。

bind:只调用一次,指令第一次绑定到元素时调用。

update:所在组件的 VNode 更新时调用

componentUpdated:指令所在组件的 VNode 及其子 VNode 全部更新后调用。

unbind:只调用一次,指令与元素解绑时调用。

**指令钩子函数会被传入以下参数:
**
el:指令所绑定的元素,可以用来直接操作 DOM 。
binding:一个对象,包含以下属性:
name:指令名,不包括 v- 前缀。
value:指令的绑定值,例如:v-my-directive=“1 + 1” 中,绑定值为 2。
oldValue:指令绑定的前一个值,仅在 update 和 componentUpdated 钩子中可用。无论值是否改变都可用。
expression:字符串形式的指令表达式
arg:传给指令的参数
modifiers:一个包含修饰符的对象
vnode: Vue编译生成的虚拟节点
oldVnode:上一个虚拟节点,仅在 update 和 componentUpdated 钩子中可用。

14.路由守卫

全局路由守卫有个两个:一个是全局前置守卫,一个是全局后置守卫

全局导航钩子:一般用来判断权限,以及页面丢失时需要执行的操作;
beforeEach()每次路由进入之前执行的函数。
afterEach()每次路由进入之后执行的函数。
beforeResolve()2.5新增

单个路由(实例钩子):某个指定路由跳转时需要执行的逻辑。
beforeEnter() beforeLeave()

组件路由钩子
beforeRouteEnter()
beforeRouteLeave()
beforeRouteUpdate()

**路由独享守卫:**路由独享守卫是在路由配置页面单独给路由配置的一个守卫

15.生命周期函数

beforeCreate(创建前):data 和 methods 的数据没有初始化

created(创建后):data和methods中的数据已经初始化完毕

beforeMount(载入前):模板编译好了,没有挂载到页面,页面此时是旧的

mounted(载入后):此时页面已经渲染完毕,这个是最早可以操作dom的钩子函数

beforeUpdate(修改前):页面显示的数据旧的,data的数据是新的

updated(修改后):页面于data的数据已经同步

beforeDestroy(销毁前):该钩子函数执行的时候,数据还可以使用

destroyed(销毁后):数据已经销毁完毕

activated(keep-alive组件激活调用)

deactivated(keep-alive组件停用调用)

errorcapture(捕获来自子孙组件错误是调用)

16.跨域(jsonp,vue)

理解跨域的概念:协议、域名、端口都相同才同域,否则都是跨域

jsonp 实现原理:主要是利用动态创建 script 标签请求后端接口地址,然后传递 callback 参数,后端接收 callback,后端经过数据处理,返回 callback 函数调用的形式,callback 中的参数就是 json

优点:浏览器兼容性好,

缺点:只支持 get 请求方式

vue跨域: 在vue.config.js的空文件中,配置文件

  • target:要访问的接口的基础地址

  • changeOrigin:是否可以跨域

  • secure:是否进行 https 验证

  • pathRewrite:将 api 替换成 ’ ’ 中的值

17.常见状态码

200 OK //客户端请求成功
400 //客户端请求有语法错误,不能被服务器所理解
401 //请求未经授权
403 //服务器收到请求,但是拒绝提供服务
404 //请求资源不存在,输入了错误的 URL
500 //服务器发生不可预期的错误
503 //服务器当前不能处理客户端的请求,一段时间后可能恢复正常

18.项目流程

创建脚手架下载element -ui 配置路由 创建登入页面 在element-ui复制表单 和表单验证 把账号密码进行绑定 根据接口判断登入状态是否 !=200登入失败,==200登入成功 this.$router.push 跳转到后台首页,存入token值 登入完成进行后台首页基本布局 分为头部区域 主题区域 侧边栏 进行相对应的css布局 然后配置axios拦截器 进行token验证 在main.js中添加代码,在将axios挂载到vue原型 请求侧边栏数据 通过v-for双重循环渲染左侧菜单 根据左侧菜单的路由制作相应的用户管理,权限管理,商品管理,订单管理,数据统计根据项目文档完成里面对应的功能.

19.深拷贝 手写代码

深拷贝复制变量值,对于非基本类型的变量,则递归至基本类型变量后,再复制。 深拷贝后的对象与原来的对象是完全隔离的,互不影响, 对一个对象的修改并不会影响另一个对象。

为什么要使用深拷贝: 我们希望在改变新的数组(对象)的时候,不改变原数组(对象)

可 以 使 用 for in 、 Object.assign 、 扩 展 运 算 符 … 、Array.prototype.slice()、Array.prototype.concat() 、递归等递归函数实现深拷贝

20.输入url到页面出现发生了什么

大致过程是这样的:

\1 DNS 解析

\2. TCP 连接

\3. 发送 HTTP 请求

\4. 服务器处理请求并返回需要的数据

\5. 浏览器解析渲染页面

\6. 连接结束

这里会延伸出问 http 状态码,和三次握手和四次挥手相关问题:

三次握手
第一次握手
客户端向服务端发送连接请求报文段。请求发送后,客户端便进入 SYN-SENT 状态。

第二次握手
服务端收到连接请求报文段后,如果同意连接,则会发送一个应答

第三次握手
当客户端收到连接同意的应答后,还要向服务端发送一个确认报文段,表示: 服务端发来的连接同意应答已经成功收到。

CP 连接的释放一共需要四步,因此称为『四次挥手』。
TCP 连接是双向的,因此在四次挥手中,前两次挥手用于断开一个方向的连接,后两次挥手用于断开另一方向的连接。

21.虚拟DOM和diff算法

虚拟dom就是用对象的方式区代真实的dom操作。

当页面打开时浏览器解析HTML元素,构建一个dom树,将状态保存起来,在内存中模拟dom操作,又会生成一个dom树,两个进行比较,根据diff算法找出不同的地方,之渲染一次不同的地方

diff算法就是进行虚拟节点对比,并返回一个patch对象,用来存储两个节点不同的地方,最后用patch记录的消息去局部更新Dom

22.vue组件中的data为什么是一个函数

data是一个函数时,每个组件实例都有自己的作用域,每个实例相互独立,不会相互影响。

Object是引用数据类型,如果不用function返回,每个组件的data都是内存的同一个地址,一个数据改变了其他也改变了

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)四部分组成。
标准模式下: 一个块的总宽度(页面中占的宽度)= width + margin(左右) + padding(左右) + border(左右)

怪异模式下: 一个块的总宽度= width + margin(左右)(即width已经包含了padding和border值)(IE浏览器)

26.什么是内存泄漏

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

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

27.原生Ajax的创建过程

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

28.事件冒泡,事件捕获,事件流

事件冒泡:事件冒泡会从当前触发的事件目标一级一级往上传递,依次触发,直到document为止。
事件捕获:事件捕获会从document开始触发,一级一级往下传递,依次触发,直到真正事件目标为止。
事件流:DOM结构是一个树型结构,当一个HTML元素产生一个事件时,该事件会在元素结点与根结点之间的路径传播,路径所经过的结点都会收到该事件,这个传播过程可称为DOM事件流。

29.阻止事件冒泡

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

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

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

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

31.let、const、var 的区别

var声明的变量存在变量提升,变量可以声明之前调用
let和const不存在变量提升
let和const存在暂时性死区
var允许重复声明变量, let和const在同一作用域不允许重复声明变量
var不存在块级作用域,let和const存在块级作用域.
var和let可以修改声明变量
const声明的变量不能改变一但改变立即初始化,不能留到以后赋值

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. for in 与 for of的区别

for of 遍历数组
用于对数组或者对象的属性进行循环操作。

for in 遍历对象
for…of循环可以使用的范围包括数组、Set 和 Map 结构、某些类似数组的对象,以及字符串

36.数组操作方法

在这里插入图片描述

37.字符操作方法

在这里插入图片描述

38.水平垂直居中

  <div id="box">
        <div id="x"></div>
  </div>

方法一:父相自绝后,子分部向左向上移动本身宽度和高度的一半(也可以用 transform:translate(-50%,-50%))最常用方法

  #box{
         width: 400px;
         height: 400px;
         background: red;
         position: relative;
     }
     #x{
         width: 200px;
         height: 200px;
         background: yellow;
         position: absolute;
         left: 50%;
         top: 50%;
         margin-left: -100px;
         margin-top: -100px;
     }

方法二:父元素设置成弹性盒,子元素横向居中,纵向居中

 #box{
         width: 400px;
         height: 400px;
         background: red;
         display: flex;
         justify-content: center;
         align-items: center;
    
     }
     #x{
         width: 200px;
         height: 200px;
         background: yellow;
       
     }

方法三:父向子绝,子元素所有定位为0,margin设置auto自适应。

  #box{
         width: 400px;
         height: 400px;
         background: red;
         position: relative;
     }
     #x{
         width: 200px;
         height: 200px;
         background: yellow;
         position: absolute;
         left: 0;
         top: 0;
         right: 0;
         bottom: 0;
         margin: auto;
       
     }

39.null和undefined区别

在JavaScript中,null 和 undefined 几乎相等
null和undefined区别:
null表示没有对象,可能将来要赋值一个对象,即该处不应该有值
undefined表示缺少值,即此处应该有值,但没有定义

40.箭头函数

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

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值