前端面试前的准备

2023-05-27 0 458

CSS 四列产业布局

CSS 盒数学模型

国际标准商业模式/IE数学模型的差别

国际标准数学模型:Width = ContentIE数学模型:Width = Content + Padding + Border

CSS怎样增设三种数学模型

box-sizing 特性 ==> content-box(国际标准数学模型,预设),border-box(IE 数学模型)
1) domElem.style.width/heightp和left

示例:依照盒数学模型说明边距重合

当三个横向外边距碰面时,它将逐步形成三个外边距。分拆后的外边距的度等同于三个出现分拆的外边距的度中的非常大者三个原素包涵在另三个原素中时(假定没吉洛姆距或前面板把外边距分分隔),它的上和/或下外边距也会出现分拆多于一般文件格式流中块框的横向外边距才会出现外边距分拆。Lembron框、自由浮动框或当然功能定位间的外边距不能分拆。

BFC(边距重合软件系统)

基本原理:块级序列化语句

渲染准则:

BFC原素的横向路径的边距会出现重合BFC地区不能与自由浮动原素的Box重合(可用作去除自由浮动)BFC是三个分立的罐子,外边的原素不能负面影响里头的原素,里头的原素也不能负面影响外边的原素排序BFC度时,自由浮动原素也会参予排序

建立 BFC:

float值不为noneposition值不为static/relativeoverflow值不为visible(等同于auto/hidden)display值为table-cell

示例:BFC横向路径重合问题(建立包裹div,增设overflow特性为hidden)

1

2

3

{

margin: 0;

padding: 0;

}

#margin {

background: pink;

overflow: hidden;

}

#margin > p {

background: red;

margin: 5px auto 25px;

}
示例:两栏自由浮动产业布局,度较低一侧会被侵染

{

margin: 0;

padding: 0;

}

#layout {

background: red;

}

#layout .left {

background: pink;

width: 100px;

height: 100px;

float: left;

}

#layout .right {

background: #ccc;

height: 110px;

overflow: auto;

}
示例:去除自由浮动(BFC即使子原素是自由浮动原素,度也会参予排序)
我是自由浮动原素

{

margin: 0;

padding: 0;

}

#float {

background: red;

// overflow: auto;

float: left;

}

#float .float {

float: left;

font-size: 30px;

}

原型链

建立对象的几种方法

字面量
var o1 = {name: o1};var o11 = new Object({name: o11});
构造函数
var M = function() { this.name = o2;}var o2 = new M();
Object.create
var P = {name: o3};var o3 = Object.create(P);

原型链概念

原型链是JS实现类与继承的基础,从示例对象向上找,直Object.prototype(原型链顶端)函数都具有prototype特性,构造函数的prototype特性指向原型对象,该原型对象的constructor特性指回构造函数
Func.prototpye.constructor === Func; // true
示例对象的__proto__特性指向构造函数的原型对象
obj.__proto__ === Func.prototype; // true
函数也具有__proto__特性(函数也是对象),指向Function的原型对象,说明该函数的构造函数Function
Func.__proto__ === Function.prototype; // true

instanceof 的原理

判断示例对象的__proto__和构造函数的prototype是否是同一引用A instanceof B:查看对象B的prototype特性指向的原型对象是否在对象A的原型链上,若在则返回true,若不在则返回false

new 运算符

三个新对象被建立,它继承自Func.prototype(构造函数的原型对象)构造函数Func被执行,相应的参数被传入,语句(this)会被指定为这个新示例若构造函数Func返回三个“对象”,那么这个对象会取代整个new出来的结果;若构造函数Func没返回“对象”,那么new出来的结果为步骤1建立的对象。

// 实现方法 _new,模拟 new 的作用

function _new(f) {

// 返回三个function

return function() {

var obj = {“proto”: f.prototype};

f.apply(obj, arguments);

return obj;

}

}

// 测试

function Person(name, age) {

this.name = name;

this.age = age;

}

var pp = _new(Person)(“Jialin”, 25);

pp instanceof Person; // true;

// 使用 Object.create 模拟 new 方法

var _new2 = function(func) {

var obj = Object.create(func.prototype);

var k = func.call(obj);

if(typeof k === object) {

return k;

} else {

return obj;

}

}

面向对象

借助构造函数实现继承(部分继承)

缺点:该方法无法继承父类的原型方法
function Parent() { this.name = parent; this.arr = [1];}function Child() { Parent.call(this); this.type = child;}

借助原型链实现继承

缺点:原型链中的原型对象是共用的(同一对象)

function Parent() { this.name = parent; this.arr = [1, 2, 3];}function Child() { this.type = child;}Child.prototype = new Parent();var c1 = new Child();var c2 = new Child();console.log(c1.arr); // [1, 2, 3]c1.arr.push(4); console.log(c2.arr); // [1, 2, 3, 4]

c1.proto === c2.proto; // true

组合方式

缺点:父类构造函数执行了2次,子类的 protype 被修改(共用),继而子类的构造函数将指向父类构造函数(子类的原型方法也丢失)

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

var cc = new Child();

cc.constructor; // Parent(){…}
优化1:将父类构造函数的执行次数减少至1次

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

var cc = new Child();

cc.constructor; // Parent(){…}
优化2:使用 Object.create 建立 Child.prototype,之后再修改子类原型的 constructor
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;

原型式继承

该方法借助原型可以基于已有的对象建立新对象,从而不必因此建立自定义类型
function object(o) { function F(){}; F.prototype = o; return new F();}复制代码
Object.create() 规范了原型式继承

寄生式继承

建立三个仅仅用作封装继承过程的函数,该函数在内部以某种方式来增强对象,最后返回对象
function createAnother(originalObj) { var clone = object(originalObj); clone.sayHi = function() { // … } return clone;}

DOM事件

DOM事件类

DOM0
element.onclick = function() {}
DOM2
// W3Celement.addEventListener(click, function(){}, false);// IEelement.attachEvent(click, function(){}, false);
DOM3(增加了许多事件)
element.addEventListener(keyup, function(){}, false);

DOM事件捕获/冒泡过程

window ==> document ==> html(通过 document.docuemntElement 获得) ==> … ==> 目标原素反向为冒泡

Event 对象的常见应用

event.preventDefault(); 表示阻止预设事件event.stopPropagation(); 表示阻止冒泡行为event.stopImmediatePropagation(); 应用作:事件响应的优先级,场景:三个按钮绑定三个click事件A和B,要求让点击A时,不执行Bevent.currentTarget;表示:当前绑定事件的对象,恒等同于 this,特殊情况:在父子嵌套关系中,父原素绑定了事件,单击子原素,此时,currentTarget指向的是父原素(因为它是绑定事件的对象);此时,target指向了子原素(因为它是触发事件的具体对象)event.target; 表示:触发事件的某个具体对象
// IEevent.sourceElement

自定义事件(无需使用回调)

使用 Event 类,但是只能指定事件名称,无法添加数据
var eve = new Event(custom);ev.addEventListener(custom, function(){ console.log(custom); });// 触发ev.dispatchEvent(eve);复制代码
使用CustomEvent不但可以指定事件名称,还可以指定三个object类型的参数

类型转换

7 种数据类型

Boolean, Null, Undefined, Number, String, SymbolObject

显示类型转换

Number函数
// 原始类型数值 ==> 原始值字符串 ==> 数值(空字符为0) or NaN布尔值 ==> true为1,false为0undefined ==> NaNnull ==> 0

对象,先调用该对象自身的 valueOf 方法,

var obj = {a:1};

console.log(Number(obj));

其中,

obj.valueOf()返回{a: 1}, {a: 1}的toString()返回[object Object]
String 函数
// 原始类型数值 ==> 对应字符串字符串 ==> 原始值布尔值 ==> true变为true,false变为falseundefined ==> undefinednull ==> null

复合类型,先调用该对象自身的 toString 方法,

若返回原始类型的值,则执行String方法转换;若返回符合类型的值,调用自身的valueOf方法,若返回原始类型的值,使用String方法转换若仍返回复合类型的值,则报错失败

复制代码Boolean 函数
// 原始类型undefined, null, -0, +0, NaN, 空字符串 均转为 false

隐式类型转换

四则运算判断语句Native调用console.log自动转换为字符串alert自动转换为字符串

常见题目

[] + [] ==> [] + {} ==>

{} + [] ==> 0
第三个大括号被作为代码块若被console.log()包括的话结果为 [object Object]

{} + {} ==> “[object Object][object Object]”

true + true ==>

1 + {a: 1} ==>
typeof返回值
undefined, boolean, number, string, symbolfunction, object

设计商业模式

单例商业模式观察者商业模式适配器商业模式工厂商业模式

通信类

同源政策及其限制

:协议 + 域名 + 端口Cookie、LocalStorage
补充:cookie,localStorage和sessionStorage差别复制代码

前后端怎样通信

Ajax(同源下通信方式)WebSocket(不受同源策略限制)CORS(支持跨域,支持同源)Fetch(兼容性不好)

怎样建立 Ajax

XHR对象的工作流程兼容性处理(IE, FireFox)事件触发条件事件的触发顺序

var xhr = XMLHttpRequest ? new XMLHttpRequest() : new window.ActiveXObject(Microsoft.XMLHTTP);

var data = opt.data;

var url = opt.url;

var type = opt.type.toUpperCase();

var dataArr = [];

for(var k in data) {

dataArr.push(k + = + data[k]);

}

if(type === GET) {

url = url + ? + dataArr.join(&);

xhr.open(type, url.replace(/?$/g, ), true);

xhr.send();

}

if(type === POST) {

// 第三个参数:预设为true,表示异步发送

xhr.open(type, url, true);

xhr.setRequestHeader(Content-type, application/x-www-form-urlencoded);

xhr.send(dataArr.join(&));

}

xhr.onload = function(){

if(xhr.status === 200 || xhr.status === 304) {

var res;

if(opt.success && opt.success instanceof Function) {

res = xhr.responseText;

if(typeof res === string) {

res = JSON.parse(res);

opt.success.call(xhr, res)

}

}

} else {

if(opt.error && opt.error instanceof Function) {

opt.error.call(xhr, res);

}

}

}

// Promise封装

var getJSON = function(url) {

var promise = new Promise((resolve, reject) => {

var client = new XMLHttpRequest();

client.open(GET, url);

client.onreadystatechange = handler;

client.responseType = json;

client.setRequestHeader(Accept, application/json);

client.send();

function handler() {

if(this.readyState !== 4) {

return;

}

if(this.status === 200) {

resolve(this.response);

} else {

reject(new Error(this.statusText));

}

};

});

return promise;

}

跨域通信的几种方式

JSONP利用 Script 标签的异步加载来实现

util.jsonp = function(url, onsuccess, onerror, charset) {

var callbackName = util.getName(name);

window[callbackName] = function() {

if(onsuccess && util.isFunction(onsuccess)) {

onsuccess(arguments[0]);

}

}

var script = util.createScript(url + &callback= + callbackName, charset);

script.onload = script.onreadystatechange = function() {

if(!script.readyState || /loaded|complete/.test(script.readyState)) {

script.onload = script.onreadystatechange = null;

if(script.parentNode) {

script.parentNode.removeChild(script);

}

window[callbackName] = null;

}

};

script.onerror = function() {

if(onerror && util.isFunction(onerror)) {

onerror();

}

}

}

//动态建立 script 标签,并请求

function addScriptTag(src){

var script = document.createElement(script);

script.setAttribute(type, text/javascript);

script.src = src;

document.body.appendChild(script);

};

// 在 onload 后,跨域请求

window.onload = function(){

addScriptTag(http://127.0.0.1:8080/jsonp?callback=test);

};

//回调函数,必须为全局,不然会报错

function test(data){

alert(data.name);

};

server.on(request,function(req, res){

var urlPath = url.parse(req.url).pathname;

var qs = querystring.parse(req.url.split(?)[1]);

if(urlPath === /jsonp && qs.callback){

res.writeHead(200,{Content-Type:application/json;charset=utf-8});

var data = {

“name”: “Monkey”

};

data = JSON.stringify(data);

var callback = qs.callback+(+data+);;

res.end(callback);

} else {

res.writeHead(200, {Content-Type:text/html;charset=utf-8});

res.end(Hell World\n);

}

});
Hashhash 改变页面不刷新,search 改变页面刷新

// 当前页面A通过iframe嵌入了跨域页面B

// A中:

var B = document.getElementsByTagName(iframe);

B.src = B.src + # + data;

// B中

window.onhashchange = function() {

var data = window.location.hash;

}
postMessage

// 窗口A(http://A.com)向窗口B(http://B.com

)发送消息

Bwindow.postMessage(data, http://B.com

);

// 在B窗口中

window.addEventListener(message, function(evet) {

console.log(event.origin); //http://A.com

console.log(event.source); // Bwindow

console.log(event.data); // data

}, false);
WebSocket

var ws = new WebSocket(wss://echo.websocket.org

);

ws.onopen = function(evt) {

console.log(Connection open…);

ws.send(Hello WebSockets);

}

ws.onmessage = function(evt) {

console.log(Received Message: , evt.data);

ws.close();

}

ws.onclose = function(evt) {

console.log(Connection closed.);

}

CORS浏览器会拦截ajax请求,如果被认为是跨域,则会加origin字段服务器端会在响应中加入Access-Control-Allow-Origin字段CORS请求预设不发送Cookie和HTTP认证信息,如需要发送Cookie,可使用// 客户端var xhr = new XMLHttpRequest();xhr.withCredentials = true;

// 服务器端Access-Control-Allow-Credentials: true

补充:fetch API

// url必须,options可选fetch(/some/url, { method: get,}).then(function(response) {

}).catch(function(err){

});

安全类

XSS 跨站脚本攻击
– 它允许恶意用户将代码注入到网页上,其他用户在观看网页时就会受到负面影响。- 这类攻击通常包涵了HTML以及用户端脚本语言

举例:通过客户端脚本(JS)在三个论坛发帖中发布一段恶意的JS代码就是脚本注入,如果这个代码内容有请求外部服务器,那么就叫做XSS!

防护:

如果您在cookie中增设了HttpOnly特性,那么通过js脚本将无法读取到cookie信息,这样能有效的防止XSS攻击对用户表单输入的数据进行过滤,对javascript代码进行转义

CSRF 跨站请求伪造

– 冒充用户发起请求(在用户不知情的情况下),完成一些违背用户意愿的请求1.登录受信任网站A,并在本地生成Cookie 。2.在不退出A的情况下,访问危险网站B。

防护:token防御的整体思路是:

后端随机产生三个token,把这个token保存在SESSION状态中;同时,后端把这个token交给后端页面下次后端需要发起请求(比如发帖)的时候把这个token加入到请求数据或者头信息中,一起传给后端;后端校验后端请求带过来的token和SESSION里的token是否一致;

HTTP协议类

HTTP协议的主要特点

简单快速输入uri进行访问资源灵活通过不用的http协议完成不同类型数据传输无连接一次连接,无需再次连接无状态两次连接,无法区分浏览器端的身份

HTTP报文的组成部分

请求报文请求行(HTTP方法 + 请求地址 + HTTP协议及版本)请求头(key/value值)空行请求体响应报文状态行(HTTP协议及版本 + 状态码 + 原因)响应头空行响应体

HTTP方法

GETPOSTPUTDELETEHEAD

POST和GET的差别

GET回退是无害的,POST会再次提交请求GET请求会被浏览器主动缓存,POST不能GET请求只能url编码,POST支持多种编码方式GET请求参数会被完整保留在浏览器历史记录里,POST中的参数不能被保留GET请求在URL中传送的参数有长度限制(2KB),POST没限制GET请求参数通过URL传递,POST放在Request Body中

HTTP状态码

200 OK: 客户端请求成功206 Partial Content: 客户端发送三个带有Range头的GET请求301 Moved Permanetly: 所请求的页面已经转移到新的URL302 Found: 所请求的页面已经临时转移到新的URL304 Not Modified: 原缓存可用400 Bad Request: 客户端请求有语法错误401 Unauthorized: 请求未经授权,必须和www-authenticate一起使用403 Forbidden: 请求页面被禁止访问404 Not Found: 请求资源不存在500 Internal Server Error: 服务器出现不可预期的错误,元缓存文件格式还可继续使用503 Server Unavailable: 请求未完成,服务器临时过载
什么是持久连接
无连接:每个请求/应答客户端和服务器都要新建三个连接(HTTP/1.0)Keep-Alive商业模式:避免重新建立连接(HTTP/1.1)
什么是管线化
管线化机制通过持久连接完成多于GET和HEAD请求可以进行管线化,POST有限制管线化不能负面影响响应到来的顺序

请求1 – 响应1 – 请求2 – 响应2 – 请求3 – 响应3

// 管线化,请求打包发送,依次进行响应(单独),并保持顺序

请求1 – 请求2 – 请求3 – 响应1 – 响应2 – 响应3

https 的介绍

1. HTTP的缺点- 使用明文(不加密)通信,内容可能被窃听- 不验证通信方的身份,可能遭遇伪装- 无法证明报文的完整性,可能已遭篡改

HTTPS 介绍

HTTPS = HTTP + 加密 + 认证 + 完整性保护

1)HTTPS使用SSL,先和SSL通信,再由SSL和TCP通信

补充:

对称密钥加密:加密和解密用同三个密钥的方式(共享)

弊端:加密时密钥也会被发给对方

非对称密钥加密:

发送方使用接收方的公开密钥进行加密处理,接收方使用自己的私有密钥解密弊端:处理速度过慢

2)HTTPS采用混合加密机制

交换密钥时,使用非对称加密方式;之后的建立通信交换报文阶段,使用对称加密方式(共享)

3)证明公开密钥的正确性 –> 使用由数字证书认证机构颁发的公开密钥证书

4)HTTPS还可以使用客户端证书

HTTP 2.0 与 HTTP1.1 的差别

– HTTP/2采用二进制格式而非文本格式- HTTP/2是完全多路复用的,同时发起无数个请求,并且响应可以同时返回- 使用报头压缩,HTTP/2降低了开销- HTTP/2让服务器可以将响应主动“推送”到客户端缓存中复制代码
因为“所有的HTTP2.0的请求都在三个TCP链接上”,“资源分拆减少请求”,比如CSS Sprites,多个JS文件、CSS文件分拆等手段没效果

3 次挥手 && 4 此握手

TCP建立连接TCP关闭连接TCP连接是全双工的,因此,每个路径都必须要单独进行关闭当一方完成数据发送任务后,发送三个FIN来终止这一路径的连接,收到三个FIN只是意味着这一路径上没数据流动了

图形机制

什么是 DOCTYPE 及作用

DTD 文件格式类型定义

告诉浏览器自身的文件格式类型

DOCTYPE

声明文件格式类型和DTD规范的,主要用作文件的合法性验证

常见的 DOCTYPE:

HTML 5

<!DOCTYPE html>

HTML 4.01 Strict 该DTD包涵所有HTML元素和特性,但不包括展示型的和弃用的原素(如:font)

HTML 4.01 Transitional 该DTD包涵所有HTML原素和特性,包括展示型和弃用的原素

浏览器的图形过程
HTML经过HTML Parser变为DOM TreeCSS经过CSS Parser变为CSSOM Tree(排序后的)DOM Tree和CSSOM Tree结合后成为Render Tree(不知道具体HTML原素的具体位置)Render Tree和Layout(精确排序位置、宽高、颜色等)结合后,进行绘制
什么是重排 Reflow

定义:DOM结构中的各个原素都有自己的盒子数学模型,这些都需要浏览器依照各种样式排序后将原素放到它该出现的位置,这个过程称为Reflow 重排

触发Reflow:

增加、删除、修改或移动DOM节点修改CSS样式修改网页的预设字体(极其不推荐!白屏闪现)
什么是重绘 Repaint

定义:将页面要呈现的内容都画在页面上,这个过程称之为Repaint

触发Repint:

DOM改动CSS改动 (只要页面显示内容不同就会Repaint)

怎样减少Repaint的频率?

通过DocumentFragment,将新建立的节点添加进去,向浏览器中一次性加入

DocumentFragment:

表示三个没父级文件的最小文件格式对象。它被当做三个轻量版的 Document 使用,用作存储已排好版的或尚未打理好格式XML片段。DocumentFragment 不是真实DOM树的一部分,它的变化不能引起 DOM 树的重新图形的操作(reflow),且不能导致性能等问题。可以使用 document.createDocumentFragment() 方法建立三个空的 DocumentFragment

JS运行机制 — 任务队列和 EventLoop

异步任务的类型:
setTimeout 和 setIntervalDOM 事件(addEventListener)Promise
EventLoop

整个最基本的 Event Loop 如图所示:

queue可以看做一种数据结构,用以存储需要执行的函数timer类型的API(setTimeout/setInterval)注册的函数,等到期后进入task队列(这里不详细展开timer的运行机制)其余API注册函数直接进入自身对应的task/microtask队列Event Loop执行一次,从task队列中拉出三个task执行Event Loop继续检查microtask队列是否为空,依次执行直至清空队列

task主要包涵:setTimeout、setInterval、setImmediate、I/O、UI交互事件

microtask主要包涵:Promise、process.nextTick、MutaionObserver

console.log(1)

setTimeout(() => {

console.log(2)

}, 0)

Promise.resolve().then(() => {

console.log(3)

}).then(() => {

console.log(4)

})

console.log(5)

// 1 5 3 4 2

分析如下:

同步运行的代码首先输出:1、5,接着,清空microtask队列:3、4

setTimeout(fn, 0) 的含义

指定某个任务在主线程最早可得的空闲时间执行,意思就是不用再等多少秒了,只要主线程执行栈内的同步任务全部执行完成,栈为空就马上执行

console.log(abc);setTimeout(() => { console.log(执行啦)},3000);setTimeout(() => { console.log(执行啦123)},0);

// abc

// 执行啦123

// 执行啦

process.nextTick(callback) 的含义

类似node.js版的”setTimeout”,在事件循环的下一次循环中调用 callback 回调函数。在同一EventLoop中,属于Microtask,优先级高于Promise

setTimeout 与 Promise 混合

console.log(1)

setTimeout(() => {

console.log(2)

new Promise(resolve => {

console.log(4)

resolve()

}).then(() => {

console.log(5)

})

})

new Promise(resolve => {

console.log(7)

resolve()

}).then(() => {

console.log(8)

})

setTimeout(() => {

console.log(9)

new Promise(resolve => {

console.log(11)

resolve()

}).then(() => {

console.log(12)

})

});

分析如下:

同步运行的代码首先输出:1、7

接着,清空microtask队列:8

第三个task执行:2、4

接着,清空microtask队列:5

第二个task执行:9、11

接着,清空microtask队列:12

setTimeout,Promise 与 process.nextTick 的混合

console.log(1);

setTimeout(function() {

console.log(2);

process.nextTick(function() {

console.log(3);

})

new Promise(function(resolve) {

console.log(4);

resolve();

}).then(function() {

console.log(5)

})

})

process.nextTick(function() {

console.log(6);

})

new Promise(function(resolve) {

console.log(7);

resolve();

}).then(function() {

console.log(8)

})

setTimeout(function() {

console.log(9);

process.nextTick(function() {

console.log(10);

})

new Promise(function(resolve) {

console.log(11);

resolve();

}).then(function() {

console.log(12)

})

})

复制代码

setTimeout 函数中,0ms 和 1ms 的效果一样(结果都是 1ms 后,传入 task 队列)

Chrome 和 Node 中的 timer 都使用这一准则

setTimeout(() => {

console.log(2)

}, 2)

setTimeout(() => {

console.log(1)

}, 1)

setTimeout(() => {

console.log(0)

}, 0)

// 1, 0, 2

页面性能

提升页面性能的方法有哪些?资源压缩分拆,减少HTTP请求非核心代码的异步加载 –> 异步加载的方式 –> 异步加载的差别利用浏览器缓存 –> 缓存的分类 –> 缓存的原理使用CDN预解析 DNS,<meta http-equi=”x-dns-prefetch-control” content=”on”>
a 标签自带了预解析的功能,那就不需要link开启预解析的功能,但是如果是https协议的话,a标签就不带有预解析的功能,因此使用 meta,<link rel=”dns-prefetch” href=”//host_name_to_prefetch.com”>一般方法,link 只是规定了包涵哪个域名的就对它进行预解析
异步加载的方式
动态脚本加载deferasync
异步加载的差别
defer 在 HTML 解析完之后才执行,如果是多个含 defer 特性的 script 标签,按照加载顺序执行async 是在加载完之后立即执行,如果是多个含 async 特性的 script 标签,执行顺序和加载顺序无关
浏览器缓存分类

强缓存(直接使用浏览器的缓存,不再请求服务器)

Expires: Thu, 21 Jan 2017 23:39:02 GMT(当然时间)Cache-Control: max-age=3600(相对时间,单位为妙)其他值:no-store(不缓存) no-cache(不缓存过期的,需revalidation)若服务器响应同时包涵Expires和Cache-Control,以Cache-Control为准

协商缓存(询问服务器,浏览器的缓存是否可以使用)

If-Modified-Since:Last-Modified …Etag/If-None-Match

使用了缓存后, 更改js文件内容但未更改js文件名。 重新发布后,怎么保证浏览器加载的是最新的js文件?

A:让浏览器上的强缓存事件变短

Yahoo 军规的其他优化方法

错误监控

后端错误的分类
即时运行错误(代码错误)资源加载错误
错误的捕获方式
即时运行错误try…catchwindow.onerror(属于DOM0)object.onerror(不能向上冒泡到window

)performance.getEntries()返回三个数组,包涵所有成功加载的资源(一种间接方法)Error事件捕获window.addEventListener(error, (e) => { console.log(捕获, e);}, true);

// true表示捕获,false表示冒泡

跨域的JS运行错误可以捕获吗?错误提示是什么?应该怎么处理?

跨域错误只提示 Script Error,解决方法:script 标签增加 crossorigin 特性,增设 js 资源响应头为 Access-Control-Allow-Origin: *

上报错误的基本原理
采用 Ajax 通信的方式上报利用 Image 对象上报(最佳)
(new Image()).src = http://…; 该请求可以直接被发出

笔试题

写出下面的输出

function Foo() {

getName = function(){console.log(1);}

return this; // 指window对象

}

Foo.getName = function(){console.log(2);}

Foo.prototype.getName = function(){console.log(3);}

var getName = function(){console.log(4);} // 变量定义提升

function getName(){console.log(5);} // 函数定义提升

Foo.getName(); // 2

getName(); // 4

Foo().getName();

// 1,返回window对象,调用window对象的getName方法(已经被从4修改为1)

getName(); // 1

new Foo.getName(); // 2

// 等价于

new function(){console.log(2);}();

new Foo().getName(); // 3

// 等价于

新建三个Foo函数的示例,调用该示例上(或原型上)的getName方法

new new Foo().getName();// 3

// 等价于

new foo.getName();

先执行new Foo(),得到Foo函数的示例;

由于点操作符的优先级高于new(不带参数),故先执行foo.getName(),返回3
优先级:点操作符 高于 new(带参数)和new(不带参数)new(带参数) 高于 new(不带参数)

算法类

数组扁平化

方法1:toString() 类型转换
var flag = function(arr) { let toString = Array.prototype.toString; Array.prototype = function() { return this.join(,); } // 隐式调用toString() let result = arr + ; Array.prototype.toString = toString; return result;}复制代码
方法2:valueOf() 格式转换

Array.prototype.valueOf = function() { return this.join(,);}var flat = function(arr) { return arr + ;};

flat(arr);

方法3:[Symbol.iterator] 遍历器

Array.prototype.[Symbol.iterator] = function() { let arr = [].concat(this); let getFirst = function(array) { let first = array.shift(); return first; } return { next: function() { let item = getFirst(arr); if(item) { return { value: item, done: false }; } else { return { done: true } } } }}

var flat = function(arr) {let r = [];for(let i of arr) {r.push(i);}return r.join(,);}
方法4:JSON序列化
function flat (arr) { let jsonArr = JSON.stringify(arr); // 将数组转化成json return jsonArr.replace(/(\[|\])/g, ); // 用正则去掉json中所有的中括号并返回};flat(arr);

实现如下功能

destructuringArray( [1,[2,4],3], “[a,[b],c]” );result: { a:1, b:2, c:3 }

// 递归实现(深拷贝)function func(arr, str) { str = Array.isArray(str) ? str : JSON.parse(str.replace(/([a-z]+)/g, “$1”)); let obj = {}; str.forEach((val, index) => { let res = arr[index]; if(Array.isArray(val)) { Object.assign(obj, func(res, val)) } else { obj[val] = res; } }}

}

三面/终面

三个团队最重要的是什么?
服从管理团队中层次分明,既有优秀的份子,也有做业务的中坚力量有对技术、对产品体验、对生活的追求综上,团队是健康的,氛围也应该是融洽的,协作也就是自然而然的
业务能力的描述
做过什么业务有什么业绩使用什么技术方案突破什么技术难点遇到什么问题最大的收获是什么
举报/反馈

相关文章

发表评论
暂无评论
官方客服团队

为您解决烦忧 - 24小时在线 专业服务