github版本戳,求star,follow
文章涉及的内容可能不全面,但量很多,需要慢慢看。来源于各个地方,我花了很长的时间整理,希望对大家有帮助。但是难免会有打字的错误或理解的错误,希望发现的可以邮箱告诉我[email protected],我会及时的进行修改,旨在能帮到大家,谢谢。
Html相关
1 html语义化
意义:根据内容的结构化(内容语义化),选择合适的标签(代码语义化)便于开发者阅读和写出更优雅的
代码的同时让浏览器的爬虫和机器很好地解析。 注意:
1.尽可能少的使用无语义的标签div和span;
2.在语义不明显时,既可以使用div或者p时,尽量用p, 因为p在默认情况下有上下间距,对兼容特殊终端有利;
3.不要使用纯样式标签,如:b、font、u等,改用css设置。
4.需要强调的文本,可以包含在strong或者em标签中(浏览器预设样式,能用CSS指定就不用他们),strong默认样式是加粗(不要用b),em是斜体(不用i);
5.使用表格时,标题要用caption,表头用thead,主体部分用tbody包围,尾部用tfoot包围。表头和一般单元格要区分开,表头用th,单元格用td;
6.表单域要用fieldset标签包起来,并用legend标签说明表单的用途;
7.每个input标签对应的说明文本都需要使用label标签,并且通过为input设置id属性,在lable标签中设置for=someld来让说明文本和相对应的input关联起来。
新标签:
2 meta viewport相关
H5标准声明,使用 HTML5 doctype,不区分大小写
标准的 lang 属性写法
声明文档使用的字符编码
优先使用 IE 最新版本和 Chrome
页面描述
页面关键词
网页作者
搜索引擎抓取
为移动设备添加 viewport
iOS 设备 begin
添加到主屏后的标题(iOS 6 新增)
是否启用 WebApp 全屏模式,删除苹果默认的工具栏和菜单栏
添加智能 App 广告条 Smart App Banner(iOS 6+ Safari)
设置苹果工具栏颜色
启用360浏览器的极速模式(webkit)
避免IE使用兼容模式
不让百度转码
针对手持设备优化,主要是针对一些老的不识别viewport的浏览器,比如黑莓
微软的老式浏览器
uc强制竖屏
QQ强制竖屏
UC强制全屏
QQ强制全屏
UC应用模式
QQ应用模式
windows phone 点击无高光
设置页面不缓存
复制代码
3 canvas 相关
使用前需要获得上下文环境,暂不支持3d
常用api:
1.fillRect(x,y,width,height)实心矩形
2.strokeRect(x,y,width,height)空心矩形
3.fillText("Hello world",200,200);实心文字
4.strokeText("Hello world",200,300)空心文字
各种东西!!!
复制代码
新标签兼容低版本
CSS相关
1.盒模型
1.ie盒模型算上border、padding及自身(不算margin),标准的只算上自身窗体的大小 css设置方法如下
/* 标准模型 */
box-sizing:content-box;
/*IE模型*/
box-sizing:border-box;
复制代码
2.margin、border、padding、content由外到里 3.几种获得宽高的方式
4.拓展 各种获得宽高的方式
5.边距重叠解决方案(BFC) BFC原理
上
这块margin-bottom:30px;
复制代码
css reset 和 normalize.css 有什么区别
居中方法
水平方向上
针对inline, 内联块inline-block, 内联表inline-table, inline-flex元素及img,span,button等元素
.text_div{
text-align:center;
}
复制代码
不定宽块状元素居中
.text_div{
margin:0 auto;//且需要设置父级宽度
}
复制代码
通过给父元素设置 float,然后给父元素设置 position:relative 和 left:50%,子元素设置 position:relative 和 left: -50% 来实现水平居中。
.wrap{
float:left;
position:relative;
left:50%;
clear:both;
}
.wrap-center{
left:-50%;
}
复制代码
垂直居中
单行内联(inline-)元素垂直居中
通过设置内联元素的高度(height)和行高(line-height)相等,从而使元素垂直居中。
.text_div{
height: 120px;
line-height: 120px;
}
复制代码
利用表布局
.father {
display: table;
}
.children {
display: table-cell;
vertical-align: middle;
text-align: center;
}
复制代码
flex布局
.center-flex {
display: flex;
flex-direction: column;//上下排列
justify-content: center;
}
复制代码
绝对布局方式
已知高度
.parent {
position: relative;
}
.child {
position: absolute;
top: 50%;
height: 100px;
margin-top: -50px;
}
未知高度
.parent {
position: relative;
}
.child {
position: absolute;
top: 50%;
transform: translateY(-50%);
}
复制代码
垂直水平居中根据上方结合
flex方式
.parent {
display: flex;
justify-content: center;
align-items: center;
}
grid方式
.parent {
height: 140px;
display: grid;
}
.child {
margin: auto;
}
复制代码
css优先级确定
bfc内容见盒模型
如何清除浮动
不清楚浮动会发生高度塌陷:浮动元素父元素高度自适应(父元素不写高度时,子元素写了浮动后,父元素会发生高度塌陷)
.float_div:after{
content:".";
clear:both;
display:block;
height:0;
overflow:hidden;
visibility:hidden;
}
.float_div{
zoom:1
}
复制代码
自适应布局
思路:
画三角形
#item {
width: 0;
height: 0;
border-left: 50px solid transparent;
border-right: 50px solid transparent;
border-top: 50px solid transparent;
border-bottom: 50px solid blue;
background: white;
}
复制代码
link @import导入css
animation
长宽比方案
display相关
JavaScript相关
1 ["1", "2", "3"].map(parseInt)
首先, map接受两个参数, 一个回调函数 callback, 一个回调函数的this值
其中回调函数接受三个参数 currentValue, index, arrary;
而题目中, map只传入了回调函数--parseInt.
其次, parseInt 只接受两个两个参数 string, radix(基数).
本题理解来说也就是key与 index
所以本题即问
parseInt('1', 0);
parseInt('2', 1);
parseInt('3', 2);
parseInt(string, radix)
string 必需。要被解析的字符串。
radix 可选。表示要解析的数字的基数。该值介于 2 ~ 36 之间。
如果省略该参数或其值为 0,则数字将以 10 为基础来解析。如果它以 “0x” 或 “0X” 开头,将以 16 为基数。
复制代码
2 [[3,2,1].reduce(Math.pow), [].reduce(Math.pow)]
arr.reduce(callback[, initialValue])
reduce接受两个参数, 一个回调, 一个初始值.
回调函数接受四个参数 previousValue, currentValue, currentIndex, array
需要注意的是 If the array is empty and no initialValue was provided, TypeError would be thrown.
所以第二个表达式会报异常. 第一个表达式等价于 Math.pow(3, 2) => 9; Math.pow(9, 1) =>9
复制代码
3
var ary = [0,1,2];
ary[10] = 10;
ary.filter(function(x) { return x === undefined;});
我们看到在迭代这个数组的时候, 首先检查了这个索引值是不是数组的一个属性, 那么我们测试一下.
0 in ary; => true
3 in ary; => false
10 in ary; => true
也就是说 从 3 - 9 都是没有初始化的bug !, 这些索引并不存在与数组中. 在 array 的函数调用的时候是会跳过这些坑的.
复制代码
4 [typeof null, null instanceof Object]
typeof 返回一个表示类型的字符串.
instanceof 运算符用来检测 constructor.prototype 是否存在于参数 object 的原型链上.
type result
Undefined "undefined"
Null "object"
Boolean "boolean"
Number "number"
String "string"
Symbol "symbol"
Host object Implementation-dependent
Function "function"
Object "object"
复制代码
5 js数据类型
1.number;
2.string;
3.boolean;
4.undefined;
5.null;
6.symbol(ES6新增,文章后面有对着新类型的解释)Symbol 生成一个全局唯一的值。
7.Object.(包括Object,Array,Function)
6 promise 用法
定义
var promise = new Promise(function(resolve, reject) {
// ... some code
if (/* 异步操作成功 */){
resolve(value);
} else {
reject(error);
}
});
使用
promise.then(function(value) {
// success
}, function(error) {
// failure
});
//等价于:
promise.then(function(){
//success
}).catch(function(){
//failure
})
复制代码
7 es6 promise ajax
定义
const myHttpClient = url => {
return new Promise((resolve, reject) => {
let 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));
}
}
});
};
使用
myHttpClient('https://www.baidu.com').then(res => {
console.log(res);
}).catch(error => {
console.log(error);
});
复制代码
8闭包
function foo(x) {
var tmp = 3;
return function (y) {
alert(x + y + (++tmp));
}
}
var bar = foo(2); // bar 现在是一个闭包
bar(10);
结果是16
es6通常用let const块级作用域代替,
闭包缺点,ie中会引起内存泄漏,严格来说是ie的缺点不是闭包的问题
复制代码
9 什么是立即执行函数?使用立即执行函数的目的是什么?
常见两种方式
1.(function(){...})()
(function(x){
console.log(x);
})(12345)
2.(function(){...}())
(function(x){
console.log(x);
}(12345))
作用 不破坏污染全局的命名空间,若需要使用,将其用变量传入如
(function(window){...}(window))
复制代码
10 async/await 语法
作用:异步代码的新方式
promise示例
const makeRequest = () => {
return getJSON()
.then(data => {
if (data.needsAnotherRequest) {
return makeAnotherRequest(data)
.then(moreData => {
console.log(moreData)
return moreData
})
} else {
console.log(data)
return data
}
})
}
async/await示例
const makeRequest = async () => {
const data = await getJSON()
if (data.needsAnotherRequest) {
const moreData = await makeAnotherRequest(data);
console.log(moreData)
return moreData
} else {
console.log(data)
return data
}
}
函数前面多了一个aync关键字。await关键字只能用在aync定义的函数内。async函数会隐式地返回一个promise,该promise的reosolve值就是函数return的值。(示例中reosolve值就是字符串"done")
复制代码
11 深浅拷贝
let a = {
aa: 1,
bb: 2,
cc: 3,
dd: {
ee: 5,
},
ff: {
gg: 6,
}
};
let d = JSON.parse(JSON.stringify(a));//深复制包含子对象
let c = {...a};//拷贝一层但不包含子对象
let b = a;//浅拷贝
b.bb = 22;
c.cc = 33;
c.dd.ee = 55;
d.ff.gg = 66;
console.log(a);
console.log(b);
console.log(c);
console.log(d);
复制代码
12数组去重
思路1:定义一个新数组,并存放原数组的第一个元素,然后将元素组一一和新数组的元素对比,若不同则存放在新数组中
思路2:先将原数组排序,在与相邻的进行比较,如果不同则存入新数组。
思路3:利用对象属性存在的特性,如果没有该属性则存入新数组。
思路4(最常用):使用es6 set
let arr= [1, 2, 3, 3, 5, 7, 2, 6, 8];
console.log([...new Set(arr)]);
复制代码
13正则实现trim()功能
function myTrim(str) {
let reg = /^\s+|\s+$/g;
return str.replace(reg, "");
}
console.log(myTrim(' asdf '));
复制代码
14 JS原型
1.每个对象都有 __proto__ 属性,但只有函数对象才有 prototype 属性
2.个人粗略理解与python的类方法静态方法实例方法差不多
复制代码
15 es6 class
面向对象,java中类
复制代码
16 JS 如何实现继承
1.使用原型继承(既继承了父类的模板,又继承了父类的原型对象。优点是继承了父类的模板,又继承了父类的原型对象,缺点就是父类实例传参,不是子类实例化传参,不符合常规语言的写法)
2.使用call的方式(继承了父类的模板,不继承了父类的原型对象。优点是方便了子类实例传参,缺点就是不继承了父类的原型对象)
复制代码
17 手写jquery插件
(function ($) {
$.fn.myPlugins = function (options) {
//参数赋值
options = $.extend(defaults, options);//对象合并
this.each(function () {
//执行代码逻辑
});
};
})(jQuery);
$(selector).myPlugins({参数});
复制代码
18 数组合并去重排序
let arr1 = [1, 25, 2, 26, 1234, 6, 213];
let arr2 = [2, 6, 2134, 6, 31, 623];
let c = [...new Set([...arr1, ...arr2])].sort((a, b) => {
return a - b;
});
复制代码
19 call apply
作用:在函数调用时改变函数的执行上下文也就是this的值 区别:call采用不定长的参数列表,而apply使用一个参数数组。 性能优化图
20 for 中setTimeOut
要为循环题创建不同的循环副本
21 sort函数
V8 引擎 sort 函数只给出了两种排序 InsertionSort 和 QuickSort,数量小于10的数组使用 插入,比10大的数组则使用 快排。
22 navigator
23 jquery绑定方式
24 事件流向
25原生操作class
//判断有无
function hasClass(ele, cls) {
return ele.className.match(new RegExp("(\\s|^)" + cls + "(\\s|$)"));
}
//添加
function addClass(ele, cls) {
if (!this.hasClass(ele, cls)) ele.className += " " + cls;
}
//删除
function removeClass(ele, cls) {
if (hasClass(ele, cls)) {
let reg = new RegExp("(\\s|^)" + cls + "(\\s|$)");
ele.className = ele.className.replace(reg, " ");
}
}
html5中加入classList
一系列操作
兼容至IE10
复制代码
DOM相关
dom事件模型
DOM之事件模型分脚本模型、内联模型(同类一个,后者覆盖)、动态绑定(同类多个) demo
复制代码
冒泡解释:当点击一个元素触发事件时. 事件会先从元素的最外层父元素一层一层进入到触发的元素, 然后在从触发元素一层一层返回到最外层父元素, 从最外层一层一层进入的阶段叫事件捕获阶段, 从最里层一层一层往外的阶段叫事件冒泡,
移动端触摸事件
①touchstart:当手指触碰到屏幕的时候触发 ②touchmove:当手指在屏幕上滑动的时候触发 ③touchend:当手指离开屏幕的时候时候触发 ④touchcancel事件:当系统停止跟踪触摸的时候触发(这个事件很少会用,一般不做深入研究)。 电话接入或者弹出信息等其他事件切入 event:
每个touch对象包含的属性
事件委托
参考定义:事件委托就是利用事件冒泡,只指定一个事件处理程序,就可以管理某一类型的所有事件 好处:给重复的节点添加相同操作,减少dom交互,提高性能 实现思路:给父组件添加事件,通过事件冒泡,排查元素是否为指定元素,并进行系列操作
HTTP相关
常见状态码
2开头 (请求成功)表示成功处理了请求的状态代码。
200 (成功) 服务器已成功处理了请求。 通常,这表示服务器提供了请求的网页。 201 (已创建) 请求成功并且服务器创建了新的资源。 202 (已接受) 服务器已接受请求,但尚未处理。 203 (非授权信息) 服务器已成功处理了请求,但返回的信息可能来自另一来源。 204 (无内容) 服务器成功处理了请求,但没有返回任何内容。 205 (重置内容) 服务器成功处理了请求,但没有返回任何内容。 206 (部分内容) 服务器成功处理了部分 GET 请求。
3开头 (请求被重定向)表示要完成请求,需要进一步操作。 通常,这些状态代码用来重定向。
300 (多种选择) 针对请求,服务器可执行多种操作。 服务器可根据请求者 (user agent) 选择一项操作,或提供操作列表供请求者选择。 301 (永久移动) 请求的网页已永久移动到新位置。 服务器返回此响应(对 GET 或 HEAD 请求的响应)时,会自动将请求者转到新位置。 302 (临时移动) 服务器目前从不同位置的网页响应请求,但请求者应继续使用原有位置来进行以后的请求。 303 (查看其他位置) 请求者应当对不同的位置使用单独的 GET 请求来检索响应时,服务器返回此代码。 304 (未修改) 自从上次请求后,请求的网页未修改过。 服务器返回此响应时,不会返回网页内容。 305 (使用代理) 请求者只能使用代理访问请求的网页。 如果服务器返回此响应,还表示请求者应使用代理。 307 (临时重定向) 服务器目前从不同位置的网页响应请求,但请求者应继续使用原有位置来进行以后的请求。
4开头 (请求错误)这些状态代码表示请求可能出错,妨碍了服务器的处理。
400 (错误请求) 服务器不理解请求的语法。 401 (未授权) 请求要求身份验证。 对于需要登录的网页,服务器可能返回此响应。 403 (禁止) 服务器拒绝请求。 404 (未找到) 服务器找不到请求的网页。 405 (方法禁用) 禁用请求中指定的方法。 406 (不接受) 无法使用请求的内容特性响应请求的网页。 407 (需要代理授权) 此状态代码与 401(未授权)类似,但指定请求者应当授权使用代理。 408 (请求超时) 服务器等候请求时发生超时。 409 (冲突) 服务器在完成请求时发生冲突。 服务器必须在响应中包含有关冲突的信息。 410 (已删除) 如果请求的资源已永久删除,服务器就会返回此响应。 411 (需要有效长度) 服务器不接受不含有效内容长度标头字段的请求。 412 (未满足前提条件) 服务器未满足请求者在请求中设置的其中一个前提条件。 413 (请求实体过大) 服务器无法处理请求,因为请求实体过大,超出服务器的处理能力。 414 (请求的 URI 过长) 请求的 URI(通常为网址)过长,服务器无法处理。 415 (不支持的媒体类型) 请求的格式不受请求页面的支持。 416 (请求范围不符合要求) 如果页面无法提供请求的范围,则服务器会返回此状态代码。 417 (未满足期望值) 服务器未满足"期望"请求标头字段的要求。
5开头(服务器错误)这些状态代码表示服务器在尝试处理请求时发生内部错误。 这些错误可能是服务器本身的错误,而不是请求出错。
500 (服务器内部错误) 服务器遇到错误,无法完成请求。 501 (尚未实施) 服务器不具备完成请求的功能。 例如,服务器无法识别请求方法时可能会返回此代码。 502 (错误网关) 服务器作为网关或代理,从上游服务器收到无效响应。 503 (服务不可用) 服务器目前无法使用(由于超载或停机维护)。 通常,这只是暂时状态。 504 (网关超时) 服务器作为网关或代理,但是没有及时从上游服务器收到请求。 505 (HTTP 版本不受支持) 服务器不支持请求中所用的 HTTP 协议版本。
缓存
2. cdn
Cache-Control 和 Etag 的区别
如下图
Cookie sessionStorage localStorage
共同点:都是保存在浏览器端,且同源的。 区别:cookie数据始终在同源的http请求中携带,即cookie在浏览器和服务器间来回传递。而sessionStorage和localStorage不会自动把数据发给服务器,仅在本地保存。cookie数据不能超过4k(适合保存小数据)。 sessionStorage和localStorage容量较大,数据有效期不同,sessionStorage:仅在当前浏览器窗口关闭前有效。localStorage:始终有效,窗口或浏览器关闭也一直保存,需手动清楚;cookie只在设置的cookie过期时间之前一直有效,即使窗口或浏览器关闭。作用域不同。 sessionStorage不在不同的浏览器窗口中共享;localStorage 在所有同源窗口中都是共享的;cookie也是在所有同源窗口中都是共享的。
应用场景:localStorage:常用于长期登录(+判断用户是否已登录),适合长期保存在本地的数据。sessionStorage :敏感账号一次性登录; cookies与服务器交互。
GET POST区别
请求行,请求头,请求体详解
1,2,3请求行,4请求体,5请求体
跨域、JSONP 、CORS、postMessage
跨域概念解释:当前发起请求的域与该请求指向的资源所在的域不一样。这里的域指的是这样的一个概念:我们认为若协议 + 域名 + 端口号均相同,那么就是同域。 如下表
jsonp实现
原生
jquery
$.ajax({
url: 'http://www.domain2.com:8080/login',
type: 'get',
dataType: 'jsonp', // 请求方式为jsonp
jsonpCallback: "onBack", // 自定义回调函数名
data: {}
});
vue
this.$http.jsonp('http://www.domain2.com:8080/login', {
params: {},
jsonp: 'onBack'
}).then((res) => {
console.log(res);
})
配合的后端node实现,其他服务器语言也可以
const querystring = require('querystring');
const http = require('http');
const server = http.createServer();
server.on('request', function(req, res) {
var params = qs.parse(req.url.split('?')[1]);
var fn = params.callback;
// jsonp返回设置
res.writeHead(200, { 'Content-Type': 'text/javascript' });
res.write(fn + '(' + JSON.stringify(params) + ')');
res.end();
});
server.listen('8080');
jsoup缺点只能实现get请求
复制代码
CORS:跨源资源共享 Cross-Origin Resource Sharing(CORS),通常服务器设置,若带cookie请求,则前后端都需要设置 后端常见设置 response.setHeader("Access-Control-Allow-Origin", "www.domain1.com"); // 若有端口需写全(协议+域名+端口),允许那些外源请求 response.setHeader("Access-Control-Allow-Credentials", "true"); //是否需要验证
前端示例
原生
var xhr = new XMLHttpRequest(); // IE8/9需用window.XDomainRequest兼容
// 前端设置是否带cookie
xhr.withCredentials = true;
xhr.open('post', 'http://www.domain2.com:8080/login', true);
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
xhr.send('user=admin');
xhr.onreadystatechange = function() {
if (xhr.readyState == 4 && xhr.status == 200) {
alert(xhr.responseText);
}
jquery
$.ajax({
...
xhrFields: {
withCredentials: true // 前端设置是否带cookie
},
crossDomain: true, // 会让请求头中包含跨域的额外信息,但不会含cookie
...
});
复制代码
postMessage(data,origin)方法接受两个参数
demo
a.html
b.html 与a.html不同源
复制代码
osi模型
七层结构:物理层、数据链路层、网络层、传输层、会话层、表示层、应用层 tcp ucp属于传输层;http属于应用层
http2.0 http1
Vue相关
生命周期顺序
组件通信
1.父传子用props,父用子用ref 子调父用$emit,无关系用Bus
Vuex
组件通信库,可以避免子组件无法改变props的弊端等 mutations 同步操作, 用于改变状态 官方不推荐异步 action 执行多个mutaions,官方推荐异步操作 mapState、mapGetters、mapActions使用示例
后两者类似
复制代码
VueRouter
定义
var routes = [
{
path:"/one",
component:导入的组件1
},
{
path:"/two",
component:导入的组件2
},
];
// 定义路由组件
var router = new VueRouter({
routes
});
// 定义路由
new Vue({
el:"#box",
router
});
访问设定的路由后 会将 替换成相应的模版
html访问方式 One (类似a标签)
js访问方式 this.$router.push('/one');
replace方式 替换当前页面
携带的参数 可以通过this.$route.query.xxxx来获取
复制代码
Vue双向绑定
原理:利用了 Object.defineProperty() 这个方法重新定义了对象获取属性值(get)和设置属性值(set)的操作来实现的。 缺点:双向数据流是自动管理状态的, 但是在实际应用中会有很多不得不手动处理状态变化的逻辑, 使得程序复杂度上升, 难以调试。
computed watch methods
用法: 区别:
算法相关
各种排序实现
相关数据
// 冒泡排序: 比较两个相邻的项,如果第一个大于第二个则交换他们的位置,元素项向上移动至正确的顺序,就好像气泡往上冒一样
冒泡demo:
function bubbleSort(arr) {
let len = arr.length;
for (let i = 0; i < len; i++) {
for (let j = 0; j < len - 1 - i; j++) {
if (arr[j] > arr[j+1]) { //相邻元素两两对比
[arr[j + 1], arr[j]] = [arr[j], arr[j + 1]];
}
}
}
return arr;
}
// 1) 首先,在数组中选择一个中间项作为主元
// 2) 创建两个指针,左边的指向数组第一个项,右边的指向最后一个项,移动左指针,直到找到一个比主元大的项,接着,移动右边的指针,直到找到一个比主元小的项,然后交换它们。重复这个过程,直到
// 左侧的指针超过了右侧的指针。这个使比主元小的都在左侧,比主元大的都在右侧。这一步叫划分操作
// 3) 接着,算法对划分后的小数组(较主元小的值组成的的小数组, 以及较主元大的值组成的小数组)重复之前的两个步骤,直到排序完成
快排demo:
function quickSort(arr, left, right) {
let len = arr.length;
let partitionIndex;
left = typeof left !== 'number' ? 0 : left;
right = typeof right !== 'number' ? len - 1 : right;
if (left < right) {
partitionIndex = partition(arr, left, right);
quickSort(arr, left, partitionIndex - 1);
quickSort(arr, partitionIndex + 1, right);
}
return arr;
}
function partition(arr, left, right) { //分区操作
let pivot = left; //设定基准值(pivot)
let index = pivot + 1;
for (let i = index; i <= right; i++) {
if (arr[i] < arr[pivot]) {
[arr[i], arr[index]] = [arr[index], arr[i]];
index++;
}
}
[arr[pivot], arr[index - 1]] = [arr[index - 1], arr[pivot]];
return index - 1;
}
// 选择排序:大概思路是找到最小的放在第一位,找到第二小的放在第二位,以此类推 算法复杂度O(n^2)
选择demo:
function selectionSort(arr) {
let len = arr.length;
let minIndex;
for (let i = 0; i < len - 1; i++) {
minIndex = i;
for (let j = i + 1; j < len; j++) {
if (arr[j] < arr[minIndex]) { //寻找最小的数
minIndex = j; //将最小数的索引保存
}
}
[arr[i], arr[minIndex]] = [arr[minIndex], arr[i]];
}
return arr;
}
// 插入排序:每次排一个数组项,假设数组的第一项已经排序,接着,把第二项与第一项进行对比,第二项是该插入到第一项之前还是之后,第三项是该插入到第一项之前还是第一项之后还是第三项
插入demo:
function insertionSort(arr) {
let len = arr.length;
let preIndex, current;
for (let i = 1; i < len; i++) {
preIndex = i - 1;
current = arr[i];
while (preIndex >= 0 && arr[preIndex] > current) {
arr[preIndex + 1] = arr[preIndex];
preIndex--;
}
arr[preIndex + 1] = current;
}
return arr;
}
// 归并排序:Mozilla Firefox 使用归并排序作为Array.prototype.sort的实现,而chrome使用快速排序的一个变体实现的,前面三种算法性能不好,但归并排序性能不错 算法复杂度O(nlog^n)
// 归并排序是一种分治算法。本质上就是把一个原始数组切分成较小的数组,直到每个小数组只有一个位置,接着把小数组归并成较大的数组,在归并过程中也会完成排序,直到最后只有一个排序完毕的大数组
归并demo:
function mergeSort(arr) { //采用自上而下的递归方法
let len = arr.length;
if(len < 2) {
return arr;
}
let middle = Math.floor(len / 2),
left = arr.slice(0, middle),
right = arr.slice(middle);
return merge(mergeSort(left), mergeSort(right));
}
function merge(left, right){
let result = [];
while (left.length && right.length) {
if (left[0] <= right[0]) {
result.push(left.shift());
} else {
result.push(right.shift());
}
}
result.push(...left);
result.push(...right);
return result;
}
//堆排序:堆排序把数组当中二叉树来排序而得名。
// 1)索引0是树的根节点;2)除根节点为,任意节点N的父节点是N/2;3)节点L的左子节点是2*L;4)节点R的右子节点为2*R + 1
// 本质上就是先构建二叉树,然后把根节点与最后一个进行交换,然后对剩下对元素进行二叉树构建,进行交换,直到剩下最后一个
堆demo:
var len; //因为声明的多个函数都需要数据长度,所以把len设置成为全局变量
function buildMaxHeap(arr) { //建立大顶堆
len = arr.length;
for (let i = Math.floor(len / 2); i >= 0; i--) {
heapify(arr, i);
}
}
function heapify(arr, i) { //堆调整
let left = 2 * i + 1;
let right = 2 * i + 2;
let largest = i;
if (left < len && arr[left] > arr[largest]) {
largest = left;
}
if (right < len && arr[right] > arr[largest]) {
largest = right;
}
if (largest !== i) {
[arr[i], arr[largest]] = [arr[largest], arr[i]];
heapify(arr, largest);
}
}
function heapSort(arr) {
buildMaxHeap(arr);
for (let i = arr.length - 1; i > 0; i--) {
[arr[0],arr[i]]=[arr[i],arr[0]];
len--;
heapify(arr, 0);
}
return arr;
}
复制代码
二分查找
思路 (1)首先,从有序数组的中间的元素开始搜索,如果该元素正好是目标元素(即要查找的元素),则搜索过程结束,否则进行下一步。 (2)如果目标元素大于或者小于中间元素,则在数组大于或小于中间元素的那一半区域查找,然后重复第一步的操作。 (3)如果某一步数组为空,则表示找不到目标元素。
// 非递归算法
function binary_search(arr, key) {
let low = 0;
let high = arr.length - 1;
while(low <= high){
let mid = parseInt((high + low) / 2);
if(key === arr[mid]){
return mid;
}else if(key > arr[mid]){
low = mid + 1;
}else if(key < arr[mid]){
high = mid -1;
}else{
return -1;
}
}
}
// 递归算法
function binary_search(arr,low, high, key) {
if (low > high){
return -1;
}
let mid = parseInt((high + low) / 2);
if(arr[mid] === key){
return mid;
}else if (arr[mid] > key){
high = mid - 1;
return binary_search(arr, low, high, key);
}else if (arr[mid] < key){
low = mid + 1;
return binary_search(arr, low, high, key);
}
};
复制代码
二叉树相关
创建
function Node(data,left,right){
this.data = data;//数值
this.left = left;//左节点
this.right = right;//右节点
};
插入二叉树
function insert(node,data){
//创建一个新的节点
let newNode = new Node(data,null,null);
//判断是否存在根节点,没有将新节点存入
if(node == null){
node = newNode;
}else{
//获取根节点
let current = node;
let parent;
while(true){
//将当前节点保存为父节点
parent = current;
//将小的数据放在左节点
if(data < current.data){
//获取当前节点的左节点
//判断当前节点下的左节点是否有数据
current = current.left;
if(current == null){
//如果没有数据将新节点存入当前节点下的左节点
parent.left = newNode;
break;
}
}else{
current = current.right;
if(current == null){
parent.right = newNode;
break;
}
}
}
}
}
翻转二叉树
function invertTree(node) {
if (node !== null) {
node.left, node.right = node.left, node.right;
invertTree(node.left);
invertTree(node.right);
}
return node;
}
复制代码
查找链表中倒数第k个结点
2个思路
1:先遍历出长度,然后查找长度-k+1的值
2:2个指针,一个指针先走k-1,然后两个一起走到底部,后者就是结果
复制代码
网络安全相关
XSS CSRF
XSS(跨站脚本攻击),恶意的注入html代码,其他用户访问时,会被执行 特点:能注入恶意的HTML/JavaScript代码到用户浏览的网页上,从而达到Cookie资料窃取、会话劫持、钓鱼欺骗等攻击 防御手段:
webpack相关
#####打包体积 优化思路
Loader
编写一个loader
loader就是一个node模块,它输出了一个函数。当某种资源需要用这个loader转换时,这个函数会被调用。并且,这个函数可以通过提供给它的this上下文访问Loader API。
reverse-txt-loader
定义
module.exports = function(src) {
//src是原文件内容(abcde),下面对内容进行处理,这里是反转
var result = src.split('').reverse().join('');
//返回JavaScript源码,必须是String或者Buffer
return `module.exports = '${result}'`;
}
使用
{
test: /\.txt$/,
use: [
{
'./path/reverse-txt-loader'
}
]
},
复制代码
plugins
使用范围更广,通常只需要require()然后添加到plugins数组中,且需要new一个
其他
URL到界面显示发生了什么
POST / HTTP1.1
Host:www.wrox.com
User-Agent:Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 2.0.50727; .NET CLR 3.0.04506.648; .NET CLR 3.5.21022)
Content-Type:application/x-www-form-urlencoded
Content-Length:40
Connection: Keep-Alive
name=Professional%20Ajax&publisher=Wiley
第一部分:请求行,第一行说明是post请求,以及http1.1版本。
第二部分:请求头部,第二行至第六行。
第三部分:空行,第七行的空行。
第四部分:请求数据,第八行。
4. 服务器处理请求并返回HTTP报文
后端处理返回http报文如下
复制代码
HTTP/1.1 200 OK
Date: Fri, 22 May 2009 06:07:21 GMT
Content-Type: text/html; charset=UTF-8
第一行为状态行,(HTTP/1.1)表明HTTP版本为1.1版本,状态码为200,状态消息为(ok)
第二行和第三行为消息报头,
Date:生成响应的日期和时间;Content-Type:指定了MIME类型的HTML(text/html),编码类型是UTF-8
第三部分:空行,消息报头后面的空行是必须的
第四部分:响应正文,服务器返回给客户端的文本信息。
空行后面的html部分为响应正文。
复制代码
组件封装
目的:为了重用,提高开发效率和代码质量 注意:低耦合,单一职责,可复用性,可维护性 常用操作:
JS异步加载
css与js动画差异
负载均衡
多台服务器共同协作,不让其中某一台或几台超额工作,发挥服务器的最大作用
CDN
内容分发网络,基本思路是尽可能避开互联网上有可能影响数据传输速度和稳定性的瓶颈和环节,使内容传输的更快、更稳定。
内存泄漏
定义:程序中己动态分配的堆内存由于某种原因程序未释放或无法释放引发的各种问题 js中可能出现的内存泄漏情况 结果:变慢,崩溃,延迟大等 原因:
避免策略:
babel原理
ES6、7代码输入 -> babylon进行解析 -> 得到AST(抽象语法树)-> plugin用babel-traverse对AST树进行遍历转译 ->得到新的AST树->用babel-generator通过AST树生成ES5代码、
promise
特性:Promise 对象的错误具有冒泡性质,会一直向后传递,直到被捕获为止,也即是说,错误总会被下一个catch语句捕获
js自定义事件
三要素: document.createEvent() event.initEvent() element.dispatchEvent()
demo:
(en:自定义事件名称,fn:事件处理函数,addEvent:为DOM元素添加自定义事件,triggerEvent:触发自定义事件)
window.onload = function(){
var demo = document.getElementById("demo");
demo.addEvent("test",function(){console.log("handler1")});
demo.addEvent("test",function(){console.log("handler2")});
demo.onclick = function(){
this.triggerEvent("test");
}
}
Element.prototype.addEvent = function(en,fn){
this.pools = this.pools || {};
if(en in this.pools){
this.pools[en].push(fn);
}else{
this.pools[en] = [];
this.pools[en].push(fn);
}
}
Element.prototype.triggerEvent = function(en){
if(en in this.pools){
var fns = this.pools[en];
for(var i=0,il=fns.length;i
es6模块 commonjs amd cmd
前后端路由差别
1.后端每次路由请求都是重新访问服务器 2.前端路由实际上只是JS根据URL来操作DOM元素,根据每个页面需要的去服务端请求数据,返回数据后和模板进行组合。
作者:信心
链接:https://juejin.im/post/5b94d8965188255c5a0cdc02
来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。