2019前端面试题整理

js基本数据类型

Number,String,Boolean,null,undefined,object

数组去重

//方法1:es6
let arr = [1, 2, 3, 2, 1, 3];
let newArr=Array.from(new Set(arr))
console.log(newArr)//(3) [1, 2, 3]
//方法2使用filter过滤函数去重。
var arr = [1, 2, 3, 1, 2, 3];
var newArr=arr.filter((v, i, arr) => arr.indexOf(v) === i)
console.log(newArr)//(3) [1, 2, 3]
//方法3:遍历数组法。
function unique(array) {
   var n = []; //一个新的临时数组 
    //遍历当前数组 
    for (var i = 0; i < array.length; i++) {
        if (n.indexOf(array[i]) == -1)
        n.push(array[i]);
        //如果当前数组的第i已经保存进了临时数组,那么跳过, 
        //否则把当前项push到临时数组里面 
    }
    return n;
}
 console.log(unique([1, 2, 3, 1, 2, 3]))//(3) [1, 2, 3]

数组排序

//从小到大
arr.sort(function(a,b){
            return a-b
 })
//从大到小
arr.sort(function(a,b){
            return b-a
 })
//按照其中一个属性值排序
var arr1=[{name:"lee",age:2},{name:"lee",age:32},{name:"lee",age:12},{name:"lee",age:8},{name:"lee",age:52}]
arr1.sort(function(a,b){  
    if(a.age<b.age){  
        return -1;  
    }else if(a.age>b.age){  
        return 1;  
    }  
    return 0;  
}); 

console.log(arr1)

数组扁平化处理

方法1(递归):

const result = []
function flat(arr) {
  arr.forEach(item => {
    if (Array.isArray(item)) {
      flat(item)
    } else {
      result.push(item)
    }
  })
}
flat(arr)
console.log(result)

方法2(扩展运算符+concat):

function flatten(arr) {
  while (arr.some(item => Array.isArray(item))) {
    arr = [].concat(...arr)
  }
  return arr
}
const result = flatten(arr)
console.log(result)

深拷贝&浅拷贝

浅拷贝:内存地址指向同一地址,一个修改另一个也随之更改
方法:let a=1; let b=a; let a={name:'tom'}; let b=Object.assign({}, a);
深拷贝:在内存中指向不同地址,可以拥有不同的值;
方法1:

function deepClone(obj) {
            //查看要拷贝的对象是数组还是对象,如果数组创建空数组,是对象创建空对象
            let newObj = obj instanceof Array ? [] : {}
            for (let k in obj) {
                //K属性名  obj[k]值
                //判断当前每个元素是否是对象或者数组 
                //如果还是对象,继续递归拷贝
                //是值,直接添加到新创建的对象或者数组里
                if (typeof obj[k] === 'object') {
                    //递归拷贝完 放入到新对象的属性
                    newObj[k] = deepClone(obj[k])
                } else {
                    //否则是值, 直接添加到新建的 newObj中
                    newObj[k] = obj[k]
                }
            }
            //返回新对象
            return newObj
        }
        var obj2 = deepClone(obj1)

方法2:

var origin_data = { a: 1, b: 2, c: [1, 2, 3] }
var copy_data = JSON.parse(JSON.stringify(origin_data))

左右固定中间自适应布局(5种方法)

1、浮动

<style>
        html *{
            padding: 0;
            margin: 0;
            height: 100%;
        }
        .container div{
            height: 100vh;
        }
        .left{
            float: left;
            width:200px;
            background:yellow;
        }
        .right{
            float: right;
            width:200px;
            background:yellow;
        }
        .mid{
            background: rgb(240, 153, 227);
        }
    </style>
<div class="container">
        <div class="left"></div>
        <div class="right"></div>
        <div class="mid">浮动</div>
    </div>

2、定位方法

 <style>
        html *{
            padding: 0;
            margin: 0;
        }
        .container{
           width: 100%;
        }
        .container div{
            height: 100vh;
        }
        .left{
            position: absolute;
            left: 0;
            width:200px;
            background:yellow;
        }
        .right{
            position: absolute;
            right: 0;
            width:200px;
            background:yellow;
        }
        .mid{
            margin-left: 200px;
            background: rgb(240, 153, 227);
        }
    </style>
    <div class="container">
        <div class="left"></div>
        <div class="right"></div>
        <div class="mid">定位</div>
    </div>

3、flex

<style>
        html *{
            padding: 0;
            margin: 0;
        }
        .container{
           display: flex;
           height: 100vh;
        }
        .left{
            width:200px;
            background:yellow;
        }
        .right{
            width:200px;
            background:yellow;
        }
        .mid{
            flex: 1;
            background: rgb(240, 153, 227);
        }
    </style>
    <div class="container">
        <div class="left"></div>
        <div class="mid">flex</div>
        <div class="right"></div>
    </div>

4、表格方法

<style>
        html *{
            padding: 0;
            margin: 0;
        }
        .container{
            width: 100%;
            height: 100vh;
           display: table;
        }
        .container div{
            display: table-cell;
        }
        .left{
            width:200px;
            background:yellow;
        }
        .right{
            width:200px;
            background:yellow;
        }
        .mid{
            width: auto;
            background: rgb(240, 153, 227);
        }
    </style>
    <div class="container">
        <div class="left"></div>
        <div class="mid">flex</div>
        <div class="right"></div>
    </div>

5、网格布局

 <style>
        html *{
            padding: 0;
            margin: 0;
        }
        .container{
            width: 100%;
            display: grid;
            grid-template-columns: 200px auto 200px;
            grid-template-rows: 100vh;
        }
        .left{
            background:yellow;
        }
        .right{
            background:yellow;
        }
        .mid{
            background: rgb(240, 153, 227);
        }
    </style>
    <div class="container">
        <div class="left"></div>
        <div class="mid">网格</div>
        <div class="right"></div>
    </div>

cookie,localStorage,SessionStorage三者的区别

1.大小不同:
cookie 4kb,localStorage,SessionStorage都是5M
2.数据有效期不同:
cookie:一般由服务器生成,可设置失效时间,如果在浏览器端生成,默认是关闭后失效
localStorage:除非被永久清除,否则永久保存。
sessionStorage:仅在当前会话会有效,关闭页面或浏览器后被清除
3.与服务器端通信不同:
Cookie 每次都会携带HTTP头中,如果使用cookie保存过多数据会带来性能问题
localStorage 和 sessionStorage 仅在客户端(即浏览器)中保存,不参与和服务器的通信

设计模式有哪些

1、js工厂模式
2、js构造函数模式
3、js原型模式
4、构造函数+原型的js混合模式
5、构造函数+原型的动态原型模式
6、观察者模式
7、发布订阅模式

DOM事件类 自定义重件

 var eve = new Event('custome');
        ev.addEventListener('custome', function () {
            console.log('custome');
        });
        ev.dispatchEvent(eve);

网页从输入网址到渲染完成经历了哪些过程

  1. 域名解析
  2. 发起TCP的3次握手
  3. 建立TCP连接后发起http请求
  4. 服务器端响应http请求,浏览器得到html代码
  5. 浏览器解析html代码,并请求html代码中的资源
  6. 浏览器对页面进行渲染呈现给用户

MVVM和MVC的区别

MVC和MVVM的区别其实并不大。都是一种设计思想。
主要就是MVC中Controller演变成MVVM中的viewModel。
MVVM主要解决了MVC中大量的DOM操作使页面渲染性能降低,加载速度变慢,影响用户体验的问题,当Model频繁发生变化,开发者需要主动更新到View。
ViewModel,是把MVC里的controller的数据加载,加工功能分离出来
最大区别:实现了VIEW和MODEL的自动更新,也就是说,当MODEL的属性发生改变时,我们不再自己手动的操作DOM,而是改变之后的属性对应的VIEW层会自动的发生改变。

HTTP协议类 POST和GET的区别

• GET在浏览器回退时是无害的,而POST会再次提交请求
•GET产生的URL地址可以被收藏,而POST不可以
•GET请求会被浏览器主动缓存,而POST不会,除非手动设置
• GET请求只能进行ur编码,而POST支持多种编码方式
• GET请求参数会被完整保留在浏览器历史记录里,而POST中的参数不会被保留
• GET请求在URL中传送的参数是有长度限制的,而POST没有限制
• 对参数的数据类型,GET只接受ASCIl字符,而POST没有限制
• GET比POST更不安全,因为参数直接暴露在URL上,所以不能用来传递敏感信息
• GET参数通过URL传递,POST放在Request body中

vue数据双向绑定原理

vue实现数据双向绑定主要是:采用数据劫持结合发布者-订阅者模式的方式,通过 Object.defineProperty() 来劫持各个属性的setter,getter,在数据变动时发布消息给订阅者,触发相应监听回调。当把一个普通 Javascript 对象传给 Vue 实例来作为它的 data 选项时,Vue 将遍历它的属性,用 Object.defineProperty() 将它们转为 getter/setter,在属性被访问和修改时通知变化。

vue与React区别

1.监听数据变化的实现原理不同
-Vue 通过 getter/setter 以及一些函数的劫持,能精确知道数据变化,不需要特别的优化就能达到很好的性能
-React 默认是通过比较引用的方式进行的,如果不优化(PureComponent/shouldComponentUpdate)可能导致大量不必要的VDOM的重新渲染
2.数据流的不同
vue数据是双向绑定的
React是单向的
3.组件通信的区别
vue组件间传递消息一般用事件
React组件间传递消息用回调函数
4.模板渲染方式的不同
React 是通过JSX渲染模板
Vue是通过一种拓展的HTML语法进行渲染

说说对原型链的理解

原型链:用于查找引用类型的属性,查找属性会沿着原型链依次进行,如果找到该属性会停止搜索并做相应的操作,否则将会沿着原型链依次查找直到结尾。
原型:所有的函数都有一个特殊的属性prototype(原型),prototype属性是一个指针,指向的是一个对象(原型对象),原型对象中的方法和属性都可以被函数的实例所共享。所谓的函数实例是指以函数作为构造函数创建的对象,这些对象实例都可以共享构造函数的原型的方法。

闭包概念

闭包就是能够读取其他函数内部变量的函数。由于在Javascript语言中,只有函数内部的子函数才能读取局部变量,因此可以把闭包简单理解成“定义在一个函数内部的函数”。所以,在本质上,闭包就是将函数内部和函数外部连接起来的一座桥梁。

改变this指向的方法

call():可以改变函数内的this 指向,可以调用函数Person.call(this,name,sex,age);
apply():会调用函数 和 call() 不同点是 apply() 的参数必须是数组或者伪数组的形式Star.apply(Person,['科比']);
bind():不会调用原来的函数,返回的是改变this指向之后的产生的新函数Star.bind(Person,1,3)
·call和apply的区别
接收的第一个参数都是要修改的this指向的对象,接收的第二个参数不同,call( )方法接受的是若干个参数的列表,apply( ) 方法接受的是一个包含多个参数的数组

减少页面加载时间的方法

1.文件拼合,减少http请求。
2.文件压缩:将需要传输的内容压缩后传输到客户端再解压
3.使用CDN
4.使用缓存,避免重复加载同意文件
5.css文件放置在head,js放置在文档尾部

vue的生命周期有哪些

总共分为8个阶段创建前/后,载入前/后,更新前/后,销毁前/后
beforeCreate:实例刚被创建,el 和 data 并未初始化,可以在这加个loading事件
created:属性已经绑定,完成了 data 数据的初始化,watch/event事件回调,el还没有
beforeMount:在挂载开始之前被调用:相关的render函数首次被调用,模板编译el,完成了 el 和 data 初始化 ,$el未编译已存在
mounted:此周期dom已经渲染完成
beforeUpdate:数据更新时调用,发生在虚拟DOM重新渲染和打补丁之前。你可以在这个钩子中进一步第更改状态,这不会触发附加的重渲染过程
updated:当这个钩子被调用时,组件DOM已经更新,避免在此期间更改状态
beforeDestroy :在这还可以访问实例的数据,清除定时器,事件监听等
destroyed

父子组件生命周期执行顺序

1、加载渲染过程
父beforeCreate=>父created=>父beforeMount=>子beforeCreate=>子created=>子beforeMount=>子mounted=>父mounted
2、子组件更新过程
父beforeUpdate=>子beforeUpdate=>子updated=>父updated
3、父组件更新过程
父beforeUpdate=>父updated
4、销毁过程
父beforeDestroy=>子beforeDestroy=>子destoryed=>父destoryed

css盒模型

盒模型:content+padding+border
1、标准盒模型content


111.png

2、IE盒模型content+padding+border


222.png

通过css设置两种模型:box-sizing:content:(浏览器默认) box-sizing:border-box;

BFC(块格式化上下文)

特性:
1.BFC 是一个独立的容器,容器内子元素不会影响容器外的元素。反之亦如此。
2.在同一个 BFC 中,两个相邻的块级盒子的垂直外边距会发生重叠。
3.BFC 区域不会和 float box 发生重叠。
4.BFC 能够识别并包含浮动元素,当计算其区域的高度时,浮动元素也可以参与计算了。
5.盒子从顶端开始垂直地一个接一个地排列,盒子之间垂直的间距是由 margin 决定的。
创建BFC
1.根元素或包含根元素的元素
2.浮动元素 float = left | right 或 inherit(≠ none)
3.绝对定位元素 position = absolute 或 fixed
4.display = inline-block | flex | inline-flex | table-cell 或 table-caption
5.overflow = hidden | auto 或 scroll (≠ visible)

为什么rem方式下的根字号要设置成62.5%,有没有更精准的方法

因为设了62.5%后就有1rem = 10px,便于用rem来指定元素的尺寸,这样响应式的时候可以直接改变font-size而无需计算其他各种样式中出现的尺寸了。用rem定义尺寸的另一个好处是更能适应缩放/浏览器设置字体尺寸等情况(因为rem相对于字体大小,会同步改变)。

vue父子组件传值

父传子
父组件代码:

//子组件html
<Son :m="msg"><Son/>
//父组件data
data(){
  return {
    msg:"我是父组件要传递的值"
  }
}

子组件代码:

<span>{{m}}<span/>
//子组件接收m
props:{
  m:String
}

子传父
子组件代码:

//html
<input v-model="sonData" @change="setData"/>
//js
data() {
    return {
      sonData:"子组件要传递的值"
    };
  },
methods: {
  //子传父
    setData(){
      this.$emit("msg",this.sonData)
    }
}

父组件代码:

//html
<Son  @msg="getData"/>
//js
data(){
  return{
    sonData:'',
  }
},
methods:{
  getData(data){
      this.sonData=data
    },
}

子组件调用父组件的方法
方法一:$parent

<child @click="childMethod()"/>
 methods: {
      childMethod() {
        this.$parent.fatherMethod();
      }
    }

方法二:$emit
父组件

<child @father="fatherMethod"></child>//调用
methods: {
      fatherMethod() {
        console.log('今天是星期天')
      }
    }

子组件

<button @click="childMethod">点击</button>
methods: {
      childMethod() {
        this.$emit('father')
      }
    }

父组件调用子组件的方法

<button @click="clickParent">点击</button>
<child ref="mychild"></child>//mychild是子组件在父组件中的名字
methods: {
      clickParent() {
        this.$refs.mychild.childMethod("嘿嘿嘿");
      }
    }

自定义指令

Vue.directive('focus',{
    inserted(el) {
      el.focus()
    }
})

vue-router动态路由

在router目录下的index.js文件中,对path属性加上/:id。
使用router对象的params.id。

vue-router有哪几种导航钩子

1.全局导航钩子:router.beforeEach(to,from,next),作用:跳转前进行判断拦截。
2.组件内的钩子;
3.单独路由独享组件

http状态码

2XX:成功状态码
200 OK 正常返回信息
201 Created 请求成功并且服务器创建了新的资源
202 Accepted 服务器已接受请求,但尚未处理

3XX:重定向
301 Moved Permanently 请求的网页已永久移动到新位置。
302 Found 临时性重定向。
303 See Other 临时性重定向,且总是使用 GET 请求新的 URI。
304 Not Modified 自从上次请求后,请求的网页未修改过。

4XX:客户端错误
400 Bad Request 服务器无法理解请求的格式,
客户端不应当尝试再次使用相同的内容发起请求。
401 Unauthorized 请求未授权。
403 Forbidden 禁止访问。
404 Not Found 找不到如何与 URI 相匹配的资源。

5XX: 服务器错误
500 Internal Server Error 最常见的服务器端错误。
503 Service Unavailable 服务器端暂时无法处理请求

http和https区别

http:超文本传输协议,端口80
https:具有安全性的 SSL 加密传输协议,端口443,一般是收费的,安全性更高

HTTP协议类 持久连接

HTTP 协议采用“请求-应答”模式,当使用普通模式,即非Keep-Alive 模式时,每个请求/应答客
户和服务器都要新建一个连接,完成之后立即断开连接 (HTTP协议为无连接的协议)
当使用Keep-Alive模式(又称持久连接、连接重用)时,Keep-Alive 功能使客户端到服务器端
的连接持续有效,当出现对服务器的后继请求时,Keep-Alive 功能避免了建立或者重新建立连接

什么是同源策路及限制

同源策略限制从一个源加载的文档或脚本如何与来自另一个源的资源进行交互
这是一个用于隔离潜在恶意文件的关键的安全机制。
• Cookie、LocalStorage 和 IndexDB 无法读取
。DOM 无法获得
。 AJAX 请求不能发送

前后端如何通信

• Ajax
• WebSocket
• CORS

原型链类 创建对象有3种方法

var o1= {name: 'o1'};
var o11=new Object ({name:'o11'});

var M=function(){this.name='o2'}
var o2=new M():

var P={name: 'o3'}; 
var o3=Object.create (P)

简单说一下Promise,谈谈你对Promise的理解

promise是异步编程的一种解决方案,Promise在一定程度上解决了回调函数的书写结构问题,解决了回调地狱的问题,有三种状态:pending(初始状态),fullfiled(成功状态),reject(失败),状态一经改变就不能再次变化

promise的方法有哪些

promise.all([]).then()------只有当数组中所有的Promise完成后才会有pending转变为resolved执行then里面的回调函数
promise.race([]).then()------当传入的数组中有任意一个promise被拒绝或者成功,则会采用第一个promise作为返回值

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 前端开发面试题 面试题目: 根据你的等级和职位的变化,入门级到专家级,广度和深度都会有所增加。 题目类型: 理论知...
    怡宝丶阅读 2,607评论 0 7
  • 一、理论基础知识部分 1.1、讲讲输入完网址按下回车,到看到网页这个过程中发生了什么 a. 域名解析 b. 发起T...
    我家媳妇蠢蠢哒阅读 3,164评论 2 106
  • 【转载】CSDN - 张林blog http://blog.csdn.net/XIAOZHUXMEN/articl...
    竿牍阅读 3,510评论 1 14
  • 请参看我github中的wiki,不定期更新。https://github.com/ivonzhang/Front...
    zhangivon阅读 7,179评论 2 19
  • 今天是个特殊的日子,我终于决定去见她了。 她是我在高中时才熟悉的,个子不高,很小很小,但总会给人一种充实的感觉,我...
    WangNianZhen_阅读 1,015评论 0 0