【原码笔记】-- protobuf.js 与 Long.js
protobuf.js的结构和webpack的加载之后的结构很相似。这样的模块化组合是个不错的结构方式。1个是适应了不同的加载方式,2个模块直接很独立。webpack的功能更全一点。但如果自己封装js库这样够用了。而且模块对外统一接口 module.exports。这和node很像。
(function(global, undefined) {
"use strict";
(function prelude(modules, cache, entries) {
function $require(name) {
var $module = cache[name];
//没有就去加载
if (!$module)
modules[name][0].call($module = cache[name] = { exports: {} }, $require, $module, $module.exports); return $module.exports;
} //曝光成全局
var proto = global.proto = $require(entries[0]); // AMD
if (typeof define === "function" && define.amd) {
define(["long"], function(Long) {
if (Long && Long.isLong) {
proto.util.Long = Long;
proto.configure();
}
});
return proto;
} //CommonJS
if (typeof module === "object" && module && module.exports)
module.exports = proto; })
//传参
({
1: [function (require, module, exports) { function first() {
console.log("first");
} module.exports = first; }, {}],
2: [function(require, module, exports) {
function second() {
console.log("second");
}
module.exports = second;
}],
3: [function (require, module, exports) { var proto = {};
proto.first = require(1);
proto.second = require(2);
proto.build = "full"; module.exports = proto;
}]
}, {}, [3]); })(typeof window==="object"&&window||typeof self==="object"&&self||this)
在处理超过16位的整形就得使用Long.js了。 主要是fromString和toString。
function fromString(str, unsigned, radix) {
if (str.length === 0)
throw Error('empty string');
if (str === "NaN" || str === "Infinity" || str === "+Infinity" || str === "-Infinity")
return ZERO;
if (typeof unsigned === 'number') {
// For goog.math.long compatibility
radix = unsigned,
unsigned = false;
} else {
unsigned = !!unsigned;
}
radix = radix || 10;
if (radix < 2 || 36 < radix)
throw RangeError('radix'); var p;
if ((p = str.indexOf('-')) > 0)
throw Error('interior hyphen');
else if (p === 0) {
return fromString(str.substring(1), unsigned, radix).neg();
} // Do several (8) digits each time through the loop, so as to
// minimize the calls to the very expensive emulated div.
var radixToPower = fromNumber(pow_dbl(radix, 8)); var result = ZERO;
for (var i = 0; i < str.length; i += 8) {
var size = Math.min(8, str.length - i),
value = parseInt(str.substring(i, i + size), radix);
if (size < 8) {
var power = fromNumber(pow_dbl(radix, size));
result = result.mul(power).add(fromNumber(value));
} else {
result = result.mul(radixToPower);
result = result.add(fromNumber(value));
}
}
result.unsigned = unsigned;
return result;
}
fromstring的思路是把字符串8位一个截取。然后转成Long型(高位,地位,符号位) 加起来。最后是一个Long型。 4294967296 是2的32次方。每次操作之前都会有一个基数的操作 mul(radixToPower)或者mul(power)这两者都是保证result的位数是正确的。
比如{low:123} 和{low:1} 相加之前,先要让{low:123}乘以10,得到{low:1230}再与{low:1}进行位操作。因为第一个是高位,不能直接相加。
function fromBits(lowBits, highBits, unsigned) {
return new Long(lowBits, highBits, unsigned);
}
fromBits 即转为Long对象。value%4294967296 得到低位。/得到高位。结果通过位移合并起来。mul是bit的乘法,add是bit的加法。 原理是讲一个64位的拆成四段。分别16位。this.low左移16位 就得到 low的32-17位是啥。 然后和addend对象的同位相加
最后的合并是通过|运算。位移之后再还原确实很巧妙。一时看上去都不大理解。
LongPrototype.add = function add(addend) {
if (!isLong(addend))
addend = fromValue(addend); // Divide each number into 4 chunks of 16 bits, and then sum the chunks. var a48 = this.high >>> 16;
var a32 = this.high & 0xFFFF;
var a16 = this.low >>> 16;
var a00 = this.low & 0xFFFF; var b48 = addend.high >>> 16;
var b32 = addend.high & 0xFFFF;
var b16 = addend.low >>> 16;
var b00 = addend.low & 0xFFFF; var c48 = 0, c32 = 0, c16 = 0, c00 = 0;
c00 += a00 + b00;
c16 += c00 >>> 16;
c00 &= 0xFFFF;
c16 += a16 + b16;
c32 += c16 >>> 16;
c16 &= 0xFFFF;
c32 += a32 + b32;
c48 += c32 >>> 16;
c32 &= 0xFFFF;
c48 += a48 + b48;
c48 &= 0xFFFF;
return fromBits((c16 << 16) | c00, (c48 << 16) | c32, this.unsigned);
};
>>>和>>有什么区别??。
toString
LongPrototype.toString = function toString(radix) {
radix = radix || 10;
if (radix < 2 || 36 < radix)
throw RangeError('radix');
if (this.isZero())
return '0';
if (this.isNegative()) { // Unsigned Longs are never negative
if (this.eq(MIN_VALUE)) {
// We need to change the Long value before it can be negated, so we remove
// the bottom-most digit in this base and then recurse to do the rest.
var radixLong = fromNumber(radix),
div = this.div(radixLong),
rem1 = div.mul(radixLong).sub(this);
return div.toString(radix) + rem1.toInt().toString(radix);
} else
return '-' + this.neg().toString(radix);
} // Do several (6) digits each time through the loop, so as to
// minimize the calls to the very expensive emulated div.
var radixToPower = fromNumber(pow_dbl(radix, 6), this.unsigned),
rem = this;
var result = '';
while (true) {
var remDiv = rem.div(radixToPower),
intval = rem.sub(remDiv.mul(radixToPower)).toInt() >>> 0,
digits = intval.toString(radix);
rem = remDiv;
if (rem.isZero())
return digits + result;
else {
while (digits.length < 6)
digits = '0' + digits;
result = '' + digits + result;
}
}
};
也是sub之后拼出来的。也就是fromstring的反向操作。
【原码笔记】-- protobuf.js 与 Long.js的更多相关文章
- h5 录音 自动生成proto Js语句 UglifyJS-- 对你的js做了什么 【原码笔记】-- protobuf.js 与 Long.js 【微信开发】-- 发送模板消息 能编程与会编程 vue2入坑随记(二) -- 自定义动态组件 微信上传图片
得益于前辈的分享,做了一个h5录音的demo.效果图如下: 点击开始录音会先弹出确认框: 首次确认允许后,再次录音不需要再确认,但如果用户点击禁止,则无法录音: 点击发送 将录音内容发送到对话框中.点 ...
- Nodejs学习笔记(六)--- Node.js + Express 构建网站预备知识
目录 前言 新建express项目并自定义路由规则 如何提取页面中的公共部分? 如何提交表单并接收参数? GET 方式 POST 方式 如何字符串加密? 如何使用session? 如何使用cookie ...
- VueJs 源码解析 (四) initRender.Js
vueJs 源码解析 (四) initRender.Js 在之前的文章中提到了 vuejs 源码中的 架构部分,以及 谈论到了 vue 源码三要素 vm.compiler.watcher 这三要素,那 ...
- Nodejs学习笔记(六)—Node.js + Express 构建网站预备知识
前言 前面经过五篇Node.js的学习,基本可以开始动手构建一个网站应用了,先用这一篇了解一些构建网站的知识! 主要是些基础的东西... 如何去创建路由规则.如何去提交表单并接收表单项的值.如何去给密 ...
- Nodejs学习笔记(七)—Node.js + Express 构建网站简单示例
前言 上一篇学习了一些构建网站会用到的一些知识点:https://www.cnblogs.com/flyingeagle/p/9192936.html 这一篇主要结合前面讲到的知识,去构建一个较为完整 ...
- [小问题笔记(六)] 解决JS已执行,输出内容乱码问题. 顺带总结编码相关知识
问题: JS输出的内容出现了乱码.如图: 分析:既然年和月的数字可以正常显示,证明js加载和执行都没有问题 解决:把js引用处的编码方式改成当前页面编码一致.charset="gb2312& ...
- Gin-Go学习笔记三:Gin-Web框架 JS分页
JS 分页 1> JS分页,业务逻辑 (1) 分页采用的是一个叫jquery.pagination.js的一个jquery插件 (2) 需要jquery的支持,此项目中使 ...
- python3笔记二:进制转换与原码反码补码
一:学习内容 进制:二进制.八进制.十进制.十六进制 进制转换 原码.反码.补码 二:进制 二进制 1.二进制:只有0和1,逢2进1 2.举例:0+0=0.0+1=1.1+1=10 3.过程剖析:二进 ...
- C语言学习笔记之原码反码补码
原码:就是我们自己看的,以及机器输出给我们看的 补码:机器永远是以补码的形式将数据保存在计算机中 正数: 原码=反码=补码 负数: 反码:原码的符号位不变,其他位取反 ,1变0 0变1 补码:机器 ...
随机推荐
- AndroidStudio中各种常见快捷键记录
AndroidStudio中各种常用操作快捷键记录 简单方法 直接设置AS的快捷键与eclipse相同,方便直接从eclipse切到AS的人. 常用的AS的默认快捷键 ctrl + N 根据类名查找J ...
- java 之 建造者模式(大话设计模式)
建造者模式,在笔者看来比较试用于,定制一个业务流程,而流程的细节又不尽相同,每个细节又必不可少,这时应考虑使用建造者模式. 大话设计模式-类图 先看下笔者写的一个简单的例子. /** * 所有建造过程 ...
- Mysql--数据的操作
1.插入数据 1.1 插入完整数据记录 语法1: 例子: 语法2: 例子: 1.2 插入数据记录一部分 语法: 例子: 1.3 插入多条数据记录 1.插入多条完整的数据 语法: 例子: 插入多条部 ...
- SpringMvc架构下css、js、jpg加载失败问题
SpringMvc架构下css.js.jpg加载失败问题 springMvc搭建成功后,页面出现一些错误,jsp.js等静态资源加载失败.导致页面没有显示任何样式以及 此处原因很简单,是因为相对路径在 ...
- 为什么win记事本编辑的shell在linux中运行会报错
结论:win记事本使用的格式有别于linux,二者不可混用.linux使用一个叫vi的编辑器. 解决办法:使用vi命令建立文件,在其中敲shell.命令:vi > filename (敲完 ...
- eclipse 常用插件 整理
开发过程中的常用Eclipse插件,按字母排序: (1) AmaterasUML 介绍:Eclipse的UML插件,支持UML活动图,class图,sequence图,usecas ...
- SEO中TDK写法的意思以及注意事项
在SEO中,所谓的TDK其实就是title.description.keywords这三个标签,这三个标签在网站的优化过程中,至关重要所以今天童童来和大家分享下,如何去写好TDK标签! 1.title ...
- PHP提高网站性能的一些方法
前段时间面试问到了这个问题,回答的不是很全面,就去问了度娘,得到了一些比较全的答案,由于出处较多就没法确定原文出处了.下面是分享的答案. 一.大型网站性能提高策略: 大型网站,比如门户网站,在面对大量 ...
- WampSever 安装问题解析
鉴于有些电脑安装wampsever出现的几种问题 [1] 2.2版本问题 这里端口配置正确,本地服务器没有开启(也就是80端口没有占用) 还是出现这种情况 也就是Apache service 和 PH ...
- layui使用心得
表单控件样式没生效, 因为没引入form. layui.use('form', function(){ var form = layui.form; }); radio改变事件没生效, 需要手动fil ...