1.WebSocket的实现和应用
- WebSocket是HTML5中的协议,支持持久连接。
- WebSocket是基于Http协议的,或者说借用了Http协议来完成一部分握手,在握手阶段与Http是相同的。
- 核心属性:
Upgrade:webSocket
Connection:Upgrade
- webSocket只要建立一次连接,就可以连续不断的得到服务器推送的消息,节省带宽和服务器端的压力。
// 客户端
var ws = new WebSocket("ws://localhost:8181");
ws.onopen = function(e) {
//成功连接服务器回调
console.log('客户端(client):与服务器的连接已打开')
}
ws.onmessage = function(e) {
var speedData = JSON.parse(e.data);
console.log("收到数据:" + JSON.stringify(speedData));
};
function sendMessage() {
ws.send('mimi');
};
// 服务端
var WebSocketServer = require('ws').Server,
wss = new WebSocketServer({ port: 8181 });//服务端口8181
wss.on('connection', function (ws) {
console.log('服务端:客户端已连接');
var sendSpeedUpdates = function (ws) {
var speedObj = {
name: 'zl',
};
ws.send(JSON.stringify(speedObj)); //需要将对象转成字符串。WebSocket只支持文本和二进制数据,推送消息
console.log("服务器:更新数据", JSON.stringify(speedObj));
}
//每三秒发送一次
var clientSpeedUpdater = setInterval(function () {
sendSpeedUpdates(ws);
}, 3000);
ws.on('message', function (message) {
//打印客户端监听的消息
console.log(message);
});
});
2.异步回调地狱
比如用ajax嵌套
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsICM38FdsYkRGZkRG9lcvx2bjxiNx8VZ6l2csUXOXFGMGdkWop0MMBjVtJWd0ckW65UbM5WOHJWa5kHT20ESjBjUIF2X0hXZ0xCMx81dvRWYoNHLrdEZwZ1Rh5WNXp1bwNjW1ZUba9VZwlHdssmch1mclRXY39CXldWYtlWPzNXZj9mcw1ycz9WL49zZuBnLzYDO4MDNzYTMzEDNwAjMwIzLc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
这就是直观的回调地狱。
异步回调地狱就是多层嵌套的异步回调。
解决方法:
- 可以用promise,通过在每次返回的promise对象后加then来减少嵌套
- 可以用generator
- 可以用async
- 实际上await是一个让出线程的标志。await后面的表达式会先执行一遍,将await后面的代码加入到microtask中,然后就会跳出整个async函数来执行后面的代码
3.chunk
webpack打包后的代码块
4.OPTIONS
获取当前URL所支持的http请求方法。
此方法存在于一些http请求的预请求中。基本除了get以外,所有对数据库有副作用的方法都会产生预请求。
options的作用根据他的返回数据就可以知道了。
response header | 作用 |
---|---|
Access-Control-Allow-Methods | 返回了服务端允许的请求,包含GET/HEAD/PUT/PATCH/POST/DELETE |
Access-Control-Allow-Credentials | 允许跨域携带cookie(跨域请求要携带cookie必须设置为true) |
Access-Control-Allow-Origin | 允许跨域请求的域名,这个可以在服务端配置一些信任的域名白名单 |
5.PUT
与post类似,后一次操作会覆盖前一次操作
6.浏览器内核
浏览器内核是多线程,在内核控制下各线程相互配合以保持同步,一个浏览器通常由以下常驻线程组成:
- GUI 渲染线程(负责页面的渲染,解析HTML、CSS,构建DOM树,布局和绘制等)
- JavaScript引擎线程
- 定时触发器线程(负责执行异步定时器一类的函数的线程,如: setTimeout,setInterval)
- 事件触发线程
- 异步http请求线程
7.nodejs事件轮询
timer:执行定时器回调
I/O:callbacks:执行io回调
poll:获取io事件
check:执行 setImmediate() 的回调
8.Node与浏览器的 Event Loop 差异
- Node端,microtask 在事件循环的各个阶段之间执行
-
浏览器端,microtask 在事件循环的 macrotask 执行完之后执行
node11事件轮询结果与浏览器一致。
之前的版本可能结果不同。
12.函数柯里化
原理:将多参的函数转为单参函数。保存一个_args数组,里面保存每一次的arguments,再写一个tostring函数,得出这些参数的最终结果。
function add() {
// 第一次执行时,定义一个数组专门用来存储所有的参数
var _args = [].slice.call(arguments);
// 在内部声明一个函数,利用闭包的特性保存_args并收集所有的参数值
var _adder = function() {
_args.push(...arguments);
return _adder;
};
// 利用toString隐式转换的特性,当最后执行时隐式转换,并计算最终的值返回
_adder.toString = function () {
return _args.reduce(function (a, b) {
return a + b;
});
}
return _adder;
}
console.log(add(1)(2)(3)+add(1, 2, 3)(4)) // 6
add(1, 2, 3)(4) // 10
add(1)(2)(3)(4)(5) // 15
add(2, 6)(1) // 9
13.数组的双向绑定
const arrayProto = Array.prototype
const arrayMethods = Object.create(arrayProto);
//拷贝数组类型
[
'push',
'pop',
'shift',
'unshift',
'splice',
'sort',
'reverse'
].forEach(item=>{
Object.defineProperty(arrayMethods,item,{
value:function mutator(){
//缓存原生方法,之后调用
const original = arrayProto[item]
let args = Array.from(arguments)
original.apply(this,args)
},
})
})
//为所有的数组行为绑定监听value
function protoAugment (target,src) {
target.__proto__ = src
}
// 调用
let obarr = []
protoAugment(obarr, arrayMethods)
14.dom的操作
1.获取节点
getElementById
getElementsByClass
getElementsByTagName
querySelector
querySelectorAll
2.指针
first/lastElementChild
previos/nextElementSibling
children/parentElement
3.创建节点
createElement
createTextNode
4.插入节点
insertBefore(newValue,childNodeA)
appendChild
5.替换
replaceChild(newValue,childNodeA)
6.删除
removeChild
7.复制
cloneNode
17.vue与React的区别
- Vue鼓励你去使用HTML模板去进行渲染,React推荐你所有的模板通用JavaScript的语法扩展——JSX书写。
- Vue 通过 getter/setter数据劫持订阅发布者模式双向数据绑定,React 默认是通过比较引用的方式进行的,是单向数据绑定
18.安全证书
防止公钥被修改。
19.mouseleave与mouseout区别
mouseout移入子元素也能触发。