【原码笔记】-- 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 补码:机器 ...
随机推荐
- IMDB TOP 250爬虫
这个小学期Python大作业搞了个获取IMDB TOP 250电影全部信息的爬虫.第二次写爬虫,比在暑假集训时写的熟练多了.欢迎大家评论. ''' ************************** ...
- 如何用webgl(three.js)搭建一个3D库房-第一课
今天我们来讨论一下如何使用当前流行的WebGL技术搭建一个库房并且实现实时有效交互 第一步.搭建一个3D库房首先你得知道库房长啥样,我们先来瞅瞅库房长啥样(这是我在网上找的一个库房图片,百度了“库房” ...
- WebWorker实战使用
总体来说webworker解决了阻塞主线程问题,但是还没解决高性能计算的问题 WebWorker整体介绍 https://developer.mozilla.org/zh-CN/docs/Web/AP ...
- python从2.7升级到3.5 需要主要的问题
今天鼓足勇气把我们python从2.7升级到3.5.我用的是pycharm开发工具.升级过程遇到一些问题小结下: 1.右击项目: 找到左侧 project interpreter选项,配置项目开发环境 ...
- JavaWeb框架SSH_Struts2_(三)
1. Struts2的拦截器(使用拦截器实现权限控制) 拦截器简介 拦截器概述 拦截器工作原理 拦截器的配置 Struts2的内建拦截器 内建拦截器的介绍 内建拦截器的配置 自定义拦截器 实现自定义拦 ...
- redis在spring-boot中的应用
Redis(REmote DIctionary Server) 是一个由Salvatore Sanfilippo写的key-value存储系统.Redis是一个开源的使用ANSI C语言编写.遵守BS ...
- robotframework文本类型的下拉框
对于下拉框定位和输入,这里主要遇到有两种类型的下拉选择. 其中一个类型是select-options格式,如图 这种方式的定位可以使用select from list by value或select ...
- 【javaFX学习】(二) 控件手册
这里写的控件可能不是所有的控件,但是应该是比较齐全并足够用的了,后面还有图表类的,3d模型类,放在后面来写吧,太多了.javafx的功能比以前想象中的要强大.而且也很方便,所有的控件写完后再用Scen ...
- 制作支持 BIOS+UEFI 的 U 盘 grub2+bootmgr 引导 + deepin_recovery + deepin_iso + win_pe
网盘下载:https://pan.baidu.com/s/1c2GXPo0 U盘为 FAT32,MBR分区表 1.下载:U盘grub2+bootmgr引导2017.12.6.2.7z 2.解压到 U盘 ...
- Retrofit网络请求库应用01
PS:什么是Retrofit? 在官方文档中有这样一句话--A type-safe HTTP client for Android and Java(一个类型安全的http client库),具体的话 ...