面试知识点突击

摘录各大语录,合集,非原创,连接较多后续添加。javascript

js 题库

原型链

原理

  • 原型prototype:对象,函数都有。css

  • 原型指针_proto_:属性,对象都有。html

  • 对象的_proto_指向构造函数的原型前端

obj._proto_ = Object.prototype
复制代码
  • A.prototype.constructer = A

new过程

var a = new B()
等同于
var a ={}
a._prototype_= B.prototype
B.call(a)
复制代码

类型

  • number,boolean,null,undefined,string,object(es6 symbol)
  • typeof =>输出类型:object,string,number,boolean,function,undefined
  • instanceof =>输出true or false 。
    • a instanceof b // a对象的原型链上是否存在b.prototype.constructor,一个对象在其原型链中是否存在一个构造函数的 prototype 属性
var arr = []
arr instanceof Array //true
typeof arr //object
null instanceof Object //false
typeof null //object
undefined instanceof Object //false
typeof undefined //undefined
function a (){}
a instanceof Object // true
typeof a //function
typeof NaN //number
复制代码

继承

原型

// 定义一个动物类
function Animal (name) {
  // 属性
  this.name = name || 'Animal';
  // 实例方法
  this.sleep = function(){
    console.log(this.name + '正在睡觉!');
  }
}
// 原型方法
Animal.prototype.eat = function(food) {
  console.log(this.name + '正在吃:' + food);
};
复制代码

原型链继承

function Cat(){ 
}
Cat.prototype = new Animal();
Cat.prototype.name = 'cat';

// Test Code
var cat = new Cat();
console.log(cat.name);
console.log(cat.eat('fish'));
console.log(cat.sleep());
console.log(cat instanceof Animal); //true 
console.log(cat instanceof Cat); //true
复制代码

特色:vue

很是纯粹的继承关系,实例是子类的实例,也是父类的实例 父类新增原型方法/原型属性,子类都能访问到 简单,易于实现java

缺点:node

若是要新增原型属性和方法,则必须放在new Animal()这样的语句以后执行;react

没法实现多继承,来自原型对象的全部属性被全部实例共享;ios

建立子类实例时,没法向父类构造函数传参es6

构造继承

function Cat(name){
  Animal.call(this);
  this.name = name || 'Tom';
}

// Test Code
var cat = new Cat();
console.log(cat.name);
console.log(cat.sleep());
console.log(cat instanceof Animal); // false
console.log(cat instanceof Cat); // true
复制代码

特色:

子类实例共享父类引用属性的问题 建立子类实例时,能够向父类传递参数 能够实现多继承(call多个父类对象)

缺点:

实例并非父类的实例,只是子类的实例 只能继承父类的实例属性和方法,不能继承原型属性/方法 没法实现函数复用,每一个子类都有父类实例函数的副本,影响性能

组合继承

function Cat(name){
  Animal.call(this);
  this.name = name || 'Tom';
}
Cat.prototype = new Animal();
Cat.prototype.constructor = Cat;

// Test Code
var cat = new Cat();
console.log(cat.name);
console.log(cat.sleep());
console.log(cat instanceof Animal); // true
console.log(cat instanceof Cat); // true

复制代码

特色:

能够继承实例属性/方法,也能够继承原型属性/方法 既是子类的实例,也是父类的实例 不存在引用属性共享问题 可传参 函数可复用

缺点:

调用了两次父类构造函数,生成了两份实例(子类实例将子类原型上的那份屏蔽了)

寄生组合继承

function Cat(name){
    Animal.call(this);
    this.name = name||'Tom';
}
(function(){
  // 建立一个没有实例方法的类
  var Super = function(){};
  Super.prototype = Animal.prototype;
  //将实例做为子类的原型
  Cat.prototype = new Super();
})();
Cat.prototype.constructor = Cat;
// Test Code
var cat = new Cat();
console.log(cat.name);
console.log(cat.sleep());
console.log(cat instanceof Animal); // true
console.log(cat instanceof Cat); //true
复制代码

方法

  • push():向数组尾部添加一个或多个元素,并返回添加新元素后的数组长度。注意,该方法会改变原数组
  • pop(): 删除数组的最后一个元素,并返回该元素。注意,该方法会改变原数组
  • unshift():在数组的第一个位置添加元素,并返回添加新元素后的数组长度。注意,该方法会改变原数组
  • shift():删除数组的第一个元素,并返回该元素。注意,该方法会改变原数组
  • valueOf():返回数组的自己。
  • indexOf():返回指定元素在数组中出现的位置,若是没有出现则返回-1。接受第二个参数,表示搜索的开始位置
    • str.indexOf(searchString,startIndex); 返回子字符串第一次出现的位置,从startIndex开始查找,找不到时返回-1
  • toString():返回数组的字符串形式
  • join():以参数做为分隔符,将全部数组成员组成一个字符串返回。若是不提供参数,默认用逗号分隔。
  • concat():用于多个数组的合并。它将新数组的成员,添加到原数组的尾部,而后返回一个新数组,原数组不变
  • reverse():用于颠倒数组中元素的顺序,返回改变后的数组。注意, 该方法将改变原数组
  • slice():用于截取原数组的一部分,返回一个新数组,原数组不变。 slice(start,end)它的第一个参数为起始位置(从0开始),第二个参数为终止位置(但该位置的元素自己不包括在内)。若是省略第二个参数,则一直返回到原数组的最后一个成员。
    • str.slice(start,end); 返回值:[start,end)
  • splice():删除原数组的一部分红员,并能够在被删除的位置添加入新的数组成员,返回值是被删除的元素。注意,该方法会改变原数组。 splice(start,delNum,addElement1,addElement2,...)第一个参数是删除的起始位置,第二个参数是被删除的元素个数。若是后面还有更多的参数,则表示这些就是要被插入数组的新元素。
  • sort():对数组成员进行排序,默认是按照字典顺序排序。排序后,原数组将被改变
  • map():对数组的全部成员依次调用一个函数,根据函数结果返回一个新数组。
  • filter():参数是一个函数,全部数组成员依次执行该函数,返回结果为true的成员组成一个新数组返回。该方法不会改变原数组
  • str.charAt(index); 返回子字符串,index为字符串下标,index取值范围[0,str.length-1]
  • str.split(separator,limit); 参数1指定字符串或正则,参照2指定数组的最大长度

promise原理

Promise 对象用于延迟(deferred) 计算和异步(asynchronous )计算.一个Promise对象表明着一个还未完成,但预期未来会完成的操做。Promise 对象是一个返回值的代理,这个返回值在promise对象建立时未必已知。它容许你为异步操做的成功或失败指定处理方法。 这使得异步方法能够像同步方法那样返回值:异步方法会返回一个包含了原返回值的 promise 对象来替代原返回值。

axios

  • 从浏览器生成XMLHttpRequests
  • 从node.js发出http请求
  • 支持Promise API
  • 拦截请求和响应
  • 转换请求和响应数据
  • 取消请求
  • 自动转换JSON数据
  • 客户端支持防范XSRF

安全

谈谈对前端安全的理解,有什么,怎么防范前端安全问题主要有XSS、CSRF攻击 XSS:跨站脚本攻击 它容许用户将恶意代码植入到提供给其余用户使用的页面中,能够简单的理解为一种javascript代码注入。

XSS的防护措施: 过滤转义输入输出 避免使用eval、new Function等执行字符串的方法,除非肯定字符串和用户输入无关 使用cookie的httpOnly属性,加上了这个属性的cookie字段,js是没法进行读写的 使用innerHTML、document.write的时候,若是数据是用户输入的,那么须要对象关键字符进行过滤与转义

CSRF:跨站请求伪造 其实就是网站中的一些提交行为,被黑客利用,在你访问黑客的网站的时候进行操做,会被操做到其余网站上

CSRF防护措施: 检测http referer是不是同域名 避免登陆的session长时间存储在客户端中 关键请求使用验证码或者token机制 其余的一些攻击方法还有HTTP劫持、界面操做劫持

webscoket

垃圾回收

vue

vuex

在main.js引入store,注入,新建一个目录store,….. export 等,经常使用的场景有:单页应用中,组件之间的状态,音乐播放、登陆状态、加入购物车等等。

Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的全部组件的状态。这里的关键在于集中式存储管理

  • 学院派:Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式;集中存储和管理应用的全部组件状态。

  • 理解:以上这4个词是咱们理解的关键。状态:什么是状态,咱们能够通俗的理解为数据。Vue只关心视图层,那么视图的状态如何来肯定?咱们知道是经过数据驱动,这里的状态管理能够简单理解为管理数据。集中存储:Vue只关心视图,那么咱们须要一个仓库(Store)来存储数据,并且是全部的数据集中存储,视图和数据就能够分析。管理:除了存储,还能够管理数据,也就是计算、处理数据。全部组件状态:所用的组件共用一个仓库(Store),也就是一个项目只有一个数据源(区分模块modules)。

  • 总结:Vuex就是在一个项目中,提供惟一的管理数据源的仓库。

  • 场景一:处理多组件依赖于同一个数据,例若有柱状图和条形图两个组件都是展现的同一数据;

  • 场景二: 一个组件的行为——改变数据——影响另外一个组件的视图,其实也就是公用依赖的数据;

  • Vuex将组件公用数据抽离,在一个公共仓库管理,使得各个组件容易获取(getter)数据,也容易设置数据(setter)

生命周期

vue生命周期总共分为8个阶段建立前/后,载入前/后,更新前/后,销毁前/后。

建立前/后: 在beforeCreated阶段,vue实例的挂载元素el尚未。

载入前/后:在beforeMount阶段,vue实例的$el和data都初始化了,但仍是挂载以前为虚拟的dom节点,data.message还未替换。在mounted阶段,vue实例挂载完成,data.message成功渲染。

更新前/后:当data变化时,会触发beforeUpdate和updated方法。

销毁前/后:在执行destroy方法后,对data的改变不会再触发周期函数,说明此时vue实例已经解除了事件监听以及和dom的绑定,可是dom结构依然存在。

双向数据绑定原理

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

第一步:须要observe的数据对象进行递归遍历,包括子属性对象的属性,都加上 setter和getter。这样的话,给这个对象的某个值赋值,就会触发setter,那么就能监听到了数据变化

第二步:compile解析模板指令,将模板中的变量替换成数据,而后初始化渲染页面视图,并将每一个指令对应的节点绑定更新函数,添加监听数据的订阅者,一旦数据有变更,收到通知,更新视图

第三步:Watcher订阅者是Observer和Compile之间通讯的桥梁,主要作的事情是:

一、在自身实例化时往属性订阅器(dep)里面添加本身

二、自身必须有一个update()方法

三、待属性变更dep.notice()通知时,能调用自身的update()方法,并触发Compile中绑定的回调,则功成身退。

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

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节点,里面有(标签名、子节点、文本等等)

1.获取el元素。

2.判断el是否为body或者html。

3.为$options编译render函数。

4.执行以前的mount函数。

关键在于第三步,编译 render 函数上。先获取 template,即获取HTML内容,而后执行 compileToFunctions 来编译,最后将 render 和 staticRenderFns 传给 vm.$options 对象。

  1. 经过 baseCompile 方法进行编译;
  2. 经过 createCompilerCreator 中的 compile 方法合并配置参数并返回 baseCompile 方法执行结果;
  3. createCompilerCreator 返回 compile 方法和 compileToFunctions 方法;
  4. compileToFunctions 方法用于将方法字符串生成真实方法。

baseCompile:

  1. parse 将HTML解析为 AST 元素。
  2. optimize该方法只是作了些标记静态节点的行为,目的是为了在从新渲染时不重复渲染静态节点,以达到性能优化的目的。
  3. generate 解析成基本的 render 函数

vue-router

单页面应用(SPA)的核心之一是: 更新视图而不从新请求页面。

一、Hash模式: hash(#)是URL 的锚点,表明的是网页中的一个位置,单单改变#后的部分,浏览器只会滚动到相应位置,不会从新加载网页,也就是说 #是用来指导浏览器动做的,对服务器端彻底无用,HTTP请求中也不会不包括#;同时每一次改变#后的部分,都会在浏览器的访问历史中增长一个记录,使用”后退”按钮,就能够回到上一个位置;

二、History模式: HTML5 History API提供了一种功能,能让开发人员在不刷新整个页面的状况下修改站点的URL,就是利用 history.pushState API 来完成 URL 跳转而无须从新加载页面;

  • Vue-Router的两种模式主要依赖什么实现的

hash主要依赖location.hash来改动 URL,达到不刷新跳转的效果.每次 hash 改变都会触发hashchange事件(来响应路由的变化,好比页面的更换) history主要利用了 HTML5的 historyAPI 来实现,用pushState和replaceState来操做浏览历史记录栈

  • 钩子函数

    • 全局的钩子

      beforeEach(to,from,next)

      afterEach(to,from,next)

    • 单个路由里面的钩子

      beforeEnter(to,from,next)

      beforeLeave (to, from, next)

    • 组件内的钩子

      beforeRouteEnter、beforeRouteUpdate、beforeRouteLeave

    vue和react

  • 相同点:都支持 ssr,都有 vdom,组件化开发,实现 webComponents 规范,数据驱动等

  • 不一样点:vue 是双向数据流(固然为了实现单数据流方便管理组件状态,vuex 便出现了),react 是单向数据流。vue 的 vdom 是追踪每一个组件的依赖关系,不会渲染整个组件树,react 每当应该状态被改变时,所有子组件都会 re-render。

VDOM 的必要性?

  • 建立真实DOM的代价高:真实的 DOM 节点 node 实现的属性不少,而 vnode 仅仅实现一些必要的属性,相比起来,建立一个 vnode 的成本比较低。 触发屡次浏览器重绘及回流:使用 vnode ,至关于加了一个缓冲,让一次数据变更所带来的全部 node 变化,先在 vnode 中进行修改,而后 diff 以后对全部产生差别的节点集中一次对 DOM tree 进行修改,以减小浏览器的重绘及回流。

vue 为何采用 vdom?

  • 性能受场景的影响是很是大的,不一样的场景可能形成不一样实现方案之间成倍的性能差距,因此依赖细粒度绑定及 Virtual DOM 哪一个的性能更好还真不是一个容易下定论的问题。 Vue 之因此引入了 Virtual DOM,更重要的缘由是为了解耦 HTML 依赖,这带来两个很是重要的好处是:

  • 再也不依赖 HTML 解析器进行模版解析,能够进行更多的 AOT 工做提升运行时效率:经过模版 AOT 编译,Vue 的运行时体积能够进一步压缩,运行时效率能够进一步提高; 能够渲染到 DOM 之外的平台,实现 SSR、同构渲染这些高级特性,Weex 等框架应用的就是这一特性。

  • 综上,Virtual DOM 在性能上的收益并非最主要的,更重要的是它使得 Vue 具有了现代框架应有的高级特性。

vue SSR ...

axios

css

未知宽高的元素实现水平垂直居中

.parent{
            width:100%;
            height:400px;
            position:relative;
        }
        .children{
            position:absolute;
            top:50%;
            left:50%;
            transform:translate(-50%,-50%);
        }
复制代码
.parent{
            width:100%;
            height:400px;
            display:flex;
            align-items:center;
            justify-content:center;
        }
        .children{
            background:red;
        }

复制代码
.parent{
            display:table;
            width:100%;
            height:400px;
        }
        .children{
            display:table-cell;
            vertical-align:middle;
            text-align:center;
        }

复制代码

深复制

var json1 = {
    name: 'aaa',
    age: 25,
    data: {
        a: 1,
        b: 2
    }
};

function deepCopy(parent, child) {
    var child = child || {};// 并非直接声明一个新child为空{},传过来的就用传过来的
    for(var i in parent) {
        if(typeof parent[i] === 'object') {
            child[i] = (parent[i].constructor === Array) ? [] : {};// child.data = {};
            deepCopy(parent[i], child[i]);// {a: 1,b: 2},传过去的是child.data的空json
        }
        else {
            child[i] = parent[i];// child.data.a ...
        }
    }
    return child;
}

var json2 = deepCopy(json1);
json2.data.a = 3;
console.log(json1.data.a);// json1.data.a不受影响,仍旧是1
console.log(json2.data.a);

复制代码

算法

都是从小到大

//冒泡
function a (arr){
    for(var i;arr<length;i++){
        for(var j;arr<=length-1;i++){
        if(arr[j]>arr[j+1]){
            var b ;
            b = arr[j];
            arr[j] = arr[j+1];
            arr[j+1] = b;
        }
    }
    }
    return arr;
}
复制代码
function b (arr){
    if(arr.length<=1){return arr;}
    var left =[];
    var right = [];
    var a = Math.floor(arr.length/2);
    var indexs = arr.splice(a,1)[0];
    for(var i=0;i<length;i++){
        if(indexs > arr[i]){
            left.push(arr[i]);
        }else{
            right.push(arr[i]);
        }
    }
    return b(left).concat([indexs],b(right));
}

复制代码

优化

  1. 减小http请求(雪碧)
  2. 将样式表放在头部
  3. 将脚本放在底部
  4. 针对第三方库文件使用cdn方式
  5. 慎用deep watch
  6. v-if v-show
  7. keep-alive

打包库忽略externals

1、加载渲染过程

父beforeCreate->父created->父beforeMount->子beforeCreate->子created->子beforeMount->子mounted->父mounted

2、子组件更新过程

父beforeUpdate->子beforeUpdate->子updated->父updated

3、父组件更新过程

父beforeUpdate->父updated

4、销毁过程

父beforeDestroy->子beforeDestroy->子destroyed->父destroyed

相关文章
相关标签/搜索