备战金三四银—前端必问的面试题(1)

前言

又快到了到金三四银找工做的黄金时间,经过这些时间作面试题整理了一些经典必问的面试题,相信会对你们有帮助!javascript

如何知道(任何的)一个网站使用了多少种HTML标签?

1,获取全部的DOM节点html

document.querySelectorAll('*')

此时获得的是一个NodeList集合,咱们须要将其转化成数组,而后对其筛选前端

2,转化为数组vue

[...document.querySelectorAll('*')]

一个拓展运算符就搞定java

3,获取数组每一个元素的标签名node

[...document.querySelectorAll('*')}.map(ele => ele.tagName)

使用一个map方法,将咱们须要的结果映射到一个新数组webpack

4,去重nginx

new Set([...document.querySelectorAll('*').map(ele=>ele.tagName)).size

咱们使用ES6中的set对象,把数组做为构造函数的参数,就实现了去重,在使用Set对象的size方法就能够获得有多少种HTML元素了es6

这段代码运行结果

async function async1() {
    console.log('async1 start');
    await async2();
    console.log('async1 end');
}
async function async2() {
    console.log('async2');
}
console.log('script start');
setTimeout(function() {
    console.log('setTimeout');
}, 0)
async1();
new Promise(function(resolve) {
    console.log('promise1');
    resolve();
}).then(function() {
    console.log('promise2');
});
console.log('script end');
第一步,输出script start

虽然有两个函数声明,有async关键字,可是没有调用,就不看,直接打印同步代码console.log(‘script start’)web

第二步,输出async1 start

由于执行async1这个函数的时候,async表达式定义的函数也是当即执行

第三步,输出async2

由于async2是async定义的函数,输出async2并返回promise对象

第四步,输出promise1

由于执行到new promise,promise是当即执行,就先打印promise1

第五步,输出script end

由于上一步先打印了promise1,而后执行到resolve的时候,而后跳出promise继续向下执行,输出script end

第六步,输出promise2

由于前面的nue promise放进resolve回调,因此resolve被放到调用栈执行

第七步,输出async1 end

由于await定义的这个promise已经执行完,而且返回结果,因此继续执行async1函数后的任务,就是console.log(‘async1 end’)

第八步,输出setTimerout

setTimeout被放在最后被调用

怎么让里面的div垂直水平居中

列举6种
<div class="parent">
    <div class="child">
    </div>
</div>

<style>
    .parent{
        width: 550px;
        height: 550px;
        border: 1px  solid #FF7F24;
        /* 方法一:定位 */
        /* position: relative; */

        /* 方法二:margin: auto */
        /* position: relative; */

        /* 方法三:利用display:table-cell */
        /* display:table-cell 加上 vertical-align:middle和text-align:center 使高度不一样的元素都水平垂直居中,其中display:inline-block使这两个div在同一行显示 */
        /* display: table-cell;
        vertical-align: middle;
        text-align: center; */

        /* 方法四:利用display:flex */
        /* display: flex;
        justify-content: center;
        align-items: center; */

        /* 方法五:计算父盒子与子盒子的空间距离(这跟方法一是一个道理) */

        /* 方法六:利用transfrom */
        /* position: relative */

        /* 方法七:利用calc计算 */
        /* position: relative; */

    }
    .child{
        width: 150px;
        height: 150px;
        border: 1px solid #FF3030;
        /* 方法一:定位 */
        /* position: absolute;
        top: 50%;
        left: 50%;
        margin-top: -75px;
        margin-left: -75px;    */

        /* 方法二:margin: auto */
        /* top: 0,left: 0,right: 0,bottom: 0就像四个方向有相同的力在拉这个盒子,而后margin:auto至关于平方剩余空间居中 */
        /* position: absolute;
        margin: auto;
        top: 0;
        left: 0;
        right: 0;
        bottom: 0; */

        /* 方法三:利用display:table-cell */
        /* display: inline-block */

        /* 方法五:计算父盒子与子盒子的空间距离(这跟方法一是一个道理) */
        /* (parent550-child150)÷2=200 */
        /* margin-top: 200px;
        margin-left: 200px; */

        /* 方法六:利用transfrom */
        /* position: absolute;
        top: 50%;
        left: 50%;
        transform: translate(-50%,-50%); */

        /* 方法七:利用calc计算 */
        /* top和left都是(父元素高-子元素高)÷2 */
        /* position: absolute;
        top:calc(200px);
        left: calc(200px); */
    }
</style>

如何比较React和Vue?

一、监听数据变化的实现原理不一样
  • Vue经过getter/setter以及一些函数,能精确知道数据变化
  • React默认是经过比较引用的方式(diff)进行的,React不精确监听数据变化
二、数据流不一样
  • Vue2.0能够经过props实现双向绑定,用vuex单向数据流的状态管理框架
  • React不支持双向绑定,提倡单项数据流,Redux单向数据流的状态管理框架
三、组件通讯的区别
  • Vue三种组件通讯方法:

    父组件经过props向子组件传递数据或回调

    子组件经过事件event向父组件发送数据或回调

    经过provide/inject实现父组件向子组件传入数据,可跨层级

  • React三种组件通讯方法:

    父组件经过props向子组件传递数据

    React不支持子组件像父组件发送数据,而使用的是回调函数

    经过 context实现父组件向子组件传入数据, 可跨层级

四、模板渲染方式不一样
  • 表面上来看:

    React经过JSX渲染模板

    Vue经过HTML进行渲染

  • 深层上来看:

    React是经过原生JS实现模板中常见语法,如:插件,条件,循环

    Vue是与组件JS分离的单独模板,经过指令实现,如:v-if

五、模板中使用的数据
  • React里模板中使用的数据能够直接import的组件在render中调用
  • Vue里模板中使用的数据必需要在this上进行中转,还要import一个组件,还要在components中声明
六、渲染过程不一样
  • Vue不须要渲染整个组件树
  • React状态改变时,所有子组件从新渲染
七、框架本质不一样
  • Vue本质是MVVM框架,由MVC发展而来
  • React是前端组件化框架,由后端组件化发展而来
八、Vuex和Redux的区别
  • Vuex可使用dispatch、commit提交更新
  • Redux只能用dispatch提交更新
九、组合不一样功能方式不一样
  • Vue组合不一样功能方式是经过mixin,能够帮我定义的模板进行编译、声明的props接收到数据….
  • React组合不一样功能方式是经过HoC(高阶组件),本质是高阶函数

谈谈你对MVVM的理解

MVVM:MVVM是Model-View-ViewModel的简写

M指的是模型,V指的是视图,VM指的是视图模型

模型指的是后端传递的数据

视图指的是所看到的页面,试图模型mvvm模式的核心,它是链接view和model的桥梁。
它有两个方向:一是将模型转化成试图,即将后端传递的数据转化成所看到的页面。实现的方式是:数据绑定。二是将视图转化为模型,即将所看到的页面转化成后端数据。

视图模型指的是界面和对应的model,由于数据库结构不能直接跟界面控件一一对应,因此,须要再定义一个数据对象专门对应view上的控件,而ViewModel的职责就是把model对象封装成能够显示和接受输入的界面数据对象

谈谈你对浅拷贝和深拷贝的理解

好比:

A复制了B,B被修改后

A要是随着B的变化而变化,那就是浅拷贝

要是B改变了,A不变,那就是深拷贝

浅拷贝:

拷贝一层,对象级别的则拷贝引用

深拷贝:

拷贝多层,每一个层级的属性都会拷贝

vue组件间的6种通讯方法

父向子传递数据经过props

子向父传递是经过$emit、event

子实例访问父实例经过$parent

父实例访问子实例经过$children

$attrs用父组件传递数据给子组件或孙组件
(包含了父做用域中不做为 prop 被识别 (且获取) 的特性绑定 (class 和 style 除外))

listeners用父组件传递数据给子组件或孙组件
包含了父做用域中的 (不含 .native 修饰器的) v-on 事件监听器

祖先组件经过provider提供变量给子孙组件

子孙组件经过inject注入变量给祖先组件

ref用来访问组件实例

emit用于父子、隔代、兄弟组件通讯

on用于父子、隔代、兄弟组件通讯

vuex用来做为兄弟之间和跨级之间的通讯

call,apply和bind相同点和区别?

相同点:

都是用来改变函数的this对象的指向的

第一个参数都是this要指向的对象

均可以利用后续参数传参

区别:

call、apply的区别:接受参数的方式不同

bind:不当即执行。而apply、call 当即执行

谈谈防抖和节流

若是事件处理函数调用的频率无限制,会加剧浏览器的负担,致使用户体验很是糟糕。此时咱们能够采用debounce(防抖)和throttle(节流)的方式来减小调用频率,同时又不影响实际效果

防抖:当持续触发事件时,必定时间段内没有再触发事件,事件处理函数才会执行一次,若是设定的时间到来以前,又一次触发了事件,就从新开始延时

节流:当持续触发事件时,保证必定时间段内只调用一次事件处理函数,原理是经过判断是否到达必定时间来触发函数。

节流无论事件触发有多频繁,都会保证在规定时间内必定会执行一次真正的事件处理函数,而函数防抖只是在最后一次事件后才触发一次函数。 好比在页面的无限加载场景下,咱们须要用户在滚动页面时,每隔一段时间发一次 Ajax 请求,而不是在用户停下滚动页面操做时才去请求数据。这样的场景,就适合用节流技术来实现
## 给数字增长“逗号”分隔?
<font color=#CD2626>例如输入: '"123456789.888"' 输出:123,456,789.888</font>

var rmb = 123456789.888; 
var retRmb = rmb.toFixed(3).replace(/\d{1,3}(?=(\d{3})+(\.\d*)?$)/g, '$&,'); 
console.log(retRmb);

描述一下vue响应原理?

Vue响应式底层实现方法是Object.defineProperty()方法,该方法中存在一个getter和setter的可选项,能够对属性值的获取和设置形成影响

Vue中编写了一个wather来处理数据

在使用getter方法时,总会通知wather实例对view层渲染页面

一样的,在使用setter方法时,总会在变动值的同时,通知wather实例对view层进行更新

js中有几种判断数据类型的方法?

js的基本数据类型:

number、string、boolean、null、undefined、symbol(es6新增)

js的引用数据类型:

object、function

一、经过typeof判断

经过typeof没法判断出数组、对象、null的具体类型

console.log(typeof 10); //number
  console.log(typeof NaN); //number

  console.log(typeof "10"); //string
  console.log(typeof false); //boolean
  console.log(typeof Symbol()); //symbol
  console.log(typeof function () {}); //function

  console.log(typeof []); //object
  console.log(typeof {}); //object
  console.log(typeof null); //object
  console.log(typeof undefined); //undefined

二、经过constructor判断

经过constructor判断数组和对象,但没法判断null,由于null不是对象 没有construtor

console.log("".constructor == String); //true
  console.log(false.constructor == Boolean); //true
  console.log(new Number(10).constructor == Number); //true 这里要使用对象的方式
  console.log([].constructor == Array); //true
  console.log({}.constructor == Object); //true

三、经过instanceof判断

instanceof是用于判断A是否为B的实例,由于instanceof是基于原型链进行检测的,因此能够经过instanceof检测数组,可是要检测对象就不是那么准确了,由于数组对象也是Object

console.log([] instanceof Array); //true
  console.log([] instanceof Object); //true
  console.log({} instanceof Array); //false
  console.log({} instanceof Object); //true

四、经过Object.prototype.toString.call判断

都能判断出来,包括unll undefined

let getType = Object.prototype.toString;
  console.log(getType.call(undefined)); //[object Undefined]
  console.log(getType.call(null)); //[object Null]
  console.log(getType.call([])); //[object Array]
  console.log(getType.call({})); //[object Object]

## js中事件传递有哪几个阶段?
捕获阶段:先由文档的根节点document往事件触发对象,从外向内捕获事件对象

目标阶段:到达目标事件位置(事发地),触发事件

冒泡阶段:再从目标事件位置往文档的根节点方向回溯,从内向外冒泡事件对象

谈谈对this的理解?

this表示当前对象,this的指向是根据调用的上下文来决定的,默认指向window对象,指向window对象时能够省略不写

调用的上下文环境包括全局和局部

全局环境:
全局环境就是在<script></script>里面,这里的this始终指向的是window对象

局部环境:
在全局做用域下直接调用函数,this指向window
对象函数调用,哪一个对象调用就指向哪一个对象
使用new实例化对象,在构造函数中的this指向实例化对象
使用call或apply改变this的指向

其它:
用于区分全局变量和局部变量,须要使用this
返回函数当前的对象

浏览器地址输入URL到看到界面经历了哪些?

  • 输入网址
  • 缓存解析
  • 域名解析
  • tcp链接,三层握手
  • 页面渲染

详细介绍一下前端缓存

前端缓存主要分为HTTP缓存和浏览器缓存,

其中HTTP缓存是在HTTP请求传输时用到的缓存,

主要在服务器代码上设置,而浏览器缓存则主要由前端js上进行设置

你知道闭包吗?平时工做中又有用到过吗?适用于什么场景?

闭包就是可以读取其余函数内部变量的函数,也就是个函数,只不过是处于其余函数内部而已
因为在javascript中,只有函数内部的子函数才能读取局部变量,因此说,闭包能够简单理解成“定义在一个函数内部的函数“

因此,在本质上,闭包是将函数内部和函数外部链接起来的桥梁

闭包能够读取函数内部的变量,和让这些变量的值始终保持在内存中

适用场景:

采用函数引用方式的setTimeout调用

将函数关联到对象的实例方法

封装相关的功能集

说说JS中原型链与继承

每一个构造函数都有一个原型对象,

原型对象都包含一个指向构造函数想指针(constructor),而实例对象都包含一个指向原型对象的内部指针(__proto__)。

若是让原型对象等于另外一个类型的实例,此时的原型对象将包含一个指向另外一个原型的指针(__proto__),另外一个原型也包含着一个指向另外一个构造函数的指针(constructor)。

假如另外一个原型又是另外一个类型的实例……这就构成了实例与原型的链条

原型链是实现继承的主要方法

你了解前端跨域吗?有哪些方法能够处理跨域?

跨域是指一个域下的文档或脚本试图去请求另外一个域下的资源

跨域的解决方案:

  • 经过jsonp跨域
  • document.domain + iframe跨域
  • location.hash + iframe
  • window.name + iframe跨域
  • postMessage跨域
  • 跨域资源共享(CORS)
  • nginx代理跨域
  • nodejs中间件代理跨域
  • WebSocket协议跨域

Proxy与Object.defineProperty的优缺点?

Proxy的优势:

能够直接监听对象而非属性,并返回一个新对象

能够直接监听数值的变化

拦截方法较多

能够劫持整个对象,并返回一个新对象

Proxy做为新标准将受到浏览器厂商重点持续的性能优化

Proxy的缺点:

Proxy是es6提供的新特性,兼容性很差

Object.defineProperty的优势:

兼容性好,支持IE9

IE9如下的版本不兼容

Object.defineProperty的缺点:

没法监控到数组下标的变化,致使直接经过数组的下标给数组设置值,不能实时响应

只能劫持对象的属性,咱们须要对每一个对象的每一个属性进行遍历

在vue2.0中,是经过递归+遍历data对象来实现对数据的监控的,

若是属性值也是对象,那么须要深度遍历,显然若是能劫持一个完整的对象才是最好的选择,

因此在vue2.0中选Object.defineProperty,

当时虽然es6的新属性出现了Proxy,可是兼容性很差,最主要的是这个属性没法用polyfill来兼容,

可是在vue3.0的版本中会有效的提供兼容解决方案

在vue3.0中,Proxy不用像Object.defineProperty给属性都设置set,get的方法,因此Proxy不会触发循环调用

Vue中的key的做用?

key的做用是为了在diff算法执行时更快的找到对应的节点,提升diff速度

vue组件高度复用增长key能够标识组件的惟一性,为了更高效更新虚拟DOM

谈谈 Vue 响应式原理?

Vue响应式底层实现方法是Object.defineProperty()方法,该方法中存在一个getter和setter的可选项,能够对属性值的获取和设置形成影响

Vue中编写了一个wather来处理数据

在使用getter方法时,总会通知wather实例对view层渲染页面

一样的,在使用setter方法时,总会在变动值得同时,通知wather实例对view层进行更新

Vue 组件 data 选项为何必定要是函数?

若是data是一个函数的话,这样没复用一次组件,就会返回一份新的data,相似于给每一个组件实例建立一个私有的数据空间,让各个组件实例维护各自的数据。而单纯的写成对象形式,就使得全部组件实例共用一份data,就会形成一个变了全都会变得结果

因此说vue组件的data必须是函数。这都是由于js的特性带来的,跟vue自己设计无关。

js自己的面向对象编程也是基于原型链和构造函数,应该会注意原型链上添加通常都是一个函数方法而不会去添加一个对象了

谈谈 Vue 的渲染过程?

一、把模板编译为render函数

二、实例进行挂载, 根据根节点render函数的调用,递归的生成虚拟dom

三、对比虚拟dom,渲染到真实dom

四、组件内部data发生变化,组件和子组件引用data做为props从新调用render函数,生成虚拟dom, 返回到步骤3

你对Webpack4了解吗?能够说说它的打包原理吗?

webpack是一个打包模块化JavaScript的工具,在webpack里一切文件皆模块,经过Loader转换文件,经过Plugin注入钩子,最后输出由多个模块组合成得文件,webpack专一于构建模块化项目

一、利用babel完成代码转换及解析,并生成单个文件的依赖模块Map

二、从入口开始递归分析,并生成整个项目的依赖图谱

三、将各个引用模块打包为一个当即执行函数

四、将最终的bundle文件写入bundle.js中

用CSS画一个三角形的原理?

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1.0">
  </head>
  <body>
    <div id="app"></div>
  </body>
</html>
<style>
    #app{
        width: 0;
        height: 0;
        border: 93px solid;
        border-color: red green yellow transparent;
    }
</style>

cmd-markdown-logo
这里主要用到了CSS3的一个transparent属性

transparent是透明的意思,在CSS3之后,支持全部的coloe属性

画的三角形其实border的宽度加上颜色来控制的,其实三角形的造成不过是,其它的边框颜色设置成了透明了而已

CSS3有哪些新特性?

  • CSS3的选择器:

    E:last-child匹配父元素的最后一个子元素E

    E:nth-child(n)匹配父元素的第n个子元素E

    E:nth-last-child(n)匹配父元素的倒数第n个子元素E

  • @Font-face特性
  • 圆角(border-radius)
  • 多列布局
  • 阴影(Shadow)
  • CSS3的渐变效果
  • CSS弹性盒子模型
  • transition对象变换时的过渡效果
  • transforms 2D转换效果
  • Animation动画效果

position有哪些值?分别表明什么做用?

static:默认值 没有定位,元素出如今正常的流中

absolute:绝对定位 相对于static定位之外的第一个父元素进行定位

relative:相对定位 生成相对定位的元素,相对于其正常位置进行定位

fixed:固定定位 生成绝对定位的元素,相对于浏览器窗口进行定位

你对缓存有了解吗?

缓存是创建一个函数的过程,这个函数可以记住以前计算的结果或值。使用缓存函数是为了不在最后一次使用相同参数的计算中已经执行的函数的计算。这节省了时间,但也有不利的一面,即咱们将消耗更多的内存来保存之前的结果

js有哪些继承方式?

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

借用构造函数继承:复制父类的实例属性给子类

组合继承:调用父类构造函数,继承父类的属性,经过将父类实例做为子类原型,实现函数复用

原型式继承:不自定义类型的状况下,临时建立一个构造函数,借助已有的对象做为临时构造函数的原型,而后在此基础实例化对象,并返回

寄生式继承:其实就是在原型式继承获得对象的基础上,在内部再以某种方式来加强对象,而后返回

寄生组合继承:经过寄生的方式来修复组合式继承的不足,完美的实现继承

最后

但愿看到文章的同窗都有收获!

文章要是有不对的地方还望指正!

最后祝你们都愈来愈优秀!

欢迎你们加入,一块儿学习前端,共同进步!
cmd-markdown-logo
cmd-markdown-logo

相关文章
相关标签/搜索