2017-11-08 21 views
1

私は既存のライブラリを調べていますが、オブジェクトに対する算術演算の使用について混乱しています。算術演算のために使用されているオブジェクトの算術演算

オブジェクトは、次のようになります。彼らはこのように使用されている

{ 
    _high: 0, 
    _low: 256, 
    remainder: { _low: 0, high: 0, remainder: null } 
} 

const id = { 
    _high: 0, 
    _low: 256, 
    remainder: { _low: 0, high: 0, remainder: null } 
}; 

while (id > 0) { 
    const remainder = Math.floor(id % 14); 
} 

質問:正確にどうなる

モジュロのような算術演算をオブジェクトに適用するか、数値と比較しますか?

可能であれば、特定のスニペットをオブジェクトプロパティを使用するものに書き換えます。

+0

のコメントを参照してください@NinaScholz。上の例のようなオブジェクトを返します。 – kentor

+0

@ NinaScholzそれはちょうど私の質問ですが、私はそれも得られませんが、それは動作します。自分でテストすることができます。 1つの数字(たとえば、_lowが0より大きい場合)がtrueの場合、falseを返すことに気付きました。 – kentor

+0

JavaScriptはオブジェクトを'.valueOf()'メソッドを呼び出して数値を返します。それは言語仕様の複雑な詳細で説明されています。 – Pointy

答えて

4

You Don't Know JS: types & grammar, chapter 4

オブジェクト(及びアレイ)は最初、そのプリミティブ値と等価に変換され、得られた値は、(既に数プリミティブではない場合)はToNumberに従って番号に強制されます今述べたルール。

ToPrimitive抽象オペレーション(ES5仕様、セクション9.1)は、問題の値(内部DefaultValueオペレーション-ES5仕様、セクション8.12.8を使用)を参照して、 valueOf()メソッドvalueOf()が利用可能でプリミティブ値を返す場合、その値は強制的に使用されます。そうでない場合、toString()は強制的な値を提供します(存在する場合)。

いずれの操作もプリミティブ値を提供できない場合は、TypeErrorがスローされます。


だから、私はあなたのオブジェクトは、あなたのオブジェクト上で実行されている両方の算術演算では、その方法は、数にオブジェクトを強制するために呼び出されるので、番号を返しvalueOf方法を持っていることを前提としています、結果として得られる値は操作で実際に使用される値です。


また、あなたの例では、それはその基礎となる valueOf方法、我々は id + 10ような何かをしようとすると、私たちは [object Object]10を取得し、理由があるが含まれていないので、かなり役に立たないのですか?デフォルトの valueOfがプリミティブを提供できないため、を返す toStringが参照され、そのプリミティブ値は 10と連結され、 [object Object]10になります。より良いこれらの例を見てみましょう、これを理解するには



1.

const id = { 
_high: 0, 
_low: 256, 
remainder: { _low: 0, high: 0, remainder: null }, 
valueOf: function(){ 
return 20; /* valueOf does not fail to provide a primitive, "20" will 
be used". */ 
}, 
toString: function() { 
return 10; /* toString's return value would be used (if it was a primitive), if "valueOf" failed to provide a primitive. */ 
} 
}; 


console.log(id + 10); // prints out "30" 


2.

const id = { 
_high: 0, 
_low: 256, 
remainder: { _low: 0, high: 0, remainder: null }, 
valueOf: function(){ 
return {}; // valueOf fails to provide a primitive 
}, 
toString: function() { 
return 10; // toString provides a primitive value, so "10" will be used. 
} 
}; 


console.log(id + 10); // prints out "20" 


3.

const id = { 
_high: 0, 
_low: 256, 
remainder: { _low: 0, high: 0, remainder: null }, 
valueOf: function(){ 
return {}; /* valueOf fails to provide a primitive */ 
}, 
toString: function() { 
return {}; /* toString fails to provide a primitive as well */ 
} 
}; 


console.log(id + 10); // a "TypeError" is thrown :(
1

答え:方法 。valueOf()は と呼ばれ、そこで独自のロジックを実装することができます。

var obj = { 
 
a: 11, 
 
b: 30, 
 
valueOf: function() { 
 
    return this.a + this.b; 
 
} 
 
} 
 

 
if (obj> 40) { 
 
    alert(obj + 1); 
 
}

+0

しかし、一般的にオブジェクトを文字列または数値にキャストすることに基づいてフローを構築することは悪い考えです。適切なロジックを、 'if(obj.isStillAlive())... 'のような明示的なメソッドに移動する方がはるかに優れています。 – skyboyer

+0

私は同意しますが、利点もあるでしょうか? OPのような混乱の欠点を取り除くもの。 – Taurus

+0

@Taurusは表示されません。新しいDate()+ 1000がDateオブジェクトではない数値を返すのは常に紛らわしいことです。 Array.prototype.sort()のデフォルトロジックが.toString()の代わりに.valueOf()を使用して要素を比較すると便利です。 しかし、残念ながらそれはそうではありません(たとえば、日付の配列は文字列表現でソートされています - したがって、すべての金曜日が最初に、すべての水曜日が最後です) – skyboyer