Event
Tips:原型继承的几种方式
const EventEmitter = require('events');
function Girl() {}
// 原型继承的几种方式
Girl.prototype.__proto__ = EventEmitter.prototype;
Object.setPrototypeOf(Girl.prototype, EventEmitter.prototype);
Girl.prototype = Object.create(EventEmitter.prototype);
// create的实现
function create(proto) {
function Fn() {}
Fn.prototype = proto;
return new Fn();
}
复制代码
node 中的发布订阅
-
on订阅 emit触发 once订阅一次 off取消订阅
-
node 中原型继承的实现:
util.inherits(Girl, EventEmitter)
(内部是通过 setPrototypeOf 实现的) -
使用
const EventEmitter = require('events');
const util = require('util');
function Girl() {}
// 原型继承 需要通过实例来调用继承的方法
util.inherits(Girl, EventEmitter);
let girl = new Girl();
// 订阅
girl.on('brokenheart', (a, b) => {
console.log('cry');
});
girl.on('brokenheart', (a, b) => {
console.log('eat');
});
//触发
setTimeout(() => {
girl.emit('brokenheart', 'a', 'b');
}, 1000);
// 订阅
const fn = () => {
console.log('shopping');
};
girl.once('brokenheart', fn);
//触发
setTimeout(() => {
// 如果先移除绑定一次的事件,再执行,因为绑定的是one,移除的是fn,所以要给one上绑定原事件函数
girl.off('brokenheart', fn);
girl.emit('brokenheart', 'a', 'b');
}, 1000);
复制代码
EventEmitter 的实现
- 要能手写
function EventEmitter() {
this._events = {};
}
EventEmitter.prototype.on = function (eventName, callback) {
if (this._events) {
// this是girl的实例,要把_events绑定到girl上
this._events = {};
}
if (this._events[eventName]) {
this._events[eventName].push(callback);
} else {
this._events[eventName] = [callback];
}
};
EventEmitter.prototype.emit = function (eventName, ...args) {
this._events[eventName].forEach((fn) => fn(...args));
};
EventEmitter.prototype.off = function (eventName, callback) {
if (this._events && this._events[eventName]) {
this._events[eventName] = this._events[eventName].filter(
(fn) => fn !== callback && fn.l !== callback
);
}
};
EventEmitter.prototype.once = function (eventName, callback) {
// 执行完毕后移除
const one = () => {
// AOP
callback();
this.off(eventName, one);
};
one.l = callback; // 关联上原始事件 用于事件移除时判断
this.on(eventName, one);
};
module.exports = EventEmitter;
复制代码
Buffer
进制的概念
- 早期前端是无法直接读取文件操作文件的 (node 是使用在服务端)对文件和前端传递过来的数据进行处理
- 前端传递过来的是二进制数据
- 进制数据: 所有内容都是以二进制来存储
- node 需要将这个数据读取出来,将数据存储到需要的位置(如硬盘),在内存中的表现都是以二进制来表现的
0.1 + 0.2 !== 0.3
最终数据都是以二进制来存储的,所以会出现不精准的情况
二进制和十进制的区别
-
十进制中最大的是 9
-
二进制中最大的是 1
-
以字节为单位存储数据 1024 字节 => 1k 1024k => 1m
-
一个字节由 8 个位组成,里面都是二进制数
-
其他进制转化为十进制:当前位的值 * 进制^当前所在位, 把每一位进行相加
-
所以一个字节最大就是 11111111(8 个 1), 最大能表示的十进制数为 255, 0-255 就是一个字节的取值范围
-
将十进制转换成二进制:取余 倒着组合
-
parseInt 可以将其他进制转换为十进制: parseInt(‘101’, 2); 参数 2 用来表示前面的 101 是一个二进制的数 数
-
0b 二进制 0x 十六进制
-
(0x64).toString(2) 十六进制转二进制 将任意进制转换成任意进制 字符串
-
小数也要转化成 2 进制
10 进制中的 0.5 是 2 进制中的 0.1(因为 10 => 0.5 20 倍 所以 2 => 0.1 20 倍)
十进制小数转为二进制的方法:乘 2 取整法可以将一个小数转化成 2 进制数
// 0.1 + 0.2的问题
0.1 * 2 = 0.2 0
0.2 * 2 = 0.4 0
0.4 * 2 = 0.8 0
0.8 * 2 = 1.6 1
0.6 * 2 = 1.2 1
0.1 * 2 = 0.2 0
0.2 * 2 = 0.4 0
0.4 * 2 = 0.8 0
0.8 * 2 = 1.6 1
0.6 * 2 = 1.2 1
// 0.1转为二进制是一个无穷尽的小数
// 0.1转为二进制进行存储的时候会稍微比0.1大一点
// 0.2也是这样
// 所以 0.1 + 0.2 会大于 0.3
console.log(0.1+0.2) // 考察的是进制转化的问题
// js没有将小数转化成2进制方法
// 为什么 0.2+0.2 没有问题?
// 如果出现精度问题怎么解决?
复制代码
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END