console.log([] == ![]) // true console.log([] == []) // false console.log([] == {}) // false console.log(new String('a') == new String('a')) // false console.log(isNaN(NaN)) // true console.log(isNaN('32131dsafdas')) // true console.log(NaN === NaN) // false console.log(NaN === undefined) // false console.log(undefined === undefined) // true console.log(typeof NaN) // number console.log({} + []) // 0 console.log([] + {}) // "[object Object]" console.log({} + {}) // "[object Object][object Object]" console.log([]+ []) // "" console.log({} + 1) // 1 console.log([] + 1) // "1"
隐式类型转换参考:https://blog.csdn.net/m0_37793545/article/details/87862847html
var name = 'world'; (function () { if (typeof name === 'undefined') { var name = 'jack' console.log('hi' + name) } else { console.log('hello' + name) } })() // hijack
var test = (function (a) { this.a = a; return function (b) { return this.a + b } }(function (a, b) { return a }(1, 2))) test(4) // 5
var x = 1, y = z = 0 function add(n) { return n = n + 1 } y = add(x) function add(n) { return n = n + 3 } z = add(x) console.log(x, y, z) // 1 4 4
function bar() { return foo; foo = 10; function foo() {} var foo = 11 } alert(typeof bar()) // function (2) var a = 1 function a() {} console.log(a) // 1 (3) var b = 1 if (true) { console.log(b) // 1 var b = 2 var c = 3 console.log(c) // 3 } console.log(b) // 2 console.log(c) // 3
var x = 3; var foo = { x: 2, baz: { x: 1, bar: function () { return this.x } } } var go = foo.baz.bar go() foo.baz.bar() // 3 // 1
console.log([1, 2] + [2, 1]) // 1,2,2,1
var test = '12344321' var test1 = test.split('').reverse().join('') console.log(test === test1)
//去重: (1)Array.from(new Set([1,2,3,5,2,1,22,'1'])) (2) var array = [1, 2, 1, 1, '1']; function unique(array) { var res = array.filter(function(item, index, array){ return array.indexOf(item) === index; }) return res; } console.log(unique(array)); (3) function unique(arr) { arr = arr.sort() let res = [] for (let i = 0; i < arr.length; i++) { if (arr[i] !== arr[i-1]) { res.push(arr[i]) } } return res }
更多去重方式:http://www.javashuo.com/article/p-pmixedhh-h.html
数组排序总结:http://www.javashuo.com/article/p-azrzzgup-dz.html前端
// (1) 借助构造函数实现继承 function Parent() { this.name = 'parent' } function Child() { Parent.call(this) this.age = 18 } // 这种方式只能实现部分继承,即父类的构造方法中的属性,子类能够继承,其缺点是,父类原型上的属性或方法,子类没法继承。 // (2)借助原型链实现继承 function Parent() { this.name = 'parent' this.play = [1, 2, 3] } function Child() { this.age = 18 } Child.prototype = new Parent() // 这种继承方式的缺点是用子类Child实例化两个对象后,var s1 = new Child(); var s2 = new Child(); s1.play.push(4); console.log(s2.play); 也会打印出[1,2,3,4],其缘由是两个对象的__proto__指向了同一个原型对象。 // (3)组合方式(继承的完美实现) function Parent() { this.name = 'parent' } function Child() { // 将父对象的构造函数绑定在子对象上 Parent.call(this) this.age = 18 } // 将Parent的prototype拷贝给Child Child.prototype = Object.create(Parent.prototype) // 修正Child的prototype对象指向的构造函数 Child.prototype.constructor = Child
// 请写出如下代码执行的顺序 setTimeout(function () { console.log(1); }); new Promise(function(resolve,reject){ console.log(2) resolve(3) }).then(function(val){ console.log(val); }) console.log(4); // 2 4 3 1 在同步代码执行完成后才回去检查是否有异步任务完成,并执行对应的回调,而微任务又会在宏任务以前执行。 同步代码=>异步代码(微任务=>宏任务) 宏任务: setTimeout 微任务: Promise.then
var a={length:2,0:'aaa',1:'bbb'}; // ES6: Array.from(a) // ES5: Array.prototype.slice.call(a);// ["aaa", "bbb"] var a={length:2}; Array.prototype.slice.call(a);// [undefined, undefined]
function Foo() { getName = function() { alert(1) } return this } Foo.getName = function() { alert(2) } Foo.prototype.getName = function() { alert(3) } var getName = function() { alert(4) } function getName() { alert(5) } //请写出如下输出结果: Foo.getName() // 2 getName() // 4 Foo().getName() // 1 getName() // 1 new Foo.getName() // 2 new Foo().getName() // 3 new new Foo().getName() // 3 // 详细解释 https://www.jb51.net/article/79461.htm
(1) 函数防抖vue
function debounce(func, delay) { var timeout return function(e) { console.log('清除', timeout, e.target.value) clearTimeout(timeout) var context = this, args = arguments console.log('新的', timeout, e.target.value) timeout = setTimeout(function() { console.log('----') func.apply(context, args) }, delay) } } var validate = debounce(function(e) { console.log('change', e.target.value, new Date() - 0) }, 380) // 绑定监听 document.querySelector('input').addEventListener('input', validate)
(2) 函数节流node
// 函数节流 function throttle(fn, threshhold) { var timeout var start = new Date() var threshhold = threshhold || 160 return function() { var context = this, args = arguments, curr = new Date() - 0 clearTimeout(timeout) //老是干掉事件回调 if (curr - start >= threshhold) { console.log('now', curr, curr - start) //注意这里相减的结果,都差很少是160左右 fn.apply(context, args) //只执行一部分方法,这些方法是在某个时间段内执行一次 start = curr } else { //让方法在脱离事件后也能执行一次 timeout = setTimeout(function() { fn.apply(context, args) }, threshhold) } } } var mousemove = throttle(function(e) { console.log(e.pageX, e.pageY) }) // 绑定监听 document.querySelector('#panel').addEventListener('mousemove', mousemove)
hash(散列、杂凑)函数,是将任意长度的数据映射到有限长度的域上。直观解释起来,就是对一串数据m进行杂糅,输出另外一段固定长度的数据h,做为这段数据的特征(指纹)。也就是说,不管数据块m有多大,其输出值h为固定长度。jquery
hashmap,hash值(key)存在的目的是加速键值对的查找nginx
详解:https://www.zhihu.com/question/26762707web
每一个实例能够维护一份被返回对象的独立的拷贝,不然;将致使多个实例共享一个对象,其中一个组件改变data属性值,其它实例也会受到影响。算法
jQuery.extend()为扩展jQuery类自己.为类添加新的方法。如 $.wang() jquery.fn.extend(object);给jQuery对象添加方法。如 $('#test').wang()
(1)所谓的virtual dom,也就是虚拟节点。它经过JS的Object对象模拟DOM中的节点,而后再经过特定的render方法将其渲染成真实的DOM节点 dom diff 则是经过JS层面的计算,返回一个patch对象,即补丁对象,在经过特定的操做解析patch对象,完成页面的从新渲染 (2)DOM DIFF 比较两棵DOM树的差别是Virtual DOM算法最核心的部分.简单的说就是新旧虚拟dom 的比较,若是有差别就以新的为准,而后再插入的真实的dom中,从新渲染。 比较只会在同层级进行, 不会跨层级比较。新旧虚拟dom比较的时候,是先同层比较,同层比较完看看时候有儿子,有则须要继续比较下去,直到没有儿子。 比较后会出现四种状况: 一、此节点是否被移除 -> 添加新的节点 二、属性是否被改变 -> 旧属性改成新属性 三、文本内容被改变-> 旧内容改成新内容 四、节点要被整个替换 -> 结构彻底不相同 移除整个替换
详解:http://www.javashuo.com/article/p-rsuyzvts-kc.htmljson
// 100 Continue 继续,通常在发送post请求时,已发送了http header以后服务端将返回此信息,表示确认,以后发送具体参数信息 // 200 OK 正常返回信息 // 201 Created 请求成功而且服务器建立了新的资源 // 202 Accepted 服务器已接受请求,但还没有处理 // 301 Moved Permanently 请求的网页已永久移动到新位置。 // 302 Found 临时性重定向。 // 303 See Other 临时性重定向,且老是使用 GET 请求新的 URI。 // 304 Not Modified 自从上次请求后,请求的网页未修改过。 // 400 Bad Request 服务器没法理解请求的格式,客户端不该当尝试再次使用相同的内容发起请求。 // 401 Unauthorized 请求未受权。 // 403 Forbidden 禁止访问。 // 404 Not Found 找不到如何与 URI 相匹配的资源。 // 500 Internal Server Error 最多见的服务器端错误。 // 503 Service Unavailable 服务器端暂时没法处理请求(多是过载或维护)。
同源策略是浏览器的一个安全功能,不一样源的客户端脚本在没有明确受权的状况下,不能读写对方资源。若地址里面的协议、域名和端口号均相同则属于同源。segmentfault
jsonp跨域、nginx反向代理、node.js中间件代理跨域、后端设置http header、后端在服务器上设置cors。
重绘:当页面中元素样式的改变并不影响它在文档流中的位置时(例如:color、background-color、visibility等),浏览器会将新样式赋予给元素并从新绘制它,这个过程称为重绘。
回流:当Render Tree(DOM)中部分或所有元素的尺寸、结构、或某些属性发生改变时,浏览器从新渲染部分或所有文档的过程称为回流。
回流要比重绘消耗性能开支更大。
回流必将引发重绘,重绘不必定会引发回流。
详解:http://www.javashuo.com/article/p-npxyfplr-cw.html
加载过程:
渲染过程:
<script>
时,会执行并阻塞渲染强制缓存:catch-control,expires,catch-control优先级高。
协商缓存:Last-Modified / If-Modified-Since和Etag / If-None-Match,其中Etag / If-None-Match的优先级比Last-Modified / If-Modified-Since高。
详解:https://juejin.im/entry/5ad86c16f265da505a77dca4
http://www.javashuo.com/article/p-qbijdnlt-bx.html
详解:http://www.javashuo.com/article/p-sdwfvzai-eb.html
首页能够控制导航跳转,beforeEach,afterEach等,通常用于页面title的修改。一些须要登陆才能调整页面的重定向功能。
beforeEach主要有3个参数to,from,next:
afterEach和beforeResolve(全局解析守卫)没有next参数
路由独享的守卫:beforeEnter,参数同全局前置守卫
组件内的守卫:beforeRouteEnter(组件实例未建立,不能使用this),beforeRouteUpdate,beforeRouteLeave
详解:https://router.vuejs.org/zh/guide/advanced/navigation-guards.html
hash模式:在浏览器中符号“#”,#以及#后面的字符称之为hash,用window.location.hash读取;
特色:hash虽然在URL中,但不被包括在HTTP请求中;用来指导浏览器动做,对服务端安全无用,hash不会重加载页面。
hash 模式下,仅 hash 符号以前的内容会被包含在请求中,如 http://www.xxx.com,所以对于后端来讲,即便没有作到对路由的全覆盖,也不会返回 404 错误。
history模式:history采用HTML5的新特性;且提供了两个新方法:pushState(),replaceState()能够对浏览器历史记录栈进行修改,以及popState事件的监听到状态变动。
history 模式下,前端的 URL 必须和实际向后端发起请求的 URL 一致,如 http://www.xxx.com/items/id。后端若是缺乏对 /items/id 的路由处理,将返回 404 错误。Vue-Router 官网里如此描述:“不过这种模式要玩好,还须要后台配置支持……因此呢,你要在服务端增长一个覆盖全部状况的候选资源:若是 URL 匹配不到任何静态资源,则应该返回同一个 index.html 页面,这个页面就是你 app 依赖的页面。”
防范:全部用户输入的都是不可信的,输入过滤和转义,重要cookie设置为HttpOnly
防范:
详解:https://www.jianshu.com/p/64a413ada155
overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
简单方法:
var add = function(a){ return function(b){ return function(c){ return a+b+c; }; }; };
可是这样的代码在add(1)(2)或者add(1)(2)(3)(4)时便不对了。
正确实现:
function add () { var args = Array.prototype.slice.call(arguments); var fn = function () { var arg_fn = Array.prototype.slice.call(arguments); return add.apply(null, args.concat(arg_fn)); } // 重写valueOf方法,是为了处理隐式类型转换 fn.valueOf = function () { return args.reduce(function(a, b) { return a + b; }) } return fn; }
详解:https://www.cnblogs.com/coco1s/p/6509141.html 或
https://blog.csdn.net/m0_37793545/article/details/87862847
function log(){ console.log.apply(console, arguments); }
手写一个new实现 function create() { // 建立一个空的对象 var obj = new Object(), // 得到构造函数,arguments中去除第一个参数 Con = [].shift.call(arguments); // 连接到原型,obj 能够访问到构造函数原型中的属性 obj.__proto__ = Con.prototype; // 绑定 this 实现继承,obj 能够访问到构造函数中的属性 var ret = Con.apply(obj, arguments); // 优先返回构造函数返回的对象 return ret instanceof Object ? ret : obj; };
详解:《JS高程》 6.2.2 《你不知道的Javascript》2.2.4
相对于父级宽度的:
max-width、min-width、width、left、right、text-indent、padding、margin、grid-template-columns、grid-auto-columns、column-gap 等;
相对于父级高度的:
max-height、min-height、height、top、bottom、grid-template-rows、grid-auto-rows、row-gap 等;
相对于主轴长度的:
flex-basis 等;
相对于继承字号的:
font-size 等;
相对于自身字号的:
line-height 等;
相对于自身宽高的:
border-radius、background-size、border-image-width、transform: translate()、transform-origin、zoom、clip-path 等;
相对于行高的:
vertical-align 等;
特殊算法的:
background-position (方向长度 / 该方向除背景图以外部分总长度)、border-image-slice (相对于图片尺寸)、filter 系列函数等;
若是自身设置 position: absolute,“父级”指:Boring:破坏文档流的div高度设为百分比是相对谁而言的?;
若是 position: fixed,“父级”指视口(父级不存在 transform 为非 none 值的状况下)。
来源:知乎
连接:https://www.zhihu.com/question/36079531/answer/65809167
闭包:就是可以读取其余函数内部变量的函数。
堆栈溢出:就是不顾堆栈中分配的局部数据块大小,向该数据块写入了过多的数据,致使数据越界,结果覆盖了别的数据。常常会在递归中发生。
内存泄露是指:用动态存储分配函数内存空间,在使用完毕后未释放,致使一直占据该内存单元。直到程序结束。指任何对象在您再也不拥有或须要它以后仍然存在。
形成内存泄漏:
setTimeout 的第一个参数使用字符串而非函数的话,会引起内存泄漏。
闭包、控制台日志、循环(在两个对象彼此引用且彼此保留时,就会产生一个循环)
防止内存泄露:
一、不要动态绑定事件;
二、不要在动态添加,或者会被动态移除的dom上绑事件,用事件冒泡在父容器监听事件;
三、若是要违反上面的原则,必须提供destroy方法,保证移除dom后事件也被移除,这点能够参考Backbone的源代码,作的比较好;
四、单例化,少建立dom,少绑事件。
点击穿透现象有3种:
点击穿透问题:点击蒙层(mask)上的关闭按钮,蒙层消失后发现触发了按钮下面元素的click事件跨页面点击穿透问题:若是按钮下面刚好是一个有href属性的a标签,那么页面就会发生跳转另外一种跨页面点击穿透问题:此次没有mask了,直接点击页内按钮跳转至新页,而后发现新页面中对应位置元素的click事件被触发了
解决方案:
一、只用touch
最简单的解决方案,完美解决点击穿透问题
把页面内全部click所有换成touch事件( touchstart 、’touchend’、’tap’)
二、只用click
下下策,由于会带来300ms延迟,页面内任何一个自定义交互都将增长300毫秒延迟
三、tap后延迟350ms再隐藏mask
改动最小,缺点是隐藏mask变慢了,350ms仍是能感受到慢的
四、pointer-events
比较麻烦且有缺陷, 不建议使用mask隐藏后,给按钮下面元素添上 pointer-events: none; 样式,让click穿过去,350ms后去掉这个样式,恢复响应缺陷是mask消失后的的350ms内,用户能够看到按钮下面的元素点着没反应,若是用户手速很快的话必定会发现
TCP是主机对主机层的传输控制协议,提供可靠的链接服务,采用三次握手确认创建一个链接,四次挥手断开链接
位码即tcp标志位,有6种标示:SYN(synchronous创建联机) ACK(acknowledgement 确认) PSH(push传送) FIN(finish结束) RST(reset重置) URG(urgent紧急)
Sequence number(顺序号码) Acknowledge number(确认号码)
第一次握手:主机A发送位码为syn=1,随机产生seq number=1234567的数据包到服务器并进入SYN_SEND状态,主机B由SYN=1知道,A要求创建联机;
第二次握手:主机B收到请求后要确认联机信息,向A发送ack number=(主机A的seq+1),syn=1,ack=1,随机产生seq=7654321的包并进入SYN_RECV状态
第三次握手:主机A收到后检查ack number是否正确,即第一次发送的seq number+1,以及位码ack是否为1,若正确,主机A会再发送ack number=(主机B的seq+1),ack=1,主机B收到后确认seq值与ack=1则链接创建成功,客户端和服务器进入ESTABLISHED状态。
完成三次握手,主机A与主机B开始传送数据。
中断链接能够是Client端发起,也能够是Server端发起
假设Client端发起中断链接请求,也就是发送FIN报文。Server端接到FIN报文后,意思是说"我Client端没有数据要发给你了",可是若是你还有数据没有发送完成,则没必要急着关闭Socket,能够继续发送数据。因此你先发送ACK,“告诉Client端,你的请求我收到了,可是我还没准备好,请继续你等个人消息”。这个时候Client端就进入FIN_WAIT状态,继续等待Server端的FIN报文。当Server端肯定数据已发送完成,则向Client端发送FIN报文,“告诉Client端,好了,我这边数据发完了,准备好关闭链接了”。Client端收到FIN报文后,"就知道能够关闭链接了,可是他仍是不相信网络,怕Server端不知道要关闭,因此发送ACK后进入TIME_WAIT状态,若是Server端没有收到ACK则能够重传。“,Server端收到ACK后,“就知道能够断开链接了”。Client端等待了2MSL后依然没有收到回复,则证实Server端已正常关闭,那好,我Client端也能够关闭链接了。Ok,TCP链接就这样关闭了!
相关问题:
1.为何创建链接协议是三次握手,而关闭链接倒是四次握手呢?
这是由于服务端的LISTEN状态下的SOCKET当收到SYN报文的建连请求后,它能够把ACK和SYN(ACK起应答做用,而SYN起同步做用)放在一个报文里来发送。但关闭链接时,当收到对方的FIN报文通知时,它仅仅表示对方没有数据发送给你了;但未必你全部的数据都所有发送给对方了,因此你能够未必会立刻会关闭SOCKET,也即你可能还须要发送一些数据给对方以后,再发送FIN报文给对方来表示你赞成如今能够关闭链接了,因此它这里的ACK报文和FIN报文多数状况下都是分开发送的.
2.为何TIME_WAIT状态还须要等2MSL后才能返回到CLOSED状态?
这是由于虽然双方都赞成关闭链接了,并且握手的4个报文也都协调和发送完毕,按理能够直接回到CLOSED状态(就比如从SYN_SEND状态到ESTABLISH状态那样);可是由于咱们必需要假想网络是不可靠的,你没法保证你最后发送的ACK报文会必定被对方收到,所以对方处于LAST_ACK状态下的SOCKET可能会由于超时未收到ACK报文,而重发FIN报文,因此这个TIME_WAIT状态的做用就是用来重发可能丢失的ACK报文。
详解解释:http://www.cnblogs.com/cy568searchx/p/3711670.html
// 坑人的连续赋值问题 var a = {n: 1}; var b = a; a.x = a = {n: 2}; console.log(a.x); // undefinde console.log(b); // {n:1,x:{n:2}}
详解:https://www.zhihu.com/question/41220520
function f1(){ var n=999 nAdd=function(){ n+=1 console.log(n) } function f2(){ console.log(n) } return f2 } f1()() // 999 nAdd() // 1000 nAdd() // 1001
require/exports 的用法只有如下三种简单的写法:
const fs = require('fs') exports.fs = fs module.exports = fs
而 import/export 的写法就多种多样:
import fs from 'fs' import {default as fs} from 'fs' import * as fs from 'fs' import {readFile} from 'fs' import {readFile as read} from 'fs' import fs, {readFile} from 'fs' export default fs export const fs export function readFile export {readFile, read} export * from 'fs'
详解:https://www.zhihu.com/question/56820346