質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

Q&A

解決済

5回答

2369閲覧

Javascriptの厳密な比較演算子

uS_aito

総合スコア145

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

0グッド

0クリップ

投稿2019/08/08 02:21

前提・実現したいこと

Javascriptで比較演算を行う時、型変換を行わせず厳密な比較を行わせたいと思っています。
例として、文字列リテラル"2"と、数値リテラル1を比較させた場合、falseを出力させたいです。
下記はあくまで例です。このような比較演算子はないようです。

console.log("2" >== 1) # -> falseにしたい

発生している問題・エラーメッセージ

MDNを参照し、またChromeの開発者ツールのコンソールやNode.js(v9.8.0)で動作を確認してみたところ、等価演算子は厳密な演算子が用意されていますが、比較演算子は厳密なものが無いように見受けられます。

node

1> "2" >= 1 2true 3> "2" >== 1 4... # 入力待ちのままです

Chrome

1"2" >== 1 2VM488:1 Uncaught SyntaxError: Unexpected token =

試したこと

一つ前にtypeofを噛ませて、その上で比較するしか無いでしょうか。

node

1> a = "2" 2'2' 3> typeof a === typeof 1 && a >= 1 4false

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答5

0

ベストアンサー

不等号を含む比較で厳密比較する仕組みは、私が知る範囲にはありません。
対策は2つ考えられます。

対策1. 型変換を許容する

ECMAScriptはあらゆる場所で型変換が働くので、型変換ルールを覚えて許容するのが最もローコストだと思います。

対策2. 型を強制する

前提として、Number型が求められる変数に String 型が代入される状況が好ましくないと私は思います。
変数に求められるのがNumber型なら、どんな過程を辿ったとしても、必ずNumber型になるのが理想的です。

JavaScript

1const number = typeof foo === 'number' ? foo : NaN;

このように書けば、Number型以外をセットしようとした時には NaN 値か代入され、比較演算子の評価値は必ず false になります。

ECMAScriptでは、変数の初期化処理に干渉は出来ませんが、プロパティに干渉する事は出来ますので、適宜活用する事をお勧めします。

  • setterで型変換後にセットし、getterで値を返す
  • new Proxy で代入時に型変換する

組み合わせ方は様々ですが、私は「class + WeakMap + getter,setter」を好んで使っています。

さすがに、Number以外を禁止する型変換は実装したことがありませんが…。
場合によっては、TypeError で強制終了させることも視野に入ります。

JavaScript

1throw new TypeError(arg + ' is not a Number')

Re: uS_aito さん

投稿2019/08/08 03:49

think49

総合スコア18162

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

uS_aito

2019/08/08 04:56

ご回答いただきありがとうございます。 miyabi-sunさんの回答にもコメントさせていただきました通り、普段使用している言語と設計思想が異なるようですね。 型変換ルールの把握と許容について意識してみようと思います。 ご回答、ありがとうございました。
guest

0

想像どおりJavaScriptという動的型付け言語の思想の話で
>==という演算子は存在しません。

型変換を行わせず厳密な比較を行わせたいと思っています。

何がどうなって数字のStringと数値を衝突させなければならないのでしょうか?
こういう型が混入してしまうこと場面を考えた時、
基本的には以下の2パターンしか存在しえません。

  • ユーザーからの入力値

→ そもそも何入力してもString型だよね、型変換試みて文字列なら例外投げよう

  • Ajax等で受け取った後付のデータ

こういう所はしっかりバリデート掛けてからハンドリングしてやれば>==演算子が欲しいという場面には遭遇しません。
上流工程を見直しましょう…というのがベストプラクティスになります。


もしエンジニアの技量差が激しい職場であれば、
思い切ってJavaScriptを捨ててTypeScriptでやるという手もあります。

コーディングルールでAny型を使うな!!みたいなルールを作れば
String型とNumber型を比較しなければならないという場面にたどりつくことすらなくなります。

TypeScriptはフロントエンドの世界で結構人気があるので、
良いエンジニアを採用するためのアプローチにもなるでしょう。


それを踏まえた上で「やだやだバリデーションはめんどくさい!」というなら、
質問文のように一度噛ませるしかありません。
全体的にそのような形式になっているのであれば、関数作って対処という形になるでしょう。

関数名はシェルスクリプトに良い名称があったので持ってきました。

JavaScript

1const ge = (a, b) => 2 typeof a == "number" && 3 typeof b == "number" && 4 a >= b; 5const gt = (a, b) => 6 typeof a == "number" && 7 typeof b == "number" && 8 a > b; 9const le = (a, b) => 10 typeof a == "number" && 11 typeof b == "number" && 12 a <= b; 13const lt = (a, b) => 14 typeof a == "number" && 15 typeof b == "number" && 16 a < b; 17 18console.log(ge(3, 2)); // true 19console.log(ge("3", 2)); // false

投稿2019/08/08 02:57

miyabi-sun

総合スコア21158

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

uS_aito

2019/08/08 04:54

回答いただきありがとうございます。 > 想像どおりJavaScriptという動的型付け言語の思想の話で > `>==`という演算子は存在しません。 こちら承知しました。ありがとうございます。 > 何がどうなって数字のStringと数値を衝突させなければならないのでしょうか? 普段PythonやGolang、C++等の型指定があるか異なる型同士の比較を許さない言語を使用しているため、異なる型同士の比較が単純にエラーにならない場合、切り分けが面倒な事態が発生するのではないかと考えたためです。 例えばpythonの場合、例えばintが帰る関数を誤ってstrが帰ると思って使い、その結果を比較するif文があった場合はその時点でエラーが出ますので、問題がある箇所をif文の前までに特定できます。 一方でJavascriptではif文をスルーしてしまい、異常動作した場合に疑いをかける箇所がif文以降にまで広がってしまいます。調べてみたところ等価演算子は厳密な演算子が存在することがわかりましたが、比較には厳密な演算子が見つからなかったため、質問させていただきました。 > こういう所はしっかりバリデート掛けてからハンドリングしてやれば`>==`演算子が欲しいという場面には遭遇しません。 > 上流工程を見直しましょう…というのがベストプラクティスになります。 こちら承知しました。Javascriptにおいてはバリデーションを行うか、ご教授いただいたいずれかの手段をとることで対応していこうと思います。 回答いただきありがとうございました。
guest

0

~~ECMAScriptの>=の定義は、「左式 < 右式」の結果がtrueundefinedのときにfalse、そうでない時にはtrue、というものなので、左式にundefinedを返せればショートカットできます。
~~

If r is true or undefined, return false. Otherwise, return true.

ECMAScript® 2020 Language Specification

たとえば、以下のとおり。

js

1a = "2"; 2( a.toFixed && a ) >= 1 3/* 4false 5*/ 6 7a = 2; 8( a.toFixed && a ) >= 1 9/* 10true 11*/

もちろん、可読性に問題があるとは思いますが。

投稿2019/08/08 05:01

編集2019/08/08 05:03
Lhankor_Mhy

総合スコア36115

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Lhankor_Mhy

2019/08/08 05:02

あ、間違えた。 しかも質問が終わっている……
uS_aito

2019/08/08 05:07

ご回答いただきありがとうございます。 すみません、予想以上に皆様からご協力をいただけたため、解決済みとさせていただきました。
guest

0

普通に関数化するのが早いでしょうね

javascript

1const dainariEqual=(a,b)=>typeof a===typeof b?a>=b:false; 2console.log(dainariEqual(2,1)); 3console.log(dainariEqual("2","1")); 4console.log(dainariEqual("2",1));

投稿2019/08/08 03:28

yambejp

総合スコア114839

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

一つ前にtypeofを噛ませて、その上で比較するしか無いでしょうか。

parseInt()するというのもありです。
型変換してしまっていて要件に合わないので削除。スルー願います。

投稿2019/08/08 02:26

編集2019/08/08 02:37
m.ts10806

総合スコア80850

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

maisumakun

2019/08/08 02:34

それだと逆に、「形を揃えて比較する」ということになってしまいませんか?
m.ts10806

2019/08/08 02:36

なってしまいますね。安易でした。 質問に提示されているtypeof で良さそうです。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問