Interview

CSS盒模型

分为标准盒模型和IE盒模型,标准盒模型width仅包括content部分,IE盒模型包括除Margin以外的部分。

切换盒模型可以借助CSS3的box-sizing属性

box-sizing:content-box; // W3C 默认值
box-sizing:border-box; //IE

JS获取盒模型宽高

dom.style.width/height  //只能获取内联样式的宽高,如所指定元素不存在内联样式,则无法获取
dom.currentStyle.width/height //仅限ie使用
window.getComputedStyle(dom).width/height //支持Firefox,Chrome
dom.getBoundingClientRect().width/height //返回元素的大小及其相对于视口的位置

块格式化上下文

BFC 定义

  BFC(Block formatting context)直译为”块级格式化上下文”。它是一个独立的渲染区域,只有Block-level box参与, 它规定了内部的Block-level Box如何布局,并且与这个区域外部毫不相干。

BFC布局规则:

  1. 内部的Box会在垂直方向,一个接一个地放置。
  2. Box垂直方向的距离由margin决定。属于同一个BFC的两个相邻Box的margin会发生重叠
  3. BFC的区域不会与float box重叠。
  4. BFC就是页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面的元素。反之也如此。
  5. 计算BFC的高度时,浮动元素也参与计算

下列方式会创建块格式化上下文

### DOM

DOM事件级别

DOM0 element.onclick = function(){}
DOM2 element.addEventListener("click",function(){},flase)
DOM2 element.addEventListener("keyup",function(){},flase)

DOM事件模型

事件捕获和事件冒泡

#### DOM事件流

事件捕获=>目标节点=>事件冒泡

DOM事件捕获具体流程

window=>document=>html

获取html

document.documentElemenet //文档的文档元素, 作为一个元素对象返回

EVENT对象的常见应用

event.preventDefault() ; //阻止默认行为
event.cancelBubble(); //阻止默认行为 ,IE专用
event.stopPropagation() ; //阻止冒泡,阻止把事件分派到其他节点
event.stopImmediatePropagation(); //如果有多个相同类型事件的事件监听函数绑定到同一个元素,当该类型的事件触发时,它们会按照被添加的顺序执行。如果其中某个监听函数执行了当前方法,则当前元素剩下的监听函数将不会被执行。
e.target //指向触发事件监听的对象。
e.currentTarget //指向添加监听事件的对象。

自定义事件

let selfEvent = new Event('self',{
      "bubbles" : true,//可选,Boolean类型,默认值为 false,表示该事件是否冒泡。
      "cancelable" : false,//可选,Boolean类型,默认值为 false, 表示该事件能否被取消。
    });
let doc = document.querySelector('.layout .left');
doc.addEventListener('self', () => {
  alert('This is Self Event');
})
doc.dispatchEvent(selfEvent)

CustomEvent()

var custom = new CustomEvent('custom',{
      "detail" : {  //可携带额外的数据
        age : 18
      },
      "bubbles" : true,
      "cancelable" : false,
    });
    用法与Event()相同,可携带数据,IE不支持

HTTP协议的主要特点

HTTP协议

HTTP报文的组成部分

请求报文
相应报文

HTTP方法

GET和POST的区别

#### HTTP状态码

HTTP持久连接

HTTP协议采用“请求-应答”模式,当使用普通模式,即非Keep-Alive模式时,每个请求/应答客户和服务器都要新建一个连接,完成之后立即断开连接(HTTP协议为无连接的协议)

当使用Keep-Alive模式(又称持久连接,连接重用)时,Keep-Alive功能使客户端到服务器端的连接持续有效,当出现对服务器的后继请求时,Keep-Alive功能避免了建立或者重新建立连接

Keep-Alive在HTTP1.1中存在

HTTP协议管线化(了解)

在使用持久连接的情况下,某个连接上消息的传递类似于

请求1->响应1->请求2->响应2->请求3->响应3

某个连接上的消息变成了类似这样

请求1->请求2->请求3->响应1->响应2->响应3

原型链

创建对象的几种方法
//对象字面量

var o1 = {name:"o1"};        //{obj: 1}
var o2 = new Object({name:'o2'}); //{obj: 1}

//构造函数

var m = function(name){this.name = name;}
var o3 = new m('o3');  //m {name: "o3"}

//Obejct.create

var p = {name:'p'}
var o4 = Object.create(p);  //{ }

只有实例才有__proto__

只有对象才有prototype

构造函数的prototype指向他的原型对象,原型对象含有一个constructor指针指向构造函数,实例有一个__proto__指向生成这个实例的构造函数的原型对象,实例还有一个``constructor`指针指向生成这个实例的构造函数

m.prototype.constructor === o3.constructor //true

instanceof的原理是判断实例对象__proto__属性与构造函数的prototype属性是不是引用同一个地址

实例 instanceof其原型链上任意一个构造函数都返回true

如果需要判断当前实例是由原型链上哪个构造函数生成的

o3.__proto__.constructor === m //true

new 运算符

当运行new运算符后

Object.create()方法创建一个新对象,使用现有的对象来提供新创建的对象的__proto__

所以通过Object.create()方法创建的对象,如果没有添加第二个参数,就是一个空对象,创建时传入的对象成为了这个新的空对象的原型对象

面向对象

继承
ES5 借助构造函数实现继承
function Animal(){
    //do something
}
function Parent1(){
    this.name = 'parent1';
}
function Child1(){
  Parent1.call(this); //将父级构造函数的This指向子构造函数的实例
    this.type = 'child1';
}
借助原型链实现继承
function Parent(){
  this.name = 'parent';
    this.arr = [1,2,3]
}
function Child(){
  this.type = 'child';
}
Child.prototype = new Parent();

var o1 = new Child();
var o2 = new Child();
o1.arr.push(4) ;
o1.arr //[1,2,3,4]
o2.arr //[1,2,3,4]

将父类对象作为子类构造函数的原型对象,所以父类对象中所有的属性和方法在子类对象中均是共享的,也就是说,所有的子类对象共享一份父类对象的属性和方法

构造函数与原型链组合继承

        function Parent() {
            this.name = 'parent';
            this.arr = [1, 2, 3]
        }

        function Child() {
            Parent.call(this);
            this.type = 'child'
        }
        Child.prototype = new Parent();
        var o1 = new Child;
        var o2 = new Child;
        o1.arr.push(4)
        console.log(o1.arr,o2.arr) //[1,2,3,4],[1,2,3]

缺点

多次执行父类构造函数,子类与父类的原型对象是同一个,所以无法判断实例到底是哪个构造函数生成的实例,Child没有自己的constructor

        function Parent() {
            this.name = 'parent';
            this.arr = [1, 2, 3]
        }

        function Child() {
            Parent.call(this);
            this.type = 'child'
        }
        Child.prototype = Parent.prototype;
        var o1 = new Child;
        var o2 = new Child;
        o1.arr.push(4)
        console.log(o1.arr,o2.arr) //[1,2,3,4],[1,2,3]

这种方式同样可以实现继承,因为在子类通过构造函数继承的时候,已经拿到了父类构造函数的所有属性和方法,剩下的只需要拿到父类构造函数原型链上的方法和属性,这样将子类构造函数的原型对象设置为父类构造函数的原型对象即可实现

缺点

子类与父类的原型对象是同一个,所以无法判断实例到底是哪个构造函数生成的实例

function Parent() {
  this.name = 'parent';
  this.arr = [1, 2, 3]
}
function Child() {
  Parent.call(this);
  this.type = 'child'
}
Child.prototype = Object.create(Parent.prototype);
Child.prototype.constructor = Child;

这样在子类构造函数的原型对象与父类构造函数的原型对象构建了一个中间层,将其隔离的目的是为了手动设置子类构造函数的原型对象的constructor而不影响父类构造函数的原型对象的constructor,上面的第二种写法如果直接指定子类的构造函数的原型对象的constructor,那么父类的构造函数的原型对象的constructor也会被改变

### 通信

什么是同源策略及限制,前后端如何通信,如何创建Ajax,跨域通信的几种方式

  1. 同源策略限制从一个源加载的文档或脚本如何与来自另一个源的资源进行交互。这是一个用于隔离潜在恶意文件的关键的安全机制。源包括协议,域名,端口
  1. 前后端如何通信:Ajax,WebSocket(不受同源策略限制),CORS(支持跨域通信与同步通信)

  2. 1

  3. 跨域通信的几种方式:

    • JSONP

    • HASH(URL后面连接的#叫做HASH,HASH的改变并不会刷新页面,URL后面连接的?叫做SEARCH,SEARCH的改变会触发页面刷新)
    • postMessage
    • WebSocket
    • CORS

JSONP

function addScriptTag(src) {
  var script = document.createElement('script');
  script.setAttribute("type","text/javascript");
  script.src = src;
  document.body.appendChild(script);
}
url:http://tcc.taobao.com/cc/json/mobile_tel_segment.htm?tel=18845798396&callback=cb
callback需要手动指定,且为全局函数,用于接收返回数据

HASH

利用hash,场景是当前页面A通过iframe或frame嵌入了跨域的页面B

var src = originURL + '#' + data;
document.getElementById('myIFrame').src = src;
子窗口通过监听hashchange事件得到通知。
window.onhashchange = checkMessage;

function checkMessage() {
  var message = window.location.hash;
  // ...
}
同样的,子窗口也可以改变父窗口的片段标识符。

postMessage

var popup = window.open('http://bbb.com', 'title');
popup.postMessage('Hello World!', 'http://bbb.com');
窗口A向窗口B发送信息
Bwindow.postMessage('data',"url");
B窗口中监听
window.addEventListener('message',function(event){
    console.log(event.origin); //http:A.com
    console.log(event.source); //Awindow
    console.log(event.data); //data!
})

WebSocket

var ws = new WebSocket("wss://echo.websocket.org");//ws非加密,wss加密
        var tet = document.querySelector('#text');

        ws.onopen = function(evt) {
            tet.innerHTML += `<br/>Connection open ...<br/>`
            ws.send("HEYYYYYY");
        };

        ws.onmessage = function(evt) {
            tet.innerHTML += `Received Message:${evt.data}<br/>`
            ws.close();
        };

        ws.onclose = function(evt) {
            tet.innerHTML += `Connection closed.`
        };

CORS

CORS是一个W3C标准,全称是”跨域资源共享”(Cross-origin resource sharing)。

它允许浏览器向跨源服务器,发出XMLHttpRequest请求,从而克服了AJAX只能同源使用的限制。

CORS与JSONP的使用目的相同,但是比JSONP更强大。

JSONP只支持GET请求,CORS支持所有类型的HTTP请求。JSONP的优势在于支持老式浏览器,以及可以向不支持CORS的网站请求数据。

安全

CSRF

跨站请求伪造(Cross-site request forgery)缩写CSRF

当用户注册并登录网站A后,网站A就会下放Cookie保存在浏览器中,用于下次登录。网站B会存在一个引诱链接,当用户点击后网站B会调用网站A的API接口,浏览器就会自动上传保存在浏览器中的Cookie,网站A通过验证后就会允许网站B的登录行为

防御

XSS

跨域脚本攻击(cross-site scripting)

CLICK

通过合法的渠道向页面中注入js脚本

禁止执行用户插入的js脚本

CSRF利用网站的漏洞发起攻击,XSS则是通过直接注入js执行脚本,而且CSRF需要用户曾经发起过登录行为

算法

渲染机制

JS运行机制

JS单线程运行,也就是JS同时只能处理一个事件,SetTimeout得以通过异步的方式执行,是因为JS采用了任务队列的方式

console.log(1);
setTimeout(()=>console.log(2),0);
console.log(3);

//1 3 2

console.log('A');
setTimeout(()=>console.log('B'),0);
while(true){}

//A

在上面的例子中,setTimeout属于异步队列。在所有的同步队列执行完毕之前,任何异步队列都不会被响应。

for(var i=0;i<4;i++){
    setTimeout(function(){
        console.log(i);
    },1000);
};
for(var i=0;i<4;i++){
    setTimeout(function(){
        console.log(i);
    },0);
};
// 4 4 4 4
JS解析遇到setTimeout函数时,就会将其视作异步任务,并通过Time模块将其接管,只要当同步任务执行完毕后,才会开始读取异步任务队列

任务队列和Event Loop

Event Loop就是当同步任务队列读取后,开始读取异步任务队列,当全部执行完毕后,重新开始读取同步任务队列。

异步任务

页面性能

  1. 资源压缩合并,减少HTTP请求
  2. 非核心代码异步加载=>异步加载的方式=>异步加载的区别
    1. 异步加载的方式
      1. 动态脚本加载
      2. defer(常用)
      3. async
    2. 异步加载的区别
      1. defer是在HTML解析完之后才会执行,如果是多个,按照加载的顺序依次执行
      2. async是在加载完之后立即执行,也就是和加载和渲染文档的过程并行执行,如果是多个,执行顺序和加载顺序无关
  3. 利用浏览器缓存=>缓存的分类=>缓存的原理
    1. 缓存的分类(以下为HTTP请求头内容)
      1. 强缓存(第一条是服务器返回的绝对时间,第二条是相对时间,当服务器时间与本地时间不一致时,以后者为准,当在3600s之内直接读取本地资源,不再与服务器通信)
        1. Expires Expires:Thu,21 Jan 2017 23:39:02 GMT
        2. Cache-Control Cache-Control:max-age=3600
      2. 协商缓存(第一条是上次响应请求的时间,Etag类似资源的HASH值,当需要请求服务器时,服务器会返回资源的Hash值,用以和本地的Etag对比,查看资源是否发生更新)
        1. Last-Modified If-Modified-Since Last-Modified:Web,26 Jan 2017 00:35:11 GMT Etag If-None-Match
  4. 使用CDN
  5. 预解析DNS,页面中A标签默认打开DNS预解析,如果页面协议为https那么浏览器会默认关闭这个功能,第一句代码就是为了强制打开A标签的DNS预解析 <meta http-equiv="x-dns-prefetch-control" content="on"> <link rel="dns-prefetch" href="//host_name_to_prefetchcom"

    错误监控