JS面试题
js数据类型
基本数据类型:Number、String、Boolean、Null、Undefined、Symbol、bigint
引用数据类型:Object、Array、Date、Function、RegExp
js变量和函数的提升
在js中变量和函数的声明会提升到最顶部执行
函数的提升高于变量的提升
函数内部如果用 var 声明了相同名称的外部变量,函数将不再向上寻找
匿名函数不会提升。
闭包
闭包就是能够读取其他函数内部变量的函数
function a(){
let a1 = 1
return function(){
return a1
}
}
闭包基本上就是一个函数内部返回一个函数
好处
可以读取函数内部的变量
将变量始终保持在内存中
可以封装对象的私有属性和私有方法
坏处
比较耗费内存、使用不当会造成内存溢出的问题
== 和 ===的区别
==是非严格意义上的相等
值相等就相等
===是严格意义上的相等,会比较两边的数据类型和值大小
值和引用地址都相等才相等
this
this总是指向函数的直接调用者
如果有new关键字,this指向new出来的对象
在事件中,this指向触发这个事件的对象
js数组和对象的遍历方式
for in
for
forEach
for-of
map与forEach的区别
forEach 方法,是最基本的方法,就是遍历与循环,默认有 3 个传参:分别是遍历的数组内
容 item、数组索引 index、和当前遍历数组 Array
map 方法,基本用法与 forEach 一致,但是不同的,它会返回一个新的数组,所以 callback
需要有 return 值,如果没有,会返回 undefined
箭头函数与普通函数的区别?
函数体内的 this 对象,就是定义时所在的对象,而不是使用时所在的对象
不可以当作构造函数,也就是说,不可以使用 new 命令,否则会抛出一个错误
不可以使用 arguments 对象,该对象在函数体内不存在。如果要用,可以用 Rest 参数代替
不可以使用 yield 命令,因此箭头函数不能用作 Generator 函数
同源策略
所谓同源策略就是浏览器的一种安全机制,未限制不同源的网站不能通信(同源指的是域名、协议、端口号相同)
如何解决跨域
jsonp跨域
document.domain + iframe 跨域
nodejs中间件代理跨域
后端在头部信息里面设置安全域名
严格模式的限制
变量必须声明后再使用
函数的参数不能有同名属性,否则报错
不能使用 with 语句
禁止 this 指向全局对象
es6新增
新增模板字符串
箭头函数
解构赋值
for-of(用来遍历数据—例如数组中的值。)
ES6 将 Promise 对象纳入规范,提供了原生的 Promise 对象。
增加了 let 和 const 命令,用来声明变量。
还有就是引入 module 模块的概念
新增简单的数据类型Symbol,独一无二不会与其他属性名冲突
attribute 和 property 的区别是什么?
attribute 是 dom 元素在文档中作为 html 标签拥有的属性
property 就是 dom 元素在 js 中作为对象拥有的属性。
对于 html 的标准属性来说,attribute 和 property 是同步的,是会自动更新的
但是对于自定义的属性来说,他们是不同步的
var、let、const的区别是什么?
var:存在变量提升;存在变量覆盖;已经被定义赋值的变量,如果再次被赋值,则以后一次值为主;没有块级作用域
const:定义的是常量,声明之后必须赋值;定义的值不能去修改,否则报错;有块级作用域;不存在变量提升和变量覆盖;对于数组和元素的修改,不算做对常量的修改,不会报错
let:有块级作用域;不存在变量提升和变量覆盖;let不允许在相同的作用域中重复声明,注意是相同作用域,不同作用域重复声明不会报错
内存泄漏
定义:程序中己动态分配的堆内存由于某种原因程序未释放或无法释放引发的各种问题。
js中可能出现的内存泄漏情况:结果:变慢,崩溃,延迟大等
js中可能出现的内存泄漏原因
全局变量
dom 清空时,还存在引用
定时器未清除
子元素存在引起的内存泄露
script 引入方式?
html 静态 <script> 引入
js 动态插入 <script>
<script defer> : 异步加载,元素解析完成后执行
<script async> : 异步加载,但执行时会阻塞元素渲染
数组(array)方法
map : 遍历数组,返回回调返回值组成的新数组
forEach : 无法 break ,可以用 try/catch 中 throw new Error 来停止
filter : 过滤
some : 有一项返回 true ,则整体为 true
every : 有一项返回 false ,则整体为 false
join : 通过指定连接符生成字符串
push / pop : 末尾推入和弹出,改变原数组, 返回推入/弹出项
unshift / shift : 头部推入和弹出,改变原数组,返回操作项
sort(fn) / reverse : 排序与反转,改变原数组
concat : 连接数组,不影响原数组, 浅拷贝
slice(start, end) : 包括开头,不包括截取,返回截断后的新数组,不改变原数组
splice(start,number,value…): 返回删除元素组成的数组,value 为插入项,改变原数组
indexOf / lastIndexOf(value, fromIndex) : 查找数组项,返回对应的下标
reduce / reduceRight(fn(prev, cur) ,defaultPrev) : 两两执行,prev 为上次化简函数的return 值,cur 为当前值(从第二项开始)
JavaScript 深浅拷贝?
浅拷贝
Object.assign
深拷贝
可以通过 JSON.parse(JSON.stringify(object)) 来解决
说说异步编程的实现方式?
回调函数
优点:简单、容易理解
缺点:不利于维护、代码耦合高
事件监听
优点:容易理解,可以绑定多个事件,每个事件可以指定多个回调函数
缺点:事件驱动型,流程不够清晰
发布/订阅(观察者模式)
类似于事件监听,但是可以通过‘消息中心’,了解现在有多少发布者,多少订阅者
Promise 对象
优点:可以利用 then 方法,进行链式写法;可以书写错误时的回调函数
缺点:编写和理解,相对比较难
Generator 函数
优点:函数体内外的数据交换、错误处理机制
缺点:流程管理不方便
async 函数
优点:内置执行器、更好的语义、更广的适用性、返回的是 Promise、结构清晰
缺点:错误处理机制
说说面向对象编程思想?
基本思想是使用对象,类,继承,封装等基本概念来进行程序设计
优点
易维护
易扩展
开发工作的重用性、继承性高,降低重复工作量。
缩短了开发周期
项目性能优化
减少 HTTP 请求数
减少 DNS 查询
使用 CDN
避免重定向
图片懒加载
路由懒加载
减少 DOM 元素数量
减少 DOM 操作
使用外部 JavaScript 和 CSS
压缩 JavaScript、CSS、字体、图片等
优化 CSS Sprite
使用 iconfont
多域名分发划分内容到不同域名
尽量减少 iframe 使用
避免图片 src 为空
把样式表放在 link 中
把 JavaScript 放在页面底部
什么是单线程,和异步的关系?
单线程 :只有一个线程,只能做一件事
原因 : 避免 DOM 渲染的冲突
浏览器需要渲染 DOM
JS 可以修改 DOM 结构
JS 执行的时候,浏览器 DOM 渲染会暂停
两段 JS 也不能同时执行(都修改 DOM 就冲突了)
webworker 支持多线程,但是不能访问 DOM
解决方案 :异步
说说负载均衡?
单台服务器共同协作,不让其中某一台或几台超额工作,发挥服务器的最大作用
http 重定向负载均衡:调度者根据策略选择服务器以 302 响应请求,缺点只有第一次有效果,后续操作维持在该服务器 dns 负载均衡:解析域名时,访问多个 ip 服务器中的一个(可监控性较弱)原因 - 避免 DOM 渲染的冲突
反向代理负载均衡:访问统一的服务器,由服务器进行调度访问实际的某个服务器,对统一的服务器要求大,性能受到 服务器群的数量
作用域链?
作用域链可以理解为一组对象列表,包含 父级和自身的变量对象,因此我们便能通过作用域链访问到父级里声明的变量或者函数
什么是原型、原型链、继承?
所有的函数都有prototype属性(原型)
所有的对象都有__proto__属性
在Javascript中,每个函数都有一个原型属性prototype指向自身的原型,而由这个函数创建的对象也有一个proto属性指向这个原型,而函数的原型是一个对象,所以这个对象也会有一个proto指向自己的原型,这样逐层深入直到Object对象的原型,这样就形成了原型链。
JS垃圾回收机制是怎样的?
1.概述
js的垃圾回收机制是为了防止内存泄漏(已经不需要的某一块内存还一直存在着),垃圾回收机制就是不停歇的寻找这些不再使用的变量,并且释放掉它所指向的内存。
在JS中,JS的执行环境会负责管理代码执行过程中使用的内存。
2.变量的生命周期
当一个变量的生命周期结束之后,它所指向的内存就会被释放。js有两种变量,局部变量和全局变量,局部变量是在他当前的函数中产生作用,当该函数结束之后,该变量内存会被释放,全局变量的话会一直存在,直到浏览器关闭为止。
3.js垃圾回收方式
有两种方式: 标记清除、引用计数
标记清除:大部分浏览器使用这种垃圾回收,当变量进入执行环境(声明变量)的时候,垃圾回收器将该变量进行了标记,当该变量离开环境的时候,将其再度标记,随之进行删除。
引用计数:这种方式常常会引起内存的泄露,主要存在于低版本的浏览器。它的机制就是跟踪某一个值得引用次数,当声明一个变量并且将一个引用类型赋值给变量得时候引用次数加1,当这个变量指向其他一个时引用次数减1,当为0时出发回收机制进行回收。
逐进增强和优雅降级
逐进增强
针对低版本浏览器进行构建页面,保证最基本的功能,然后再针对高版本浏览器进行效果、交互等改进和追加功能达到更好的用户体验。
优雅降级
一开始就构建完整的功能,然后再针对低版本浏览器进行兼容
VUE面试题
vue优点
轻量级
速度快
简单易学
低耦合
可重用性
独立开发
文档齐全,且文档为中文文档
vue父组件向子组件传递数据
props
子组件向父组件传递事件
$emit
v-show和v-if指令的共同点和不同点
相同点:都可以控制dom元素的显示和隐藏
不同点:v-show只是改变display属性,dom元素并未消失,切换时不需要重新渲染页面
v-if直接将dom元素从页面删除,再次切换需要重新渲染页面
如果需要频繁的进行元素的显示和隐藏使用v-show性能更好
如何让CSS只在当前组件中起作用
scoped
<keep-alive></keep-alive>的作用是什么
主要是用于需要频繁切换的组件时进行缓存,不需要重新渲染页面
如何获取dom
给dom元素加ref=‘refname’,然后通过this.$refs.refname进行获取dom元素
说出几种vue当中的指令和它的用法
v-model 多用于表单元素实现双向数据绑定
v-bind:简写为:,动态绑定一些元素的属性,类型可以是:字符串、对象或数组。
v-on:click 给标签绑定函数,可以缩写为@,例如绑定一个点击函数 函数必须写在methods里面
v-for 格式: v-for="字段名 in(of) 数组json" 循环数组或json
v-show 显示内容
v-else指令:和v-if指令搭配使用,没有对应的值。当v-if的值false,v-else才会被渲染出来
v-if指令:取值为true/false,控制元素是否需要被渲染
v-else-if 必须和v-if连用
v-text 解析文本
v-html 解析html标签
v-bind:class 三种绑定方法 1、对象型 '{red:isred}' 2、三元型 'isred?"red":"blue"' 3、数组型 '[{red:"isred"},{blue:"isblue"}]'
v-once进入页面时 只渲染一次 不在进行渲染
v-cloak 防止闪烁
v-pre 把标签内部的元素原位输出
vue-loader是什么?它的用途是什么?
vue文件的一个加载器,将template/js/style转换为js模块
用途:js可以写es6、style样式
为什么用key
给每个dom元素加上key作为唯一标识 ,diff算法可以正确的识别这个节点,使页面渲染更加迅速。
axios及安装?
vue项目中使用ajax时需要axios插件
下载方式cnpm install axios --save
v-model的使用
v-model用于表单的双向绑定,可以实时修改数据
请说出vue.cli项目中src目录每个文件夹和文件的用法
components存放组件
app.vue主页面入口
index.js主文件入口
assets存放静态资源文件
router是定义路由相关的配置
view是视图
分别简述computed和watch的使用场景
用官网的一句话来说,所有需要用到计算的都应该使用计算属性。多条数据影响一条数据时使用计算属性,使用场景购物车。
如果是一条数据更改,影响多条数据时,使用watch,使用场景搜索框。
v-on可以监听多个方法吗?
可以,比如 v-on=“onclick,onbure”
$nextTick的使用
在data()中的修改后,页面中无法获取data修改后的数据,使用$nextTick时,当data中的数据修改后,可以实时的渲染页面
vue组件中data为什么必须是一个函数?
因为javaScript的特性所导致,在component中,data必须以函数的形式存在,不可以是对象。
组件中的data写成一个函数,数据以函数返回值的形式定义,这样每次复用组件的时候,都会返回一份新的data,相当于每个组件实例都有自己私有的数据空间,他们值负责各自维护数据,不会造成混乱。而单纯的写成对象形式,就是所有组件实例共用了一个data,这样改一个全部都会修改。
渐进式框架的理解
主张最少
可以根据不同的需求选择不同的层级
vue在双向数据绑定是如何实现的?
vue双向数据绑定是通过数据劫持、组合、发布订阅模式的方式来实现的,也就是说数据和视图同步,数据发生变化,视图跟着变化,视图变化,数据也随之发生改变
核心:关于vue双向数据绑定,其核心是Object.defineProperty()方法
单页面应用和多页面应用区别及缺点
单页面应用(SPA),通俗的说就是指只有一个主页面的应用,浏览器一开始就加载所有的js、html、css。所有的页面内容都包含在这个主页面中。但在写的时候,还是分开写,然后再加护的时候有路由程序动态载入,单页面的页面跳转,仅刷新局部资源。多用于pc端。
多页面(MPA),就是一个应用中有多个页面,页面跳转时是整页刷新
单页面的优点:用户体验好,快,内容的改变不需要重新加载整个页面,基于这一点spa对服务器压力较小;前后端分离,页面效果会比较酷炫
单页面缺点:不利于seo;导航不可用,如果一定要导航需要自行实现前进、后退。初次加载时耗时多;页面复杂度提高很多。
Vue 项目中为什么要在列表组件中写 key,其作用是什么?
key是给每一个vnode的唯一id,可以依靠key,更准确, 更快的拿到oldVnode中对应的vnode节点。
更准确
因为带key就不是就地复用了,在sameNode函数 a.key === b.key对比中可以避免就地复用的情况。所以会更加准确。
更快
利用key的唯一性生成map对象来获取对应节点,比遍历方式更快。
父组件和子组件生命周期钩子执行顺序是什么?
加载渲染过程
父 beforeCreate -> 父 created -> 父 beforeMount -> 子 beforeCreate -> 子 created -> 子 beforeMount -> 子 mounted -> 父 mounted
子组件更新过程
父 beforeUpdate -> 子 beforeUpdate -> 子 updated -> 父 updated
父组件更新过程
父 beforeUpdate -> 父 updated
销毁过程
父 beforeDestroy -> 子 beforeDestroy -> 子 destroyed -> 父 destroyed
谈一谈你对 nextTick 的理解?
当你修改了data的值然后马上获取这个dom元素的值,是不能获取到更新后的值,你需要使用$nextTick这个回调,让修改后的data值渲染更新到dom元素之后在获取,才能成功。
vue组件中data为什么必须是一个函数?
因为JavaScript的特性所导致,在component中,data必须以函数的形式存在,不可以是对象。
组建中的data写成一个函数,数据以函数返回值的形式定义,这样每次复用组件的时候,都会返回一份新的data,相当于每个组件实例都有自己私有的数据空间,它们只负责各自维护的数据,不会造成混乱。而单纯的写成对象形式,就是所有的组件实例共用了一个data,这样改一个全都改了。
vue和jQuery的区别
jQuery是使用选择器($)选取DOM对象,对其进行赋值、取值、事件绑定等操作,其实和原生的HTML的区别只在于可以更方便的选取和操作DOM对象,而数据和界面是在一起的。比如需要获取label标签的内容:$("lable").val();,它还是依赖DOM元素的值。
Vue则是通过Vue对象将数据和View完全分离开来了。对数据进行操作不再需要引用相应的DOM对象,可以说数据和View是分离的,他们通过Vue对象这个vm实现相互的绑定。这就是传说中的MVVM。
delete和Vue.delete删除数组的区别
delete只是被删除的元素变成了 empty/undefined 其他的元素的键值还是不变。Vue.delete 直接删除了数组 改变了数组的键值。
SPA首屏加载慢如何解决
安装动态懒加载所需插件;使用CDN资源。
vue项目是打包了一个js文件,一个css文件,还是有多个文件?
根据vue-cli脚手架规范,一个js文件,一个CSS文件。
vue更新数组时触发视图更新的方法
push();
pop();
shift();
unshift();
splice();
sort();
reverse()
什么是 vue 生命周期?有什么作用?
每个 Vue 实例在被创建时都要经过一系列的初始化过程——例如,需要设置数据监听、编译模板、将实例挂载到 DOM 并在数据变化时更新 DOM 等。同时在这个过程中也会运行一些叫做 生命周期钩子 的函数,这给了用户在不同阶段添加自己的代码的机会。
第一次页面加载会触发哪几个钩子?
beforeCreate, created, beforeMount, mounted
vue获取数据在一般在哪个周期函数
created
beforeMount
mounted
created和mounted的区别
created:在模板渲染成html前调用,即通常初始化某些属性值,然后再渲染成视图。
mounted:在模板渲染成html后调用,通常是初始化页面完成后,再对html的dom节点进行一些需要的操作。
vue生命周期的理解
总共分为8个阶段创建前/后,载入前/后,更新前/后,销毁前/后。
创建前/后: 在beforeCreated阶段,vue实例的挂载元素$el和数据对象data都为undefined,还未初始化。在created阶段,vue实例的数据对象data有了,$el还没有。
载入前/后:在beforeMount阶段,vue实例的$el和data都初始化了,但还是挂载之前为虚拟的dom节点,data.message还未替换。在mounted阶段,vue实例挂载完成,data.message成功渲染。
更新前/后:当data变化时,会触发beforeUpdate和updated方法。
销毁前/后:在执行destroy方法后,对data的改变不会再触发周期函数,说明此时vue实例已经解
除了事件监听以及和dom的绑定,但是dom结构依然存在。
vuex是什么?
vue框架中状态管理。
vuex有哪几种属性?
有五种,State、 Getter、Mutation 、Action、 Module
state: 基本数据(数据源存放地)
getters: 从基本数据派生出来的数据
mutations : 提交更改数据的方法,同步!
actions : 像一个装饰器,包裹mutations,使之可以异步。
modules : 模块化Vuex
vue全家桶
vue-cli、vuex、vueRouter、Axios
vue-cli 工程常用的 npm 命令有哪些?
npm install 下载 node_modules 资源包的命令
npm run dev 启动 vue-cli 开发环境的 npm 命令
npm run build vue-cli 生成 生产环境部署资源 的 npm 命令
npm run build–report 用于查看 vue-cli 生产环境部署资源文件大小的 npm 命令
请说出 vue-cli 工程中每个文件夹和文件的用处?
build 文件夹是保存一些 webpack 的初始化配置。
config 文件夹保存一些项目初始化的配置
node_modules 是 npm 加载的项目依赖的模块
src 目录是我们要开发的目录:
assets 用来放置图片
components 用来放组件文件
app.vue 是项目入口文件
main.js 项目的核心文件
v-if 和 v-show 有什么区别
共同点:都是动态显示 DOM 元素
区别点:
v-if 是动态的向 DOM 树内添加或者删除 DOM 元素
v-show 是通过设置 DOM 元素的 display 样式属性控制显隐
v-if 切换有一个局部编译/卸载的过程,切换过程中合适地销毁和重建内部的事件监听和子组件
v-show 只是简单的基于 css 切换
性能消耗
v-if 有更高的切换消耗
v-show 有更高的初始渲染消耗
使用场景
v-if 适合运营条件不大可能改变
v-show 适合频繁切换