23

私はNode.jsが初めてです。バッファ比較はありません 。これらの機能にはbuffertoolsなどのモジュールを使用する必要があります。

しかし、純粋な Node.js で 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

ボンネットの下で実際に何が起こっているのですか?

4

2 に答える 2

41

これが、比較演算子がオブジェクトに対して機能する方法です。

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:比較は反撃します

ここに興味深い部分があります。<関係演算子(および>がどのように定義されているかを見てみましょう。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()
'�'

さて、それは役に立ちませんでした。<抽象関係比較アルゴリズム(の大きな名前)には、文字列を処理するためのステップがあることに気付くでしょう。それらを数値(charコード)に変換するだけです。そうしよう:

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

65533は重要な番号です。これは、2つの二乗の合計です142^2 + 213^2。また、「何が起こったのかわからない」という意味のUnicode置換文字でもあります。そのため、16進数に相当するものは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. バッファを作成しました。Benjamin Gruenbaumは、次のようにしてテストケースを再現するのを手伝ってくれました。

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

  2. コンソールに出力するとき、値は同等の16進数に変換されます(Buffer#inspectを参照)。

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

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

  3. ただし、内部的には、それらは無効な文字を表しています(16進エンコードではないため、繰り返しになりますが、実装の本質を自由に掘り下げることができます。皮肉なことに)。したがって、文字列に変換すると、Unicode置換文字で表されます。

  4. それらは異なるオブジェクトであるため、すべての等式演算子はを返しfalseます。

  5. ただし、作業の方法が少ないため、または大きいため、比較のために文字列(および数値)に変換されました。ポイント#3に照らして、それは同じ値です。したがって、それらを互いに小さくしたり大きくしたりすることはできず、になりfalseます。

最後に、あなたの顔に笑顔を置くために:

b1 <= b2 //true
b1 >= b2 //true
于 2013-03-24T01:11:43.537 に答える
9

すでに受け入れられた回答がありますが、受け入れられた回答が特に明確または役立つとは思わないので、私はまだ発言するほうがよいと思いました。OPが尋ねなかった質問に答えるという理由だけで、それは間違っています。それでは、それを要約しましょう:

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

求められるのは、「バッファーで同等性と比較 (別名 (合計) 順序付け) を実行するにはどうすればよいか」だけです。

答えは次のとおりです。

  • 両方のバッファのすべてのバイトをステップスルーして手動で行い、対応するバイト間の比較を実行しますb1[ idx ] === b2[ idx ]

  • またはBuffer.compare( b1, b2 )which を使用すると、最初のバッファーが 2 番目のバッファーの前、まったく同じ、または後にソートされるかどうかに応じて-1、 、0、またはのいずれかが得られます (バッファーを含むリストのソートは と同じくらい簡単です)。+1dd.sort( Buffer.compare )

===最初の例で使用していることを確認してください。JavaScriptでの の悪用に関するこのサイトでの私の頻繁なコメントは、==その理由を非常に明確にするはずです。

于 2015-04-21T15:46:46.490 に答える