前端知识点

关于排序

  • js中sort函数的底层实现机制?

js中sort内置多种排序算法,是根据要排序数的乱序程度来决定使用哪种排序方法。V8 引擎 sort 函数只给出了两种排序 InsertionSort 和 QuickSort,长度小于20的使用InsertionSort(插入排序),大于20的数组则使用 QuickSort(快速排序)javascript

快速排序css

function quickSort(arr){
        if(arr.length<=1){ //若是数组中只有一位数,返回数组
            return arr;
        }
        var mNumIndex = Math.floor(arr.length/2); //取基准值的下标
        var mNum = arr.splice(mNumIndex,1)[0];  //取基准值
        var left = [];  //左边数组
        var right = []; //右边数组
        for(var i=0;i<arr.length;i++){
            if(arr[i]<mNum){  //若是数组小于基准值,放在左边数组
                left.push(arr[i]);
            }else{            ///不然
                right.push(arr[i]);
            }
        }        
        return quickSort(left).concat([mNum],quickSort(right));
        //返回左边数组+基准值+右边数组
    }

插入排序html

function insertSort(arr) {
  let length = arr.length;
  for(let i = 1; i < length; i++) {
    let temp = arr[i];
    for(let j = i; j > 0; j--) {
      if(arr[j] >= arr[j-1]) {
        break;      // 当前考察的数大于前一个数,证实有序,退出循环
      }
      arr[j] = arr[j-1]; // 将前一个数复制到后一个数上
    }
    arr[j] = temp;  // 找到考察的数应处于的位置
  }
  return arr;
}

选择排序(实现思路跟冒泡排序差很少, 能够说是冒泡排序的衍生版本)vue

function selectionSort(arr) {
      var len = arr.length
      var minIndex, temp
      for (i = 0; i < len - 1; i++) {
        minIndex = i
        for (j = i + 1; j < len; j++) {
          if (arr[j] < arr[minIndex]) {
            minIndex = j
          }
        }
        temp = arr[i]
        arr[i] = arr[minIndex]
        arr[minIndex] = temp
      }
      return arr
    }

数组去重

ES6java

function unique(arr) {
      return Array.from(new Set(arr))
    }
    new Set自己是一个构造函数,用来生成Set数据结构,类数组,成员的值都是惟一的,
    没有重复的值。
    Array.from()将一个类数组对象或者可遍历对象转换成一个真正的数组。

ES5node

function unique(arr) {
      var newArr = []
      for (var i = 0; i < arr.length; i++) {
        if (newArr.indexOf(arr[i]) === -1) {
          newArr.push(arr[i])
        }
      }
     return newArr
   }
    var result = [];    
    var obj = {};    
    for(var i =0; i<arr.length; i++){
       if(!obj[arr[i].key]){
          result.push(arr[i]);
          obj[arr[i].key] = true;
       }
    }

如何统计网页里出现多少种html标签

ES5webpack

var doms = document.getElementsByTagName('*')
    var obj = {}
    var ret = []
    for (let i = 0; i < doms.length; i++) {
      var name = doms[i].nodeName
      if(!obj[name]){
        ret.push(name)
        obj[name] = true
      }
    }
    console.log(ret.length)

ES6ios

let names = [...document.getElementsByTagName('*')].map(v=>v.nodeName)
   console.log(new Set(names).size)

获取dom下的全部节点

function getDom(dom) {
      var list = []
      var domChildren = dom.childNodes
      for (var i = 0; i < domChildren.length; i++) {
        // nodeType === 1 是元素节点,2是属性节点。
        if (domChildren[i].nodeType === 1) {
          list.push(domChildren[i])
          var retArr = getDom(domChildren[i])
          list = list.concat(retArr)
        }
      }
      return list
    }
    getDom(document.querySelector('body'))

实现bind方法:web

Function.prototype.bind= function(obj){
    var _self = this, args = arguments;
    return function() {
        _self.apply(obj, Array.prototype.slice.call(args, 1));
    }
}

防抖功能函数,接受传参

定义:屡次触发事件后,事件处理函数只执行一次,而且是在触发操做结束时执行。

原理:对处理函数进行延时操做,若设定的延时到来以前,再次触发事件,则清除上一次的延时操做定时器,从新定时。
    function debounce(fn) {
      // 四、建立一个标记用来存放定时器的返回值
      let timeout = null;
      return function() {
        // 五、每次当用户点击/输入的时候,把前一个定时器清除
        clearTimeout(timeout);
        // 六、而后建立一个新的 setTimeout,
        // 这样就能保证点击按钮后的 interval 间隔内
        // 若是用户还点击了的话,就不会执行 fn 函数
        var args = arguments;
        timeout = setTimeout(() => {
          fn.apply(this, args);
        }, 1000);
      };
    }
    sayDebounce(){
     console.log("防抖成功!");
    }
    btn.addEventListener("click", debounce(sayDebounce));

函数节流

定义:触发函数事件后,短期间隔内没法连续调用,只有上一次函数执行后,过了规定的时间间隔,才能进行下一次的函数调用。算法

原理:对处理函数进行延时操做,若设定的延时到来以前,再次触发事件,则清除上一次的延时操做定时器,从新定时。

JavaScript中经常使用的设计模式

详细连接: https://juejin.im/post/5afe64...

  • 1.单例模式
特色:一个类只能构造出惟一实例 
案例:建立菜单对象或者弹出框
const singleton = function(name) {
  this.name = name
  this.instance = null
}

singleton.prototype.getName = function() {
  console.log(this.name)
}

singleton.getInstance = function(name) {
  if (!this.instance) { // 关键语句
    this.instance = new singleton(name)
  }
  return this.instance
}

// test
const a = singleton.getInstance('a') // 经过 getInstance 来获取实例
const b = singleton.getInstance('b')
console.log(a === b)
  • 2.工厂模式

建立一个对象经常须要复杂的过程,因此不适合在一个复杂的对象中。建立对象可能会致使大量的重复代码,也可能提供不了足够级别的抽象。工厂方法模式经过定义一个单独的建立对象的方法来解决这些问题,由子类实现这个方法来建立具体类型的对象。

function Animal(opts){
    var obj = new Object();
    obj.name = opts.name;
    obj.color = opts.color;
    obj.getInfo = function(){
        return '名称:'+obj.name +', 颜色:'+ obj.color;
    }
    return obj;
}
var cat = Animal({name: '波斯猫', color: '白色'});
cat.getInfo();
  • 3. 订阅/发布者模式

发布订阅模式,基于一个主题/事件通道,但愿接收通知的对象(称为subscriber)经过自定义事件订阅主题,被激活事件的对象(称为publisher)经过发布主题事件的方式被通知。

就和用户订阅微信公众号道理同样,一个公众号能够被多个用户同时订阅,当公众号有新增内容时候,只要发布就行了,用户就能接收到最新的内容

订阅/发布者模式和观察者模式的区别:

在观察者模式中,观察者须要直接订阅目标事件。在目标发出内容改变的事件后,直接接收事件并做出响应。发布订阅模式相比观察者模式多了个事件通道,订阅者和发布者不是直接关联的。
一、Observer模式要求观察者必须订阅内容改变的事件,定义了一个一对多的依赖关系;
二、Publish/Subscribe模式使用了一个主题/事件通道,这个通道介于订阅着与发布者之间;
三、观察者模式里面观察者「被迫」执行内容改变事件(subject内容事件);发布/订阅模式中,订阅着能够自定义事件处理程序;
四、观察者模式两个对象之间有很强的依赖关系;发布/订阅模式两个对象之间的耦合读底

function Public(){
        //存放订阅者信息
        this.subscribers = [];
        // 添加订阅者
        this.addSubscriber = function(subscriber) {
          //保证一个订阅者只能订阅一次
          let flag = this.subscribers.some(function(item){
            return item == subscriber;
          })
          if(!flag){
            this.subscribers.push(subscriber);
          }
          return this;
        }
        // 发布消息
        this.publish = function(data) {
          let arr = arguments; 
          this.subscribers.forEach(function(fn){
            fn(...arr)
          })
          return this;
        }
      }
      let publisher = new Public() //初始化
      let fanfan = function(data){
        console.log(`订阅者吴亦凡收到订阅信息:${[...arguments]}`)
      }
      let luhan = function(data){
        console.log(`订阅者鹿晗收到订阅信息:${[...arguments]}`)
      }
      publisher.addSubscriber(fanfan).addSubscriber(luhan); // 添加订阅者fanfan
      publisher.publish('NBA头条快讯', '蔡徐坤签约掘金');
  1. 3. 观察者模式

一个或多个观察者对目标的状态感兴趣,经过将本身依附在目标对象上以便注册所感兴趣的内容。目标状态发生改变而且观察者可能对这些改变感兴趣,会发送一个通知消息,调用每一个观察者的更新方法。当观察者再也不对目标状态感兴趣时,他们能够简单将本身从中分离。

首先是目标的构造函数,他有个数组,用于添加观察者。还有个广播方法,遍历观察者数组后调用他们的update方法:
class Subject{
  constructor(){
    this.subs = [];
  }
  addSub(sub){
    this.subs.push(sub);
  }
  notify(){
    this.subs.forEach(sub=> {
      sub.update();
    });
  }
}
那么观察者就得有个update方法:
class Observer{
  update(){
    console.log('update');
  }
}
let subject = new Subject();
let ob = new Observer();
//目标添加观察者了
subject.addSub(ob);
//目标发布消息调用观察者的更新方法了
subject.notify();   //update

4. 策略模式
特征:根据不一样参数能够命中不一样的策略;
案例:动画库里的算法函数
5. 代理模式
特征:代理对象和本体对象具备一致的接口;
案例:图片预加载
5. 迭代器模式
特征:能获取聚合对象的顺序和元素;
案例:each([1, 2, 3], cb);
5. 命令模式
特征:不一样对象间约定好相应的接口;
案例:按钮和命令的分离;
6. 组合模式
特征:组合模式在对象间造成一致对待的树形结构;
案例: 扫描文件夹;
7. 组合模式
特征:组合模式在对象间造成一致对待的树形结构;
案例: 扫描文件夹;
6. 组合模式
特征:组合模式在对象间造成一致对

  1. 列表项目

待的树形结构;
案例: 扫描文件夹;

判断数组

Object.prototype.toString.call(arr) === "[object Array]" ;
Array.isArray(arr);
arr.constructor === Array;

This的指向

  1. 全局范围:指向winodow(严格模式下不存在全局变量,指向undedfiend);
  2. 普通函数调用:指向window
  3. 对象方法调用:指向最后调用它的对象
  4. 构造函数调用:指向new出来的对象
  5. 显示设置this: call apply 方法显示将this指向第一个参数指明的对象
  6. 箭头函数没有prototype(原型),因此箭头函数自己没有this, 箭头函数的this指向在定义的时候继承自外层第一个普通函数的this,跟使用位置没有关系。被继承的普通函数的this指向改变,箭头函数的this指向会跟着改变,不能直接修改箭头函数的this指向(call、aaply、bind)会默认忽略第一个参数,可是能够正常传参。

什么是原型链?

建立一个函数就会为其建立一个prototype属性,指向这个函数的原型对象,原型对象会自动得到constructor属性,指向prototype属性所在函数。

Function.prototype.a = "a";   
Object.prototype.b = "b";   
function Person(){}   
console.log(Person);    //function Person()   
let p = new Person();   
console.log(p);         //Person {} 对象   
console.log(p.a);       //undefined   
console.log(p.b);       //b
p.__proto__ === Person.prototype;Person.prototype.constructor === Person;

640?wx_fmt=jpeg&wxfrom=5&wx_lazy=1&wx_co=1

new操做符具体干了什么呢?

  1. 建立一个空对象,而且 this 变量引用该对象,同时还继承了该函数的原型。
  2. 属性和方法被加入到 this 引用的对象中。
  3. 新建立的对象由 this 所引用,而且最后隐式的返回 this 。

页面加载过程

  1. 浏览器根据 DNS 服务器获得域名的 IP 地址
  2. 向这个 IP 的机器发送 HTTP 请求
  3. 服务器收到、处理并返回 HTTP 请求
  4. 浏览器获得返回内容

Vue实现数据双向绑定的原理:Object.defineProperty()

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

vue的数据双向绑定 将MVVM做为数据绑定的入口,整合Observer,Compile和Watcher三者,经过Observer来监听本身的model的数据变化,经过Compile来解析编译模板指令(vue中是用来解析 {{}}),最终利用watcher搭起observer和Compile之间的通讯桥梁,达到数据变化 —>视图更新;视图交互变化(input)—>数据model变动双向绑定效果。

<body>
    <div id="app">
    <input type="text" id="txt">
    <p id="show"></p>
</div>
</body>
<script type="text/javascript">
    var obj = {}
    Object.defineProperty(obj, 'txt', {
        get: function () {
            return obj
        },
        set: function (newValue) {
            document.getElementById('txt').value = newValue
            document.getElementById('show').innerHTML = newValue
        }
    })
    document.addEventListener('keyup', function (e) {
        obj.txt = e.target.value
    })
</script>

对vue的keep-alive 的了解

keep-alive是 Vue 内置的一个组件,可使被包含的组件保留状态,或避免从新渲染。
在vue 2.1.0 版本以后,keep-alive新加入了两个属性: include(包含的组件缓存) 与 exclude(排除的组件不缓存,优先级大于include) 。

Vue.js的template编译的理解?

答:简而言之,就是先转化成AST树,再获得的render函数返回VNode(Vue的虚拟DOM节点)

详情步骤:

首先,经过compile编译器把template编译成AST语法树(abstract syntax tree 即 源代码的抽象语法结构的树状表现形式),compile是createCompiler的返回值,createCompiler是用以建立编译器的。另外compile还负责合并option。

而后,AST会通过generate(将AST语法树转化成render funtion字符串的过程)获得render函数,render的返回值是VNode,VNode是Vue的虚拟DOM节点,里面有(标签名、子节点、文本等等)

Vue.nextTick

在下次 DOM 更新循环结束以后执行延迟回调。在修改数据以后当即使用这个方法,获取更新后的 DOM。
原理:事件循环机制(Event Loop)
如下事件属于宏任务:

setInterval()
setTimeout()
如下事件属于微任务

new Promise()
new MutaionObserver()

  1. MutationObserver监听DOM更新完毕的。
  2. vue用异步队列的方式来控制DOM更新和nextTick回调前后执行
  3. microtask(微任务)由于其高优先级特性,能确保队列中的微任务在一次事件循环前被执行完毕
  4. 由于兼容性问题,vue不得不作了microtask向macrotask(Promise)的降级方案

VUE的watch与computed的区别

  • 触发条件不一样

1.computed计算属性会依赖于使用它的data属性,只要是依赖的data属性值有变更,则自定义从新调用计算属性执行一次。
2.watch则是在监控的data属性值发生变更时,其会自动调用watch回调函数。

  • 应用场景不一样

1.执行异步操做,开销较大的操做,避免堵塞主线程,使用watch。
2.简单且串行返回的,使用computed

请解释闭包

《JavaScript权威指南》中的概念:有权访问另外一个做用域中变量的函数
闭包特性:可实现函数外访问函数内变量,外层变量能够不被垃圾回收机制回收。
缺点:

  1. 在闭包中使用this对象可能会致使一些问题,由于匿名函数的执行具备全局性,所以其this对象一般指window.
  2. 因为闭包会使得函数中的变量都被保存在内存中,内存消耗很大,因此不能滥用闭包,不然会形成网页的性能问题,在IE中可能致使内存泄露。解决方法是,在退出函数以前,将不使用的局部变量所有删除.
function outer() {
  var a = 2;
  function inner() {
    console.log(a);
  }
  return inner;
}
var neal = outer();
neal();//2

JS数据类型

基础类型:Undefined, Null, Boolean, Number, String, Symbol(ES6新增,表示独一无二的值))一共6种
引用类型:Object

JS中的基础数据类型,这些值都有固定的大小,每每都保存在栈内存中(闭包除外),由系统自动分配存储空间。咱们能够直接操做保存在栈内存空间的值,所以基础数据类型都是按值访问 数据在栈内存中的存储与使用方式相似于数据结构中的堆栈数据结构,遵循后进先出的原则。

JS的引用数据类型,好比数组Array,它们值的大小是不固定的。引用数据类型的值是保存在堆内存中的对象。JS不容许直接访问堆内存中的位置,所以咱们不能直接操做对象的堆内存空间。在操做对象时,其实是在操做对象的引用而不是实际的对象。所以,引用类型的值都是按引用访问的。这里的引用,咱们能够粗浅地理解为保存在栈内存中的一个地址,该地址与堆内存的实际值相关联。
clipboard.png

数据结构:

数据结构就是关系,没错,就是数据元素相互之间存在的一种或多种特定关系的集合。
逻辑结构:是指数据对象中数据元素之间的相互关系,也是咱们从此最须要关注和讨论的问题。
物理结构:是指数据的逻辑结构在计算机中的存储形式。

常见的数据结构:
数组,队列(queue),堆(heap),栈(stack),链表(linked list ),树(tree),图(graph)和散列表(hash)

参照:https://www.cnblogs.com/slly/...

  • 栈:

一种遵循后进先出(LIFO)原则的有序集合。新添加的或待删除的元素都保存在栈的同一端,称做栈顶,另外一端就叫栈底。在栈里,新元素都接近栈顶,旧元素都接近栈底。

  • 队列(queue):

是只容许在一端进行插入操做,而在另外一端进行删除操做的线性表。与栈相反,队列是一种先进先出(First In First Out, FIFO)的线性表。与栈相同的是,队列也是一种重要的线性结构,实现一个队列一样须要顺序表或链表做为基础。

  • 链表:

链表存储有序的元素集合,但不一样于数组,链表中的元素在内存中并非连续放置的。每一个元素由一个存储元素本事的节点和一个指向下一个元素的引用组成。相对于传统的数组,链表的一个好处在于,添加或者删除元素的时候不须要移动其余元素。 使用链表结构能够克服数组须要预先知道数据大小的缺点(C语言的数组须要预先定义长度),链表结构能够充分利用计算机内存空间,实现灵活的内存动态管理。 数组和链表的一个不一样在于数组能够直接访问任何位置的元素,而想要访问链表中的一个元素,须要从起点开始迭代列表。

click在ios上有300ms延迟,缘由及如何解决?

  1. 粗暴型,禁用缩放
<meta name="viewport" content="width=device-width, user-scalable=no">
  1. 利用FastClick,其原理是:
检测到touchend事件后,马上出发模拟click事件,而且把浏览器300毫秒以后真正出发的事件给阻断掉

css盒模型

1.IE盒子模型(怪异盒子)box-sizing :border-box;
宽度=margin+width
2.W3C标准盒模型box-sizing : content-box;

宽度=margin+border+padding+width

选择器权重

!important > 行内样式>ID选择器 > 类选择器 > 标签 > 通配符* > 继承 > 浏览器默认属性

有几种方法清楚浮动

1. 父元素 overflow: hidden;
2.浮动元素后面的元素: clear: both;
3.伪元素选择器:.clear::after{ content:’’;display:block; clear:both;};
4.父元素设置高度;
5.父级元素:display: table;

如何作水平垂直居中?

方案一:已知宽高,设置position: absolute;,而后left和top都设置为50%,再根据margin的负值来调正
方案二:相似方案一,最后一步用transform:translate(-50%,-50%);
方案三:绝对定位,top、bottom、left、right都设置为0,设置好宽高,而后margin: auto;
方案四:display:table-cell; + vertical-align:middle;
方案五:使用flex弹性盒模型

<div class=“box”>
    <div class=“item”></div>
</div>
box{
    display:flex;
    justifly-content:center;
    Align-item:center;
}
Box{
    Position:relative;
}
Item{
 Position:absolute;
 Top:50%;
 Transform:translateY(-50%);
}

选择器权重

!important > 行内样式>ID选择器 > 类选择器 > 标签 > 通配符* > 继承 > 浏览器默认属性

webpack的一些原理和机制

webpack:把全部依赖打包成一个 bundle.js 文件,经过代码分割成单元片断并按需加载。

  1. 解析webpack配置参数,合并从shell传入和webpack.config.js文件里配置的参数,生产最后的配置结果。
  2. 注册全部配置的插件,好让插件监听webpack构建生命周期的事件节点,以作出对应的反应。
  3. 从配置的entry入口文件开始解析文件构建AST语法树,找出每一个文件所依赖的文件,递归下去。
  4. 在解析文件递归的过程当中根据文件类型和loader配置找出合适的loader用来对文件进行转换。
  5. 递归完后获得每一个文件的最终结果,根据entry配置生成代码块chunk。
  6. 输出全部chunk到文件系统。

ES6模块与CommonJS模块的差别

  1. CommonJs 模块输出的是一个值的拷贝,ES6模块输出的是一个值的引用
  2. CommonJS 模块是运行时加载,ES6模块是编译时输出接口
  3. ES6输入的模块变量,只是一个符号连接,因此这个变量是只读的,对它进行从新赋值就会报错

模块加载AMD,CMD,CommonJS Modules/2.0 规范

AMD 是 RequireJS 在推广过程当中对模块定义的规范化产出(不过 RequireJS 从 2.0 开始,也改为能够延迟执行(根据写法不一样,处理方式不一样))。
CMD 是 SeaJS 在推广过程当中对模块定义的规范化产出。

  1. 这些规范的目的都是为了 JavaScript 的模块化开发,特别是在浏览器端的
  2. 对于依赖的模块,AMD 是提早执行,CMD 是延迟执行
  3. CMD 推崇依赖就近,AMD 推崇依赖前置

继承方式

相关文案

  1. 原型链继承
  2. 借用构造函数 (类式继承)
  3. 组合式继承(原型+构造函数继承)
  4. 原型式继承
  5. 寄生式继承
  6. 寄生组合式继承
父子类
function Animal(name) {
    this.name = name || "Mike";//实例属性
    this.love = function () {
      console.log(this.name + "爱吃骨头")//实例方法
    }
    this.other = [];//实例引用属性
  }
  Animal.prototype.sleep = function (place) {
    console.log(this.name + "在" + place + "睡觉")
  }
  • 原型链继承
function Dog() {}
  Dog.prototype = new Animal();
  Dog.prototype.name = "Jack";
  var dog1 = new Dog("twoHa");
  var dog2 = new Dog("keJi");
  console.log(dog1.name);//Jack
  console.log(dog2.name);//Jack
  dog1.love();//Jack爱吃骨头
  dog2.love();//Jack爱吃骨头
  dog1.sleep("床上");//Jack在床上睡觉
  dog2.sleep("客厅");//Jack在客厅睡觉

优势:
 1. 实例是子类的实例,也是父类的实例
 2. 父类新增原型方法/原型属性,子类都能访问到
 3. 简单,易于实现

缺点:

 1. 要想为子类新增属性和方法,必需要在new Animal()这样的语句以后执行,不能放到构造器中
 2. 没法实现多继承
 3. 来自原型对象的引用属性是全部实例共享的,改变实例会污染父类
 4. 建立子类实例时,没法向父类构造函数传参

XSS和CSRF

XSS跨站脚本攻击:
不须要你作任何的登陆认证,它会经过合法的操做(好比在url中输入、在评论框中输入),向你的页面注入脚本(多是js、hmtl代码块等)。

  • 编码:当恶意代码值被做为某一标签的内容显示:在不须要html输入的地方对html 标签及一些特殊字符( ” < > & 等等)作过滤,将其转化为不被浏览器解释执行的字符。
  • 在标签的 href、src 等属性中,包含 javascript: (伪协议)等可执行代码。
  • 过滤:移除用户输入的和事件相关的属性。如onerror能够自动触发攻击,还有onclick等。移除用户输入的Style节点、Script节点、Iframe节点。(尤为是Script节点,它但是支持跨域的呀,必定要移除);
  • httpOnly: 在 cookie 中设置 HttpOnly 属性后,js脚本将没法读取到 cookie 信息。
  • jsonp引起的xss攻击
  • 就是前面说到的,Content-Type 不要乱用,严格按照标准协议来作。目前的框架默认确定会检测一下内容类型,若是不是很必要,不要手动设置。由于有可能多转发几回 Content-Type 就被改了。
  • callback 作长度限制,这个比较 low。

检测 callback 里面的字符。通常 callback 里面都是字母和数字,别的符号都不能有。

  • callback 作一个编码,若是用 Go 语言作的话,以下。对全部 callback 都处理。callback = template.JSEscapeString(callback)
  • CSRF攻击:跨站请求伪造。

要完成一次CSRF攻击,受害者必须知足两个必要的条件:

  • 登陆受信任网站A,并在本地生成Cookie。(若是用户没有登陆网站A,那么网站B在诱导的时候,请求网站A的api接口时,会提示你登陆)
  • 在不登出A的状况下,访问危险网站B(实际上是利用了网站A的漏洞)。

舒适提示一下,cookie保证了用户能够处于登陆状态,但网站B其实拿不到 cookie。
预防

  • Token 验证:(用的最多)

(1)服务器发送给客户端一个token;
(2)客户端提交的表单中带着这个token。
(3)若是这个 token 不合法,那么服务器拒绝这个请求。

  • 隐藏令牌:

把 token 隐藏在 http 的 head头中。
方法二和方法一有点像,本质上没有太大区别,只是使用方式上有区别。

  • Referer 验证:Referer 指的是页面请求来源。意思是,只接受本站的请求,服务器才作响应;若是不是,就拦截。

XSS 与 CSRF异同

  • CSRF:须要用户先登陆网站A,获取 cookie。
  • XSS:不须要登陆。
  • CSRF:是利用网站A自己的漏洞,去请求网站A的api。
  • XSS:是向网站 A 注入 JS代码,而后执行 JS 里的代码,篡改网站A的内容。

HTTP

HTTP是用于传输如HTML文件,图片文件,查询结果的应用层协议。它被设计于用于服务端和客户端之间的通讯。

传统轮询(Traditional Polling)

当前Web应用中较常见的一种持续通讯方式,一般采起 setInterval 或者 setTimeout 实现。例如若是咱们想要定时获取并刷新页面上的数据,能够结合Ajax写出以下实现:

setInterval(function() {
    $.get("/path/to/server", function(data, status) {
        console.log(data);
    });
}, 10000);
缺陷:
程序在每次请求时都会新建一个HTTP请求,然而并非每次都能返回所需的新数据。
当同时发起的请求达到必定数目时,会对服务器形成较大负担。
  • 长轮询(long poll)

客户端发送一个request后,服务器拿到这个链接,若是有消息,才返回response给客户端。没有消息,就一直不返回response。以后客户端再次发送request, 重复上次的动做。

http协议的特色是服务器不能主动联系客户端,只能由客户端发起。它的被动性预示了在完成双向通讯时须要不停的链接或链接一直打开,这就须要服务器快速的处理速度或高并发的能力,是很是消耗资源的。

websocket 和http区别

 相同点:

  1. 都是应用层的协议
  2. 都是基于tcp,而且都是可靠的协议

不一样点:

  1. websocket是持久链接的协议,而http是非持久链接的协议.
  2. websocket是双向通讯协议,模拟socket协议,能够双向发送消息,而http是单向的.
  3. websocket的服务端能够主动向客服端发送信息,而http的服务端只有在客户端发起请求时才能发送数据,没法主动向客户端发送信息.

回流与重绘

  1. 当render tree(渲染树)中的一部分(或所有)由于元素的规模尺寸,布局,隐藏等改变而须要从新构建。这就称为回流(reflow)。每一个页面至少须要一次回流,就是在页面第一次加载的时候。在回流的时候,浏览器会使渲染树中受到影响的部分失效,并从新构造这部分渲染树,完成回流后,浏览器会从新绘制受影响的部分到屏幕中,该过程成为重绘。
  2. 当render tree中的一些元素须要更新属性,而这些属性只是影响元素的外观,风格,而不会影响布局的,好比background-color。则就叫称为重绘。

注意:回流必将引发重绘,而重绘不必定会引发回流。

    • 当页面布局和几何属性改变时就须要回流。下述状况会发生浏览器回流:
    1. 添加或者删除可见的DOM元素;
    2. 元素位置改变;
    3. 元素尺寸改变——边距、填充、边框、宽度和高度
    4. 内容改变——好比文本改变或者图片大小改变而引发的计算值宽度和高度改变;
    5. 页面渲染初始化;
    6. 浏览器窗口尺寸改变——resize事件发生时;

    请详细说下你对vue生命周期的理解?

    总共分为8个阶段建立前/后,载入前/后,更新前/后,销毁前/后
    beforeCreate 建立前执行(vue实例的挂载元素$el和数据对象data都为undefined,还未初始化)

    1. created 完成建立 (完成了data数据初始化,el还未初始化)
    2. beforeMount 载入前(vue实例的$el和data都初始化了,但仍是挂载以前为虚拟的dom节点,data.message还未替换。)
    3. mounted 载入后html已经渲染(vue实例挂载完成,data.message成功渲染。)
    4. beforeUpdate 更新前状态(view层的数据变化前,不是data中的数据改变前)
    5. updated 更新状态后
    6. beforeDestroy 销毁前
    7. destroyed 销毁后 (在执行destroy方法后,对data的改变不会再触发周期函数,说明此时vue实例已经解除了事件监听以及和dom的绑定,可是dom结构依然存在)

    说一下每个阶段能够作的事情

    1. beforeCreate:能够在这里加一个loading事件,在加载实例时触发。
    2. created:初始化完成时的事件写这里,若是这里结束了loading事件,异步请求也在这里调用。
    3. mounted:挂在元素,获取到DOM节点
    4. updated:对数据进行处理的函数写这里。
    5. beforeDestroy:能够写一个确认中止事件的确认框。
    相关文章
    相关标签/搜索