前端面试简单大汇总

92 阅读11分钟

*该文章仅起到唤醒你记忆库里灰色区域的记忆,深入查看和了解需自行百度

- vue和react的区别

  • React严格来说只针对MVC的view层,Vue是MVVM模式。
  • virtual DOM不一样,vue会跟踪每一个组件的依赖关系,不需要重新渲染整个组件树,而对于React来说,只要应用状态发生改变,全部组件都会重新渲染,所以react中会需要shouldComponentUpdate这个生命周期来控制;
  • 组件写法不一样,React是JSX,把所有写在Js中, Vue是写在同一个文件;
  • 数据绑定:vue是数据的双向绑定,react是单向数据流;
  • react中state对象不能改变,需要使用setState更新状态,vue中state对象不是必须的,数据由data在vue对象中管理;

- redux和vuex的区别

  • vuex是在redux的基础上进行改变的,对仓库的管理更加明确。
  • 使用mutation来替换redux中的reducer。
  • vuex有自动渲染的功能,所以不需要更新。
  • vuex是专门为vue提供的状态管理工具,而redux是一个泛用的状态管理框架。

- Vue的生命周期

  • Vue的生命周期指的是从组件创建到销毁的一系列过程;分别为以下阶段:
  • beforeCreate 在实例初始化之后,数据监听和事件配发之前触发,所以在这个事件中获取不到data数据;
  • created 实例创建完成后触发,可以访问data、methods等属性,但这个时候组件还没有被挂在到页面上,所以这个时候访问不到$el属性,一般我们可以在这个页面中进行初始化工作,比如通过ajax请求数据来对页面进行初始化
  • beforeMount 在组件被挂在到页面之前触发,会找到对应的template,并编译成render函数
  • mounted 组件挂在到页面后触发,可以通过DOM API获取页面中到DOM元素
  • beforeUpdate 在数据更新时触发,发生在虚拟DOM重新渲染和打补丁之前,在这可以对可能被移除的元素做一些操作,比如移除事件监听器
  • updated 虚拟DOM重新渲染和打补丁之后调用
  • beforeDestroy 在实例销毁之前调用,可以销毁定时器、解绑全局事件
  • destroyed 在实例销毁之后调用,之后实例中所有东西都会解除绑定,所有的事件监听器会被移除,所有的子实例也会被销毁
  • 当我们使用keep-live的时候 还有俩函数
  • activate和deactivated

- vue组件间的参数传递

一、父子组件通信

  • 1、第一种子组件通过props属性来接收父组件的数据,然后父组件在子组件上注册监听事件,子组件通过emit触发事件来向父组件发送数据;
  • 2、第二种通过ref属性给子组件设置一个名字,父组件通过refs组件名来获得子组件,子组件通过refs组件名来获得子组件,子组件通过parent获得父组件。
  • 3、第三种使用provider/inject,父组件中通过provider提供变量,子组件中通过inject来将变量注入到组件。 二、兄弟组件传值
  • 1、使用eventBus方法,它的本质是通过创建一个空的vue实例来作为消息传递的对象,通信的组件引入这个实例,通信的组件通过这个实例上监听和触发事件,来实现消息的传递
  • 2、通过parent.parent.refs来获取到兄弟组件

三、任意组件之间

  • 1、使用eventBus,其实就是创建一个事件中心,相当于中转站,可以用它来传递事件和接收事件,
  • 业务复杂的时候可以使用vuex,xuex的思想就是将这些公共的数据抽离出来,将它作为一个全局的变量来管理,其他组件就可以对着干公共数据进行读写操作,

Vue路由的原理

  • 通过地址栏的变化,进行组件的安装和卸载,
  • 优点:用户体验好
  • 缺点:无法记录之前滚动的位置,无法在前进后退的时候记住滚动的位置
  • 前端路由一共有两种,一是通过hash,一是通过pushState的方式

vue-router中的导航钩子函数

  • 全局的钩子函数beforeEach和afterEach
  • beforeEach(to,from,next)有3个参数,分别代表要进入的路由对象,要离开的路由对象,必须要执行的函数;如果不传就执行下一个钩子函数,传flase终止跳转;
  • 单个路由独享的钩子beforeEnter,它是在路由配置上直接进行定义的
  • 组件内的导航钩子主要有3种,beforeRouteEnter、beforeRouteUpdate、beforeRouteleave它们是直接在路由组件内部直接进行定义的

routeroute和router的区别

  • $route是路由信息对象包括path、hash、query等;
  • 而$router是路由实例对象包括了路由的跳转方法,钩子函数等

- Vue常用的修饰符

  • .prevent提交事件不再重载页面;
  • .stop阻止单击事件冒泡
  • .self当事件发生在该元素本身而不是子元素的时候会触发

浅入promise

  • 它是异步编程的一种解决方案 ,可以将异步操作以同步的方式表现出来,避免回调地狱的产生
  • promise是异步的解决办法;
  • promise是一个对象,对象的状态不受外界影响,状态一旦改变不可逆;
  • promise.all可以将多个promise实例包装成一个新的promise实例。成功返回结果数组,失败返回最先被reject失败状态的值
  • promise.race,那个结果返回的快就返回那个结果,不管是成功还是失败
  • promise 有三种状态,(pending 进行中、resolved 成功、rejected 失败)
  • 小记:通过new promise创建一个promise对象,参数是个回调函数,回调里有2个参数,resolve,reject(失败)
  • Promise是一个构造函数,接收一个函数作为参数,返回一个Promise实例,Promise实例有三种状态pending、resolved和rejected分别代表了进行中,已成功和已失败,状态是不可逆的;

Vuex的实现原理

  • Vuex的状态存储是响应式的,当Vue组件从store中读取状态时,若store中状态发生改变,响应的组件也会得到更新状态。但不能直接改变state,必须通过显示的提交(commit)mutations来追踪每一个状态的变化。

computed和watch的差异

  • computed是计算属性并将该属性挂载到vue实例上,依赖其他属性计算值,并且它的值有缓存,只有当计算值变化才会返回内容,

  • 而watch是监听已经存在且已挂载到vue实例上的数据,用watch也可以监听computed计算属性的变化

  • computed具有缓存,只有当依赖变化后,第一次访问computed属性,才会计算新值,而watch是当数据发生变化便会调用执行函数

vue中mixin和mixins区别

  • mixin用于全局混入,会影响到每个组件实例
  • mixins应该是我们最常用的扩展组件的方式了,如果多个组件中有相同的业务逻辑,就可以将这些逻辑剥离出来,通过mixins混入代码,比如上拉下拉加载数据这些逻辑,要注意的是mixins混入的钩子先于组件内的钩子函数执行,并且在遇到同名选项的时候也会选择性进行合并

开发中常用的几种Content-type

  • application/x - www-form -urlencoded 浏览器原生form表单,数据放在body里key和val都进行URl转码
  • multipart/form-data 这是post请求,一般表单上传文件的时候使用该方式
  • application/json 告诉服务器消息主体是序列化后的JSON字符串
  • text/xml 该种方式主要用来提交XML格式的数据

对前端模块化的认识

  • AMD 是提前执行,CMD 是延迟执行。
  • AMD推荐通过返回一个对象做为模块对象,CommonJS通过对module.exports或exports的属性赋值来达到暴露模块对象的目的。

类组件和函数组件

  • 函数组件中无法使用state,也无法使用组件的生命周期方法

  • 函数组件都是展示性组件,接受props,渲染DOM

  • 函数组件中没有this,但在类组件中仍要绑定this这个琐碎的事,如:在render()方法中要使用this.props来替换props

  • 类组件中可以使用局部状态state和生命周期方法。

  • 函数式组件和容器组件的使用

  • 容器组件负责全部的数据状态,交互逻辑,

  • 函数式组件负责使用数据,展示数据

什么是事件流?

  • 当一个HTML元素产生一个事件时,这个事件会在元素节点与跟节点之间的路径传播,路径所经过的节点都会收到改元素,这个传播的过程就是DOM事件流。
  • 过程分为捕获和冒泡;

如何找到事件源

  • Var target = e.target||e.srcElement
  • tagName 能找到事件源的元素名

栈和队列的区别

  • 栈的插入和删除操作都是在一端进行的,而队列的操作却是在两端进行的。 队列先进先出,栈先进后出。 栈只允许在表尾一端进行插入和删除,而队列只允许在表尾一端进行插入,在表头一端进行删除 - setState
  • setState 以异步的方式执行,一般理解为this.state的值会在DOM中渲染,取token,作为参数setState是同步的 - constructor
  • Constructor 参数接受两个参数 props,context
  • 可以获取到父组件传下来的props,context,如果想在constructor构造函数内部(在组件其他地方是可以直接收的)使用props或context,需要传super对象;

- ES6的class constructor 和 super

  • 只要组件存在constructor,就必须要写super,否则this指向会错误

跨域

  • 我一般都是用框架自带的跨域;
  • 还有前端方式possMessage、纯后端CORS、前后结合Jsonp、webSocket、nginx代理跨域、nodejs中间件代理跨域

Jsonp原理

  • 动态创建一个script标签,添加到body中,设置script标签的scr属性,属性值就是接口,通过接口上的某个参数向服务器传递一个函数,通过这个回调函数接收服务器数据,通过jsonp格式获取的数据大多数是object类型
  • 优点:
  • 解决了在测试或者开发中获取不用域下的数据,用户传递一个callback参数给服务器,然后后端返回时将callback参数作为函数名包裹住JSON数据,这样客户端就可以随意定义自己的函数了
  • 缺点:
  • 只支持get请求不支持post;(传给后端一个json格式的数据,就会报415,告诉你请求格式不正确)
  • 登录时需要用session来判断当前用户的登录状态,这个时候有跨域,前后台取到的session是不一样的,就不能用session判断
  • 优点是兼容性好,简单易用,支持浏览器与服务器双向通信,缺点只支持GET请求

什么是Proxy?

  • Proxy用于修改某些操作的默认行为,等同于在语言层面作出修改,所以属于一种“元编程”即对编程语言进行编程
  • Proxy可以理解成,在目标对象之前架设一层“拦截”,外界对该对象的访问,都必须先通过这层拦截,因此提供了一种机制,可以对外界对访问进行过滤和改写。Proxy这个词的原意是代理,代理器;
  • 不管Proxy怎么修改都可以在Reflect上获取默认行为

单例模式、策略模式、适配器模式是什么

  • 单例模式:保证了全局只有一个实例来访问。比如说常用的如弹框组件的实现和全局状态的实现;
  • 策略模式:主要是将方法实现和调用分离,外部通过不同的参数可以调用不同的策略,为主要在MVP模式解藕的时候用来将视图的方法定义和方法调用分离;

怎么创建一个类

  • 类就是对象的抽象,对象是类的实例
  • 函数定义的无状态组件
  • ES5原生方式React.createClass定义的组件
  • ES6形式的extends React.Component定义的组件

get和post的区别

  • 共同点:
  • 两者都可以发送和接收数据
  • 区别:
  • get是url方式传递数据,post是以http请求中的body部分传递数据,所以说post更安全
  • get传递数据直接在浏览器地址栏可以看到,而post可以要在开发者工具中看到
  • Get传递数据 中文可能不会被编码或者出现乱码,post不会;
  • get在IE下会走缓存,post不会

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

普通函数:

  • this指向他的直接调用者
  • 默认情况下,没找到直接调用者,this指向window
  • 严格模式下,没有直接调用者this是undefined
  • 使用call,apply,bind(ES5新增)绑定的,this指的是绑定的对象

箭头函数

  • 箭头函数的this指向创建时的那个对象,而不是引用时的那个对象
  • 箭头函数的this永远指向上下文的this,任何方法都改变不了指向
  • 箭头函数可以绑定this对象,大大减少了显示绑定this对象的写法(call、apply、bind),箭头函数并不适用所有场景,ES7提出了函数绑定,来取代call、apply、bind调用。
  • 箭头函数不会自动绑定局部变量,如this,arguments,super(ES6),new.target(ES6)等,箭头函数没有他自己的this值,箭头函数内的this值继承外围作用域,在箭头函数中调用this,就只是简单的沿着作用域链向上寻找,找到最近的一个this拿来使用
  • 函数绑定运算符是并排的两个冒号(::)
  • 左边是一个对象,右边是一个函数,这个运算符会自动将左边的对象,作为上下文环境(即this对象),绑定到右边的函数上面

this的理解

  • this是执行上下文的一个属性,运行时自动生成的一个内部对象,只能在函数内部使用,随着函数使用场合的不同,this的值会发生变化。
  • 谁调用它,它就指向谁。
  • 一般在这几种情况下会用到它,
  • 单纯的函数调用;(this指向全局)
  • 作为对象方法的调用;(this指向这个对象)
  • 作为构造函数调用;(this指向这个新创建的对象)
  • apply调用,apply()是函数对象的一个方法,它的作用是改变函数的调用对象,它的第一个参数就表示改变后的调用这个函数的对象,当它的参数为空时,默认调用全局对象

js如何创建一个对象

  • 对象的字面量创建 var obj = {}
  • 创建实力对象 var obj = new Object()
  • 构造函数的模式 function fn(){},new fn()
  • 工厂模式 用一个函数 通过传参返回对象

谈谈你对面向对象的理解

  • 在使用对象的时候只关注他提供的功能,不关注细节;
  • 它是一种通用的思想,主要特征抽象,封装和继承,
  • 它主张把大的问题拆分开,并试图用分工协作完成。
  • 好处
  • 开发周期短,效率高,可靠性高后期易于维护
  • 原型链的理解
  • 就是实例对象和原型之间的链接
  • 封装 继承 多态(js中不存在多态概念)

Js获取原型的方法 prototype、proto、constructor三者的关系

  • prototype
  • 每个函数都有一个Prototype属性,这个属性指向原型对象;
  • proto
  • 当我们实例一个对象时这个对象自带了一个(每个对象都有个)_proto_属性,指向创建自己的那个构造函数原型,对象可以直接访问它的属性和方法
  • 总结:
  • 当我们创建一个构造函数的时候这个构造函数自带了一个prototype属性,这个属性指向原型对象,这个对象里有个constructor构造器,它的作用是指向创建自己的构造函数,prototype还可以存放公共的属性和方法,

继承的方式

  • 1、通过改变父类的执行环境来实现
  • 2、通过 call 、apply
  • 3、原型、混合继承
  • 4、es6 构造函数

call、apply、bind三者的区别

  • 相同:
  • 都是改变this指向的,第一个参数是this要指向的对象,都可以利用后续的参数
  • 不同:
  • Call第一个参数是this指向,后面是传入函数执行的参数。
  • apply 第一个参数是this指向,第二个是argnments伪数组
  • bind也可以有多个参数,在执行的时候还可以添加,但要注意行参的顺序,会返回执行上下文被改变的函数不会立即执行,前两者会直接执行

作用域链的理解

  • 作用域链的作用就是保证执行环境里有权访问的变量和函数是有序的,作用于链的变量只能向上访问,访问到window为止;(不能向下访问)。
  • 简单说就是作用域集合,当前作用域->父级作用域->…全局作用域 形成的作用域链条;
  • 全局作用域的变量和方法都可以进行调用
  • 局部的变量和方法只能局部进行调用(除闭包外)
  • 局部可以访问全局的变量和方法。

谈谈你对arguments的了解

  • 函数内部自带的一个对象
  • 存储的是所有的实惨
  • 可以使用[]及下标访问arguments中的内容 arguments[0] 访问第一个实参
  • 可以使用arguments.lengts确定传入实参的个数
  • 最常用的途径(判断传入的参数个数根据不同参数做不同的事情)
  • JS的变量声明提升
  • 函数及变量的声明都将被提升到函数的最顶部,这就叫提升,
  • Js只有声明的变量会提升,初始化的不会
  • 声明分为两部一是声明操作(var a)和 赋值操作(a=2)

递归和循环的区别

  • 递归算法
  • 优点:代码简洁、清晰、并且容易验证正确性
  • 缺点:
  • 1、她的运行会不断的开辟空间,创建新变量增加堆栈处理,占用过多内存资源,执行效率有一定影响
  • 注意:递归就是在这个过程或函数里调用自身
  • 循环算法:
  • 优点:速度快,解构简单
  • 缺点:不能解决所有问题

浅谈文档碎片的理解

  • js操作dom时发生了什么
  • 每次对Dom的操作都会发生重排
  • 什么是文档碎片
  • document.createDocumentFragment()
  • 一个容器,用于暂时存放创建dom元素
  • 文档碎片的作用
  • 将需要添加的大量元素,先添加到文档碎片中,再将文档碎片添加到需要插入到位置,这样大大减少了dom的操作,提高了性能

什么是回流和重绘

  • 当改变渲染树需要重新构建的时候,就会发生回流
  • 每个页面都至少发生一次回流,在页面渲染的时候;
  • 浏览器从新绘制渲染树的时候就是重绘

如何在当前视口看见当前元素

scrollIntoView()

如何判断当前脚本运行在浏览还是node环境中

  • this===window ? ‘browser’:’node’
  • 通过判断Global对象是否为window,如果不为window,当前脚本没有运行在浏览器中

移动端的点击事件有延迟时间是多久,为什么会有,怎么解决?

  • 会有300ms的延迟,因为移动端会有双击缩放的操作,所以浏览器在click后哟啊等待300ms,看用户有没有下一次点击来判断这次操作是不是双击;
  • 解决
  • 1、通过meta标签禁止网页缩放
  • 2、通过meta将网页的viewport设置为ideal viewport
  • 3、调用js库 ,如Fastclick
  • 还有可能引起点击穿透

Js数据类型

  • 有两种 ,基本数据类型和引用数据类型
  • 原始数据类型(栈):undefined、null、boolean、number、string及symnol
  • symbol代表创建后独一无二且不可改变的数据类型,可能是为了解决可能出现的全局变量冲突的问题
  • 引用数据类型(堆):对象、数组和函数
  • 区别:
  • 存储位置不同,原始数据直接存储在栈中的简单数据段,占据空间小,大小固定数据被频繁使用数据,
  • 引用数据放在堆中的对象,占据空间大,大小不固定。

Symbo类型注意点

  • symbo函数前不能使用new命令会报错;
  • 可以接诶好搜一个字符串作为参数,表示Symbol实例的描述,主要是为了控制台显示,或者转为字符串时好区分;
  • Object.getOwnPropertySymbols方法返回一个数组,成员是当前对象的所有用作属性名的Symbol值
  • Symbol.for接收一个字符串作为参数,然后搜索有没有以该参数作为名称的Symbol值,如果有,就返回这个Symbol值,否则就新建并返回一个以该字符串为名称的Symbol值
  • Symbol.keyFor方法返回一个已登记的Symbol类型值的key

什么是堆,什么是栈 栈中数据是先进后出,堆是先进先出

null和undefined的区别

  • null是一个表示无的对象,转为数值时为0,undefined是一个表示无的原始值,转为数值时为NaN。
  • 两者都是基本数据类型,undefined是未定义,null代表空对象,一般变量声明了但还没有定义的时候会返回undefined,null主要是赋值给一些可能会返回对象的变量作为初始化;
  • undefined:
  • 变量被声明了,但没有赋值
  • 调用函数时,应该提供的参数没有提供,
  • 对象没赋值的属性
  • 函数没有返回值
  • null
  • 作为函数的参数,表示该函数的参数不是对象
  • 作为对象原型链的终点

eval是做什么的

  • 它的功能是把对应的字符串解析成js代码运行,尽量避免使用eval 不安全消耗性能(2次,一次解析成js语句,一次执行)

移动端性能优化

  • 尽量使用css3动画,开启硬件加速。
  • 适当使用touch事件代替click事件。
  • 避免使用css3渐变阴影效果。
  • 可以用transform: translateZ(0)来开启硬件加速。
  • 不滥用Float。Float在渲染时计算量比较大,尽量减少使用
  • 不滥用Web字体。Web字体需要下载,解析,重绘当前页面,尽量减少使用。
  • 合理使用requestAnimationFrame动画代替setTimeout
  • PC端的在移动端同样适用
  • 用innerHTML代替DOM操作,减少DOM操作次数,优化JS性能
  • 图片预加载,将样式表放在顶部,将脚本放在底部,加上时间戳

什么是闭包

  • 闭包就是可以读取其他函数内部变量的函数,使用闭包主要是为了设计私有的方法和变量,在js中函数就是闭包,因为只有函数才会产生作用域的概念,
  • 闭包可以避免全局变量的污染,但容易造成内存泄漏。
  • 闭包中this指向window
  • 特点:
  • 函数嵌套函数
  • 函数可以引用外层的参数和变量
  • 参数和变量不会被垃圾回收机制回收
  • 那些操作会造成内存泄漏
  1. 意外的全局变量引起的内存泄露
  2. 闭包引起的内存泄露
  3. 没有清理的DOM元素引用
  4. 被遗忘的定时器或者回调

高内聚、低耦合

  • 一个系统有多个模块组成,划分模块时把功能相连密切的放在一个模块中,这就是高内聚
  • 功能联系远的放在其他模块中,模块之间联系越少越好,接口越简单越好,这就是低耦合

如何清除浮动

  • 1、给父级定义一个伪类 after{ Display:block;clear:both;visibility:hidden;height:0 }
  • 2、父级定义overflow:hidden
  • 3、给父级加高度
  • 4、父级定义overflow:auto
  • BrowserRouter
  • 一个使用了Html5 history Api的高阶路由组件,保证ui界面和url保持同步

HTTP 和 HTTPS的基本概念

  • HTTP是一种网络协议,HTTPS是以安全为目的的HTTP通道,就是HTTPS的安全版,
  • HTTPS主要有两种:1是建立一个信息安全通道,2是确认网站的真实性

HTTPS的优点

  • 使用HTTPS协议可认证用户和服务器,确保数据发送到正确的客户机和服务器
  • HTTPS是SSL+HTTP协议构建的,要比HTTp安全,可防止数据在传输过程中不被窃取、改变、确保数据的完整性 缺点:
  • 使用HTTPS 页面的加载时间延长50%,耗电增加10%-20%
  • SSL证书需要钱
  • SSL证书通常需要绑定IP,不能在同一IP上绑定多个域名,IPv4资源不可能支撑这个消耗。
  • HTTPS协议的加密范围也比较有限,在黑客攻击、拒绝服务攻击、服务器劫持等方面几乎起不到什么作用。最关键的,SSL证书的信用链体系并不安全,特别是在某些国家可以控制CA根证书的情况下,中间人攻击一样可行。

区别:

  • HTTP协议传输的数据都是未加密的,也就是明文,因此使用HTTP协议传输隐私信息非常不安全,为了保证这些隐私数据能加密传输,于是网景公司设计了SSL协议用于对HTTP协议传输的数据进行加密,从而就诞生了HTTPS。简单来说,HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议,要比http协议安全。 HTTPS和HTTP的区别主要如下:
  • https协议需要到ca申请证书,一般免费证书较少,因而需要一定费用。
  • http是超文本传输协议,信息是明文传输,https则是具有安全性的ssl加密传输协议。
  • http和https使用的是完全不同的连接方式,用的端口也不一样,前者是80,后者是443。
  • http的连接很简单,是无状态的;HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议,比http协议安全。

js的垃圾回收机制是什么原理

  • 垃圾回收机制有两种方法 第一种是标记清除法
  • 当变量进入执行环境时,就标记这个变量为”进入环境”,当变量离开环境的时候,则将其标记为”离开环境”,垃圾收集器在运行的时候会给储存在内存中的所有变量都加上标记,然后它会去掉环境中的标量以及被环境中的变量引用的标记,而在此之后再被加上标记的变量将被视为准备删除的变量,原因是环境中的变量已经无法访问到这些变量了,最后,垃圾收集器完成内存清除工作,销毁那些带标记的值,并回收他们所占用的内存空间 第二种是引用计数法
  • 当声明了一个变量并将一个引用类型赋值给改变量时,则这个值得引用次数就是1,相反,如果包含对这个值引用的变量又取得了另外一个值,则这个值得引用次数就-1,当这个引用次数变成0时,则说明没有办法在访问这个值了,因而就可以将其所占的内存空间给收起来,这样垃圾收集器再下次运行时,它就会释放那些引用次数为0的值所占的内存

AMD和CMD规范的区别

  • AMD依赖前置;在定义模块的时候就要声明其依赖的模块。
  • 在依赖加载完成后直接执行,顺序和我们书写的不一定一致
  • CMD就近依赖 ;只有在用到莫哥模块的时候再去require
  • 依赖模块加载完成后并不执行,只是下载,等到所有模块都加载好后,进入回调函数逻辑,遇到require语句才执行对应模块,顺序和我们书写的一致

ES6模块、commonJS、AMD、CMD的差异

  • commonJs输出的是一个值的拷贝,是对象在运行时加载的,
  • ES6模块输出的是值的引用 requireJS的核心原理
  • 通过动态创建script脚本来异步引入模块,然后对每个脚本的load事件进行监听,如果每个脚本都加载完成了,再调用回调函数

兼容问题

  • 关于使用event对象,出现的兼容问题
  • e.keyCode || e.which
  • e.keyCode || e.which
  • e.keyCode || e.which
  • e.offsetX || e.layerX
  • 关于获取滚动条时,出现的兼容问题
  • document.documentElment.scrollTop || document.body.scrollTop
  • 阻止浏览器默认行为的兼容
  • e.preventDefault?e.preventDefault():e.returnValue=false
  • return false
  • 阻止事件冒泡的兼容
  • e.stopPropagation?e.stopPropagation():e.cancelBubble=true
  • 取消拖拽时文字选中状态兼容
  • window.getSelection().removeAllRanges():document.selection.empty()
  • 处理一步的方式 -利用回调函数 -用async和await来处理异步 -promise -发布/订阅
  • 我们假定,存在一个"信号中心",某个任务执行完成,就向信号中心"发布"一个信号,其他任务可以向信号中心"订阅"这个信号,从而知道什么时候自己可以开始执行。这就叫做"发布/订阅模式",又称"观察者模式”
  • 事件 触发一个事件也可以作为异步的处理 当触发某个事件再来执行某件事

节流和防抖

  • 函数防抖是事件被触发n秒后再执行回调,如果在这n秒内事件又被触发了,就从新计时;
  • 函数节流是规定一个时间,在这个时间内只能有一次触发事件的回调函数执行,

数组的方法

  • push() 从队尾添加,改变原数组
  • pop() 移除数组末尾最后一项,返回移除的项
  • shift() 删除数组第一项,返回删除元素的值,如果数组为空返回undefined
  • unshift() 添加头部,改变原数组
  • sort() 数组排序,参数为一个匿名函数,如果匿名函数返回正值,则升序排列,反之相反
  • reverse() 翻转数组项的顺序 原数组改变
  • concat() 将参数添加到原数组,将参数添加到数组的末尾,并返回一个新数组,不改变原数组
  • slice() 返回原数组中指定开始下标到结束下标之间的项组成的新数组,slice接受两个参数,如果致谢一个参数,slice方法返回从该参数到数组末尾的所有项,如果有两个参数,该方法返回起始位置和结束位置之间的项,但不包括结束位置的项
  • splice() 可以实现删除,插入,替换 删除(可以删除任意属相的项,只需要指定2个参数,要删除的第一项的位置和要删除的项) 插入,替换(可以向指定位置插入任意数量的项,只需提供3个参数:起始位置,0(要删除的项),插入的项),splice()方法始终都会返回一个数组,数组中包括从原数组中删除的项,如果没有删除任何项则返回一个空数组
  • map() 对数组中的每一项运行给定函数,返回每次函数调用的结果组成的数组
  • some() 判断数组中是否存在满足条件的项,只要有一项满足条件,就返回true
  • every() 判断数组中每一项都是否满足条件,只有所有选项都满足条件,才会返回true
  • filter() 过滤功能,数组中的每一项运行给定函数,返回满足过滤条件组成的数组
  • forEach() 对数组进行循环遍历,对数组中的每一项运行给定函数,这个方法没有返回值,参数都是function类型,默认有传参功能,参数分别是,便利的数组内容,对应的索引,数组本身
  • indexOf() 接受两个参数,要查找的项和表示查找起点位置的索引,返回查找的项在数组的位置,没找到的情况下返回-1

map与each方法的区别

  • map()方法主要用来遍历操作数组和对象,
  • each()主要用于遍历jquery对象。
  • each()返回的是原来的数组,并不会新创建一个数组。
  • map()方法会返回一个新的数组。如果在没有必要的情况下使用map,则有可能造成内存浪费。

伪数组转成真数组

  • Array.from()
  • Array.prototype.slice.call();

如何将字符串转化为数字

  • Number()
  • parseInt()方法
  • parseFloat()

常用正则

  • 匹配日期:如yyy-mm-dd
  • Var regex = /^[0-9]{4}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])$/;
  • 匹配qq号
  • var regex = /^[1-9][0-9]{4,10}$/g;
  • 手机号码正则
  • var regex = /^1[34578]\d{9}$/g;

link和import的区别

  • link是xhtml标签,除了可以加载css外,还可以定义RSS等事物;@import只能加载css
  • link引用时,在页面载入时同时加载,而@import需要页面网页完全加载后才加载
  • link无兼容问题,@import低版本浏览器不支持
  • link支持javascript控制dom,@import不支持

事件监听

  • 事件源.addEventListener("去掉on的事件",function(){},true/flase)默认为false
  • 事件委托本质上是利用了浏览器的事件冒泡机制,
  • 事件委托的好处 :
  • 可以为同样元素绑定多次同一事件
  • 可以确定是冒泡还是捕获
  • 事件委托
  • 利用冒泡的原理,把事件加到父元素上,触发执行效果
  • 好处:实现对未来元素事件的绑定(绑定事件时,页面上还不存在的元素)
  • 减少事件绑定,提高性能
  • 事件绑定
  • 对DOM元素绑定事件处理函数
  • 1、在DOM元素中直接绑定
  • 2、在JS中绑定
  • 3、绑定事件监听函数
  • 事件监听和解绑
  • 监听:addEventListener() attachEvent()
  • 解绑:removeEventListener() detachEvent()

懒加载的实现原理

  • 意义:懒加载的主要目的是作为服务器前端优化,减少请求数或延迟请求数
  • 实现原理:先加载一部分数据,当触发某个条件时利用异步加载剩余的数据,新得到的数据,不会影响有数据的显示,同时最大程度上减少服务器的资源消耗
  • 实现方式:
  • 延迟加载,使用setTimeOut或setInterval进行加载延迟
  • 符合某些条件,或触发了某些事件才开始异步下载
  • 可视区加载

双向数据绑定和单向数据的区别

  • 单项数据
  • 父组件给子组件传递数据,但子组件不能给父组件传递数据;
  • 双向数据绑定
  • 各种数据相互依赖相互绑定,导致数据问题的源头难以被跟踪到:单向数据流的数据流动向可以跟踪,流动单一,追查问题的时候可以更便捷,缺点是写起来不太方便,要使视图发生改变就得创建各种action来维护state
  • 双向绑定把数据变更的操作隐藏在框架内部,调用者并不会直接感知。而在践行单向数据流的flux系的实现中,其实是在全局加了一个单利事件分发器,开发者必须显示的通过这个统一的时间及制作数据变更通知
  • vue通过双向数据绑定,来实现View和Model的同步更新,主要是通过使用数据劫持和发布订阅者模式来实现
  • 双向数据绑定的原理就是利用了Object.defineProperty()这个方法重新定义了对象获取属性值(get)和设置属性值(set)的操作来实现的。
  • Object.defineProperty介绍
  • Object.defineProperty函数一共有三个参数,第一个参数是需要定义属性的对象,第二个参数是需要定义的属性,第三个是该属性描述

webpack的看法

  • 我使用webpack最主要的是为了简化页面依赖的管理,并通过将其打包为一个文件来降低页面加载时请求的资源数。它将所有的资源都看成一个模块,并把页面逻辑当作一个整体,通过一个特定的文件入口找到所有的依赖文件,将各个依赖文件通过loader和plugins处理后,然后打包在一起,输出一个浏览器可以识别的Js文件

Js中异步机制

  • 最常见的是使用回调函数,缺点是代码耦合度高不利于维护,多个回调函数嵌套的时候会造成回调地域
  • 第二种:Promise方式,使用这种方式可以将嵌套的回调函数作为链式调用,有时会造成多个then的链式调用,可能会造成代码的语义不够明确
  • 第三种generator
  • 第四种是async函数的形式

图片的懒加载和预加载

  • 预加载:提前加载图片,当用户需要查看时可直接从本地缓存中渲染
  • 懒加载:主要是作为服务器前端的优化,减少请求数或延迟请求数
  • 区别主要是一个是提前加载一个是迟缓加载甚至不加载,懒加载对服务器前端有一定的缓解压力的作用,预加载会增加服务器前端的压力

Mouseover和mouseenter

  • 当鼠标移动到元素上时就会触发mouseenter事件 类似mouseover 它们两者之间的差别是mouseenter不会冒泡

cookie,sessionStorage,LocalStorage三者多区别

  • 会话跟踪技术
  • 大小限制不超过4K,每个域下cookie不能超过50个
  • 有效期限和设置的时间有关系,过了会自动删除
  • cookie只能是字符串
  • 如何删除一个cookie
  • var date = new Date(); date.setDate(date.getDate() - 1);//真正的删除

ES6

  1. 块级作用域
  2. 常量const
  3. 解构赋值
  4. 字符串模版
  5. 展开运算符
  6. 箭头函数
  7. 箭头函数
  8. class类
  9. 模块化
  10. 继承
  11. 新增模板字符串(为JavaScript提供了简单的字符串插值功能)
  12. 箭头函数(操作符左边为输入的参数,而右边则是进行的操作以及返回的值Inputs=>outputs。)
  13. for-of(用来遍历数据—例如数组中的值。)
  14. arguments对象可被不定参数和默认参数完美代替。ES6将promise对象纳入规范,提供了原生的Promise对象。
  15. 增加了let和const命令,用来声明变量。
  16. 增加了块级作用域。
  17. let命令实际上就增加了块级作用域。ES6规定,var命令和function命令声明的全局变量,属于全局对象的属性;
  18. let命令、const命令、class命令声明的全局变量,不属于全局对象的属性。还有就是引入module模块的概念
  19. Let
  20. 变量不允许被重复定义
  21. 不会进行变量声明提升
  22. 保留块级作用域
  23. const
  24. 常量值不允许被改变
  25. 不会进行变量声明提升

关系型数据库和非关系型数据库的区别

  • 关系型数据库是指采用关系模型来组织数据的数据库,结构清晰,使用方便,好维护;
  • 非关系型数据库通常指数据以对象的形式存储在数据库中,而对象之间的关系通过每个对象自身的属性来决定,操作存取速度快。

window.onload 与 document.ready的区别

  • 执行时间
  • window.onload必须等到页面内包括图片的所有元素加载完毕后才执行。
  • $(document).ready()是DOM结构绘制完毕后就执行,不必等到加载完毕。
  • 编写个数不同
  • window.onload不能同时编写多个,如果有多个window.onload方法,只会执行一个
  • $(document).ready()可以同时编写多个,并且都可以得到执行
  • 简化写法
  • window.onload没有简化写法
  • (document).ready(function())可以简写成(document).ready(function(){})可以简写成(function(){});

对node的理解

  • 是一个基于Cheome V8引擎的js运行环境
  • 使用了事件驱动、非阻塞模式
  • 适应于数据高并发,适合多请求,但不适合高运算,有权限读取操作系统级别的API
  • 一般用来配合 mongodb 开发一些小的接口,和使用他的 npm 命令,主要用 nodejs 做中间件

position的值,relative和absolute分别是相对于谁定位的

  • absolute :生成绝对定位的元素, 相对于最近一级的 定位不是 static 的父元素来进行定位。
  • fixed (老IE不支持)生成绝对定位的元素,通常相对于浏览器窗口或 frame 进行定位。
  • relative 生成相对定位的元素,相对于其在普通流中的位置进行定位。
  • static 默认值。没有定位,元素出现在正常的流中
  • sticky 生成粘性定位的元素,容器的位置根据正常文档流计算得出

谈谈你对webpack的看法

  • WebPack 是一个模块打包工具,你可以使用WebPack管理你的模块依赖,并编绎输出模块们所需的静态文件。它能够很好地管理、打包Web开发中所用到的HTML、JavaScript、CSS以及各种静态文件(图片、字体等),让开发过程更加高效。对于不同类型的资源,webpack有对应的模块加载器。webpack模块打包器会分析模块间的依赖关系,最后 生成了优化且合并后的静态资源。

instanceof的作用

instanceof运算符用于判断构造函数的prototype属性是否出现在对象的原型链中的任何位置

new操作符具体干了什么

  • 创建了一个空对象
  • 将对象的原型设置为函数的prototype对象
  • 让函数的this指向这个对象
  • 判断函数的返回值类型 如果是值类型返回创建的对象,如果是引用类型返回这个引用对象

Js延迟加载的方法有哪些

  • defer属性
  • async属性
  • 动态创建DOM方式
  • 使用setTimeout延迟方法
  • 让js最后加载

对ajax的理解

  • 我的理解它是一种异步通信的方法,通过直接由js脚本向服务器发起HTTP通信,然后根据服务器返回的数据,更新网页中相应的部分,而不是刷新整个页面;就是局部刷新

类数组转数组

  • 通过call调用数组的slice方法实现转换
  • Arry.prototype.slice.call(arrayLike);
  • 通过call调用splice方法来实现转换
  • Array.prototype.splice.call(arrayLike,0)
  • 通过apply调用数组的concat方法来实现转换
  • Array.prototype.concat.apply([],arrayLike)
  • 通过Array.from方法转换
  • Array.from(arraylike)

柯里化函数实现

将使用多个参数的函数转换成一系列使用一个参数的函数;

function curry(fn,args){

//获取函数需要的参数长度

let length = fn.length;

args = args || [];

return function(){

let subArgs = args.slice(0);

//拼接得到现有的所有参数

for(let i = 0;i<arguments.length;i++){

subArgs.push(arguments[i]); }

//判断参数的长度是否已经满足函数所需参数的长度

if(subArgs.length>=length){

//如果满足,执行函数

return fn.apply(this,subArgs);

}else{

//如果不满足,递归返回柯里函数,等待参数的传入 return curry.call(this,fn,subArgs);

} } }

//ES6 实现 function curry(fn,...args){

return fn.length<= args.lentg?fn(...args) : curry.bind(null,fn,...args);

}

toprecision、toFixed和Math.round的区别

  • Toprecision 用于处理精度,精度是从左至右第一个不为0的数开始算起
  • toFixed 是对小数点后指定位数取整,从小数点开始数起
  • Math.round是将一个数字四舍五入到一个整数

排序

  • 冒泡排序:对相邻的元素进行两两比较,顺序相反则进行交换,这样会把最大或者最小浮到最顶端;冒泡排序是稳定排序
  • 选择排序:从待排序的数据中选择最大或者最小的一个作为首元素,直到所有元素排完为止,消耗比较大,且不是稳定排序
  • 插入排序:将一个待排序的记录插入到前面已经排好序的有序列中去,直到插完所有元素;
  • 快速排序:将要排序的数据分割成两部分,一部分的所有数据比另一部分的所有数据都要小,
  • 希尔排序、归并排序、堆排序、基数排序

什么是Gulp

  • 基于node的自动化构建工具
  • 作用:
  • 1、自动压塑JS、css和图片,合并文件,编译sass自动刷新浏览器