前端面试题收集

常见前端面试题整理贴

JS

js的继承实现

JavaScript 对象有一个指向一个原型对象的链。当试图访问一个对象的属性时,它不仅仅在该对象上搜寻,还会搜寻该对象的原型,以及该对象的原型的原型,依此层层向上搜索,直到找到一个名字匹配的属性或到达原型链的末尾。

创建方式

构造器方法

构造器其实就是一个普通的函数。当使用 new 操作符 来作用这个函数时,它就可以被称为构造方法(构造函数)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
function Graph() {
this.vertices = [];
this.edges = [];
}
Graph.prototype = {
addVertex: function(v){
this.vertices.push(v);
}
};
var g = new Graph();
// g是生成的对象,他的自身属性有'vertices'和'edges'.
// 在g被实例化时,g.[[Prototype]]指向了Graph.prototype.

Object.create (es5)

ECMAScript 5 中引入了一个新方法:Object.create()。可以调用这个方法来创建一个新对象。新对象的原型就是调用 create 方法时传入的第一个参数:

1
2
3
4
5
6
7
8
9
10
11
12
13
var a = {a: 1};
// a ---> Object.prototype ---> null
var b = Object.create(a);
// b ---> a ---> Object.prototype ---> null
console.log(b.a); // 1 (继承而来)
var c = Object.create(b);
// c ---> b ---> a ---> Object.prototype ---> null
var d = Object.create(null);
// d ---> null
console.log(d.hasOwnProperty); // undefined, 因为d没有继承Object.prototype

class (es6)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class Polygon {
constructor(height, width) {
this.height = height;
this.width = width;
}
}
class Square extends Polygon {
constructor(sideLength) {
super(sideLength, sideLength);
}
get area() {
return this.height * this.width;
}
set sideLength(newLength) {
this.height = newLength;
this.width = newLength;
}
}
var square = new Square(2);

性能

遍历对象的属性时,原型链上的每个可枚举属性都会被枚举出来。
hasOwnProperty 是 JavaScript 中唯一一个只涉及对象自身属性而不会遍历原型链的方法。

js的闭包

1
2
闭包是指那些能够访问独立(自由)变量的函数 (变量在本地使用,但定义在一个封闭的作用域中)。
换句话说,这些函数可以“记忆”它被创建时候的环境。

闭包是指能够访问在封闭作用于内的变量的函数,这些函数可以保存它们被创建时的环境。

1
2
3
4
5
6
7
8
9
10
function makeFunc() {
var name = "Mozilla";
function displayName() {
alert(name);
}
return displayName;
}
var myFunc = makeFunc();
myFunc();

闭包的应用

  • 访问私有属性

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    var Foo = function(){
    var name = 'fooname';
    var age = 12;
    this.getName = function(){
    return name;
    };
    this.getAge = function(){
    return age;
    };
    };
    var foo = new Foo();
    foo.name; // => undefined
    foo.age; // => undefined
    foo.getName(); // => 'fooname'
    foo.getAge(); // => 12
  • 在内存中维持变量:如果缓存数据、柯里化。

性能问题

需要注意的,由于闭包内的部分资源无法自动释放,容易造成内存泄露

“use strict”;

声明方式

  • script 声明
  • function 声明

    区别

    语法错误

    如果代码中使用”use strict”开启了严格模式,则下面的情况都会在脚本运行之前抛出SyntaxError异常:

  • 八进制语法:var n = 023和var s = “\047” (数字前不能有0)

  • with语句
  • 使用delete删除一个变量名(而不是属性名):delete myVariable
  • 使用eval或arguments作为变量名或函数名
  • 使用未来保留字(也许会在ECMAScript 6中使用):implements, interface, let, package, private, protected, public, static,和yield作为变量名或函数名
  • 在语句块中使用函数声明:if(a<b){ function f(){} }
  • 对象字面量中使用两个相同的属性名:{a: 1, b: 3, a: 7}
  • 函数形参中使用两个相同的参数名:function f(a, b, b){}

语义差异

函数调用中的this

在普通的函数调用f()中,this的值会指向全局对象.在严格模式中,this的值会指向undefined.当函数通过call和apply调用时,如果传入的thisvalue参数是一个null和undefined除外的原始值(字符串,数字,布尔值),则this的值会成为那个原始值对应的包装对象,如果thisvalue参数的值是undefined或null,则this的值会指向全局对象.在严格模式中,this的值就是thisvalue参数的值,没有任何类型转换.

arguments对象属性不与对应的形参变量同步更新

在非严格模式中,修改arguments对象中某个索引属性的值,和这个属性对应的形参变量的值也会同时变化,反之亦然.这会让JavaScript的代码混淆引擎让代码变得更难读和理解。在严格模式中arguments 对象会以形参变量的拷贝的形式被创建和初始化,因此 arguments 对象的改变不会影响形参。

eval相关的区别

在严格模式中,eval不会在当前的作用域内创建新的变量.另外,传入eval的字符串参数也会按照严格模式来解析.你需要全面测试来确保没有代码收到影响。另外,如果你并不是为了解决一个非常实际的解决方案中,尽量不要使用eval。

this

全局上下文

在全局运行上下文中(在任何函数体外部),this指代全局对象,无论是否在严格模式下。

函数上下文

在函数内部,this的值取决于函数是如何调用的。

直接调用
  • 非严格模式 window
  • 严格模式 如果this未被执行的上下文环境定义,那么它将会默认为undefined。

对象方法中的 this

对象方法中的this,指向调用该函数的对象(就近原则)

构造函数中的 this

当一个函数被作为一个构造函数来使用(使用new关键字),它的this与即将被创建的新对象绑定。

call / apply

绑定到一个指定的对象上

bind

f.bind(someObject)会创建一个与f具有相同函数体和作用域的函数,但是在这个新函数中,this将永久地被绑定到了bind的第一个参数

事件委托

在一个对象上触发某类事件(比如单击onclick事件),如果此对象定义了此事件的处理程序,那么此事件就会调用这个处理程序,如果没有定义此事件处理程序或者事件返回true,那么这个事件会向这个对象的父级对象传播,从里到外,直至它被处理(父级对象所有同类事件都将被激活),或者它到达了对象层次的最顶层,即document对象(有些浏览器是window)。

阻止继续冒泡

stopPropagation()

AMD/CMD/UMD

  1. 对于依赖的模块,AMD 是提前执行,CMD 是延迟执行。不过 RequireJS 从 2.0 开始,也改成可以延迟执行(根据写法不同,处理方式不同)。CMD 推崇 as lazy as possible.2. CMD 推崇依赖就近,AMD 推崇依赖前置。看代码:
    在 RequireJS 里,模块有多种书写格式,推荐的是:
    define([“./a”, “./b”], function(a, b) {
    a.doSomething();
    b.doSomething();
    });
    在 SeaJS 里,模块只有一种书写格式:
    define(function(require, exports, module) {
    require(“./a”).doSomething();
    require(“./b”).doSomething();
    });

CSS

盒子模型

里到外 padding border margin

box-sizing

属性用于更改用于计算元素宽度和高度的默认的 CSS 盒子模型。可以使用此属性来模拟不正确支持CSS盒子模型规范的浏览器的行为。

content-box

默认值,标准盒子模型。 width 与 height 只包括内容的宽和高, 不包括边框(border),内边距(padding),外边距(margin)。

border-box

width 和 height 属性包括内容,内边距和边框,但不包括外边距。

position有哪些属性,各自是什么特点?

static

该关键字指定元素使用正常的布局行为,即元素在文档流中当前的布局位置。此时 top, right, bottom, left 和 z-index 属性无效。

relative

该关键字下,元素先放置在未添加定位时的位置,再在不改变页面布局的前提下调整元素位置(因此会在此元素未添加定位时所在位置留下空白)。position:relative 未定义对 table, 元素应用的效果。

absolute

不为元素预留空间,通过指定元素相对于最近的非 static 定位祖先元素的偏移,来确定元素位置。绝对定位的元素可以设置外边距(margins),且不会与其他边距合并。

fixed

不为元素预留空间,而是通过指定元素相对于屏幕视口(viewport)的位置来指定元素位置。元素的位置在屏幕滚动时不会改变。打印时,元素会出现在的每页的固定位置。fixed 属性会创建新的栈上下文。当元素祖先的 transform 属性非 none 时,容器由视口改为该祖先。

sticky

盒位置根据正常流计算(这称为正常流动中的位置),然后相对于该元素在流中的 flow root(BFC)和 containing block(最近的块级祖先元素)定位。在所有情况下(即便被定位元素为 table 时),该元素定位均不对后续元素造成影响。当元素 B 被粘性定位时,后续元素的位置仍按照 B 未定位时的位置来确定。position: sticky 对 table 元素的效果与 position: relative 相同。

垂直居中

table

1
2
3
4
5
6
7
8
#wrapper {
display: table;
}
#cell {
display: table-cell;
vertical-align: middle;
}

绝对定位

1
2
3
4
5
#content {
position: relative;
top: 50%;
transform: translateY(-50%);
}

行高(单行文本)

flex

1
2
3
4
#content{
display:flex;
align-item: center
}

JS

圣杯布局

http://www.cnblogs.com/imwtr/p/4441741.html

flex

http://www.cnblogs.com/imwtr/p/4441741.html

grid

https://css-tricks.com/snippets/css/complete-guide-grid/

HTML

Style标签放置的最佳位置

head 里,提前加载样式
w3c不建议放在body中,新增的style标签的“scoped”属性(兼容性不行,只有FF)

常见行内元素和块级元素

行内 : b, em, strong,
a, br, img, span, sub, sup
button, input, label, select, textarea

块级元素:canvas,div,dl,footer,form,h1,header,hr,p,pre,section,table,ul,li

HTML5 新增标签

article, audio, video, canvas, footer, header, nav, section

Doctype

<!DOCTYPE> 告知 浏览器 当前的 HTML (或 XML) 文档是哪一个版本. Doctype 是一条 声明, 而不是一个 标签; 也可以把它叫做 “文档类型声明”, 或 简称为 “DTD”.

浏览器

IE和Chrome事件模型的区别

Chrome 捕获=>目标=>冒泡
IE 目标=>冒泡

cookie和session区别

1,session 在服务器端,cookie 在客户端(浏览器)
2,session 默认被存在在服务器的一个文件里(不是内存)
3,session 的运行依赖 session id,而 session id 是存在 cookie 中的,也就是说,如果浏览器禁用了 cookie ,同时 session 也会失效(但是可以通过其它方式实现,比如在 url 中传递 session_id)
4,session 可以放在 文件、数据库、或内存中都可以。
5,用户验证这种场合一般会用 session

浏览器缓存策略

HTTP 缓存

Cache-Control:public, max-age=31536000

HTML5 manifest

localStorage

Service Worker

HTTP

处理跨域的方法

Iframe + document.domain

原理:相同主域名不同子域名下的页面,可以设置document.domain让它们同域
限制:同域document提供的是页面间的互操作,需要载入iframe页面

有src的标签(统计代码)

原理:所有具有src属性的HTML标签都是可以跨域的,包括img, script
限制:需要创建一个DOM对象,只能用于GET方法

JSONP

原理:script是可以跨域的,而且在跨域脚本中可以直接回调当前脚本的函数。
限制:需要创建一个DOM对象并且添加到DOM树,只能用于GET方法
.getJSON与.get的区别是前者会把responseText转换为JSON,而且当URL具有callback参数时, jQuery将会把它解释为一个JSONP请求,创建一个script标签来完成该请求。

跨域资源共享(CORS)

原理:服务器设置Access-Control-Allow-OriginHTTP响应头之后,浏览器将会允许跨域请求
限制:浏览器需要支持HTML5,可以支持POST,PUT等方法

常见HTTP状态码

  1. 1xx消息
  2. 2xx成功
  3. 3xx重定向
  4. 4xx客户端错误
  5. 5xx服务器错误

    GET和POST的区别

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

HTTP的底层是TCP/IP。所以GET和POST的底层也是TCP/IP,也就是说,GET/POST都是TCP链接。GET和POST能做的事情是一样一样的。你要给GET加上request body,给POST带上url参数,技术上是完全行的通的。

GET和POST本质上就是TCP链接,并无差别。但是由于HTTP的规定和浏览器/服务器的限制,导致他们在应用过程中体现出一些不同。

GET产生一个TCP数据包;POST产生两个TCP数据包。

对于GET方式的请求,浏览器会把http header和data一并发送出去,服务器响应200(返回数据);
而对于POST,浏览器先发送header,服务器响应100 continue,浏览器再发送data,服务器响应200 ok(返回数据)。

url请求的过程

浏览器查找域名的 IP 地址
这一步包括 DNS 具体的查找过程,包括:浏览器缓存->系统缓存->路由器缓存…
浏览器向 web 服务器发送一个 HTTP 请求 4. 服务器的永久重定向响应(从 http://example.comhttp://www.example.com)
浏览器跟踪重定向地址
服务器处理请求
服务器返回一个 HTTP 响应
浏览器显示 HTML
浏览器发送请求获取嵌入在 HTML 中的资源(如图片、音频、视频、CSS、JS等等)
浏览器发送异步请求

服务器技术

websocket

框架

antdesign

React的diff原理和组件化思想

state / props

props不变的,state变的。

f7优缺点

node版本的区别

angularjs 脏检查

Angular将双向绑定转换为一堆watch表达式,然后递归检查这些watch表达式的结果是否变化。如果变化,则执行相应的watcher函数。等到model值不再变化,也就不会再有watch函数被触发,则一个digest循环结束。
$watch: 监听scope model变化
$apply: 触发“脏检查”
$digest: 内部函数,执行脏检查。 digest循环包括2个while循环:
处理$evalAsync的异步运算队列
处理$watch的wathers队列