Node.js中的缓冲区比较

我在Node.js中是新的 没有缓冲区比较,我应该使用buffertools模块这些function。

但是当我比较纯节点中的Buffer对象时,我看到一个非常奇怪的行为。

> var b1 = new Buffer([170]); > var b2 = new Buffer([171]); > b1 <Buffer aa> > b2 <Buffer ab> > b1 < b2 false > b1 > b2 false > b1 == b2 false 

 > var b1 = new Buffer([10]); > var b2 = new Buffer([14]); > b1 <Buffer 0a> > b2 <Buffer 0e> > b1 > b2 false > b1 < b2 true > b1 == b2 false 

实际上究竟发生了什么?

这就是比较运算符如何处理对象:

 var a = {}, b = {}; a === b; //false a == b; //false a > b; //false a < b; //false var c = { valueOf : function () { return 0; } }; var d = { valueOf : function () { return 1; } }; c === d; //false c == d; //false c > d; //false c < d; //true 

在引擎盖下

(有点)

第1部分:平等

这是最简单的部分。 抽象平等( == , spec )和严格平等( === , spec )检查是否引用同一个对象(比较引用)。 在这种情况下,他们显然不是,所以他们的答案是false==规格步骤10, ===规格步骤7)。

因此,在这两种情况下:

 b1 == b2 //false b1 === b2 //false 

第2部分:比较反击

这里有趣的部分。 让我们看看如何定义关系运算符( <> )。 在这两种情况下,我们来看看调用链。

 x = b1 //<Buffer aa> y = b2 //<Buffer ab> //11.8.5 The Abstract Relational Comparison Algorithm (http://es5.github.com/#x11.8.5) Let px be the result of calling ToPrimitive(x, hint Number). Let py be the result of calling ToPrimitive(y, hint Number). //9.1 ToPrimitive (http://es5.github.com/#x9.1) InputType is Object, therefore we call the internal [[DefaultValue]] method with hint Number. //8.12.8 [[DefaultValue]] (hint) http://es5.github.com/#x8.12.8 We try and fetch the object's toString method. If it's defined, call it. 

在这里我们已经达到了高潮:什么是缓冲区的toString方法? 答案在于node.js内部深处。 如果你想的话, 有它 。 我们可以通过实验发现,

 > b1.toString() ' ' > b2.toString() ' ' 

好的,这没有帮助。 你会注意到,在抽象关系比较algorithm(Abstract Relational Comparison Algorithm)( <是什么)中,有一个处理string的步骤。 它只是将它们转换为它们的数值 – char代码。 让我们这样做:

 > b1.toString().charCodeAt(0) 65533 > b2.toString().charCodeAt(0) 65533 

65533是一个重要的数字。 这是两个方块的总和: 142^2 + 213^2 。 它也恰好是Unicodereplace字符,这个字符表示“我不知道发生了什么”。 这就是为什么它的hex等价于FFFD。

显然, 65533 === 65533 ,所以:

 b1 < b2 //is b1.toString().charCodeAt(0) < b2.toString().charCodeAt(0) //is 65533 < 65533 //false b1 > b2 //following same logic as above, false 

就是这样

伙计,到底是什么?

好吧,这一定是混乱,因为我的解释努力没有得到很好的思考。 回顾一下,发生了什么事情:

  1. 你创build了一个缓冲区。 本杰明·格鲁恩鲍姆(Benjamin Gruenbaum)通过这样做来帮助我重buildtesting用例:

    var b1 = new Buffer([170]), b2 = new Buffer([171]);

  2. 当输出到控制台时,这些值被转换成它们的hex等价值(参见缓冲区#检查 ):

    170..toString(16) === 'aa'

    171..toString(16) === 'ab'

  3. 然而,在内部,它们代表了无效的字符(因为它不是hex编码;再一次,你可以自由钻研实现本质,我不会(哦讽刺))。 因此,转换为string时,它们用Unicodereplace字符表示。

  4. 由于它们是不同的对象,任何相等运算符将返回false

  5. 然而,由于工作的方式不及大于工作,他们被转换成string(然后到数字)进行比较。 根据第3点,这是相同的价值; 因此,它们不能小于或大于对方,导致false

最后,只要把你的脸上的笑容:

 b1 <= b2 //true b1 >= b2 //true 

已经有了一个可以接受的答案,但是我觉得我还是可以用一句话来形容,因为我没有find接受的答案,特别清楚或有帮助。 如果仅仅因为它回答了OP没有提出的问题,那甚至是不正确的。 所以让我们来看看:

 > var b1 = new Buffer([170]); > var b2 = new Buffer([171]); > b1 < b2 > b1 > b2 > b1 == b2 

所有要求的是:“我如何在缓冲区上执行等价和小于/大于比较(又名(全部)sorting)”。

答案是:

  • 要么通过跨过两个缓冲区的所有字节手动执行,并在相应的字节之间进行比较,例如b1[ idx ] === b2[ idx ]

  • 或使用Buffer.compare( b1, b2 )给你一个-1+1 ,这取决于第一个缓冲区是先sorting还是排在第二个之后(sorting包含缓冲区的列表d是那么就像d.sort( Buffer.compare )一样简单)。

观察我在第一个例子中使用=== 我在这个网站上对JavaScript滥用==频繁评论应该清楚地说明这是为什么。