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

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

ただいまの
回答率

88.37%

フォームで受け取った数値は必ず文字列になる? 文字列を数値にする目的でevalを使用してはいけない?

解決済

回答 6

投稿

  • 評価
  • クリップ 1
  • VIEW 4,788

re97

score 208

あるコードで、フォームで受け取った数値を(数値にする目的でだと思うのですが)、evalしている箇所があるのですが、

eval(フォームで受け取った数値);

質問1
・フォームで受け取った数値は必ず文字列になるのでしょうか?


質問2
・仮にフォームで受け取った数値でなかった場合、数値にする目的で文字列をevalしても良いでしょうか?

typeof '100'; //"string"
typeof eval('100'); //"number"

質問3
・下記はどういう意味でしょうか?

算術式を評価する目的で eval() を呼び出してはいけません。JavaScript は算術式を自動的に評価します

日本語

Do not call eval() to evaluate an arithmetic expression; JavaScript evaluates arithmetic expressions automatically.

英語

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 6

+6

フォームで受け取った数値をeval()、質問3に関して

そんなコード使わないほうが良いでしょう。
eval()というのは引数に渡した値をJavaScriptコードとして動的に実行します
つまるところ、コードを書けば、それが実行できるということです。

もし、悪意のあるコードを記述すれば、(eval()した後にその値をどのように処理するかにもよりますが、処理によっては)重大なXSS脆弱性を生むことにもなります。

参考リンク  MDN eval()
https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/eval

input要素などに入力された値に対してJavaScriptで処理を行いたい場合はvalueを取得して…という方法で可能ですので、わざわざeval()する必要性は皆無です。

質問2に関して

JavaScriptのデータ型の書式について少し誤解があるのかもしれません。

'1' //クォーテーションで囲むと文字列です
1 //数値は何も囲いません


受け取った値に対して型変換したい場合は、それぞれ専用のメソッドがあります。eval()ではなくそれらを利用しましょう。
また、受け取った値が必ず文字列か?と言われると、同じように取得にどのような処理をしているかによって変わってきます。(ただ、型変換等は基本としてやるかな…?と思います。)

この辺りも一緒に確認されてみてはいかがでしょう?

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/04/04 11:36

    ・回答&リンク提示ありがとうございました
    ・型変換難しいですね…

    キャンセル

  • 2016/04/06 02:12 編集

    よくよく考えるとあまり質問への答えになっていませんでしたね…失礼いたしました。。

    型変換、理屈が分かると簡単なことだと思いますよ!
    ただ、この部分が曖昧だと算術の際に予期しないエラーをまねくのでその点だけ注意というところでしょうか。

    例えばJavaScriptの場合、文字列と数値を+(加算)すると数値が文字列に型変換されてしまうという特徴があります。(エラーにならない)
    なので
    var a = 'これは文字列';
    var b = 2;
    a + b = 'これは文字列2'

    になってしまいます。(加算ではなく文字列の連結)
    ここで、もし数値どうしの計算をさせたいのに、文字列扱いで数字を変数へ格納してしまうと、下記のようなことが起こります。
    var a = '3';
    var b = 2;
    console.log( a + b ) //32 (※string)

    本当ならば「5」という結果を欲しているのに、まったく違う答えが返ってきます。
    こういったことにならないように、(このケースなら)文字列をあらかじめNumber()等で型変換しておくと良い、くらいの感じかなと。

    キャンセル

  • 2016/04/06 11:48

    コメントありがとうございました

    キャンセル

+3

解決済みのようですが、やや誤解があるようなので補足します。
「フォームで受け取った値」を「input 要素ノードのプロパティを参照した場合」だとして、String 型に限定されてはいません。

  • input.value … String 型
  • input.valueAsNumber … Number 型
  • input.valueAsDate … Object 型 (new Date)
<input type="number" value="1">
<input type="date" value="2016-04-06">
<input type="text" value="2">

<script type="text/javascript">
'use strict';
console.log(typeof document.querySelector('input[type=number]').valueAsNumber); // "number"
console.log(typeof document.querySelector('input[type=date]').valueAsDate);     // "object"
console.log(Object.prototype.toString.call(document.querySelector('input[type=date]').valueAsDate));  // "[object Date]"
console.log(typeof document.querySelector('input[type=text]').valueAsNumber);   // "number"
</script>

Re:  re97 さん

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/04/06 12:07

    ・回答ありがとうございました

    ・「GETやPOSTで送信された数値を受け取った時点」では、常に文字列になる、という認識で合っているでしょうか?

    ・回答内容は、数値で送信したつもりでも異なる場合があるということ?
    それとも、「フォームで受け取った値」を「input 要素」へセットした場合(?)、Number型で受け取ることも可能ということでしょうか?

    ・valueAsNumberは、input要素にだけ適用可能なプロパティ?
    ・valueAsNumberのTypeにdoubleと書いてあったのですがどういう意味? 適用対象によってnumberにもなり得る?

    キャンセル

  • 2016/04/06 13:35 編集

    ・GETやPOSTで送信された値はサーバサイドで受け取るのでクライアントサイドJavaScriptでは受け取れません。JavaScriptで参照可能なのはDOM要素への参照だけです。
    ・valueAsNumberがinput要素ノード専用かは全ての要素ノードの仕様をみる必要があります。少なくない時間がかかると想われる為、その都度調べる事をお勧めします。
    ・double は浮動小数点数を指します。JavaScript では Number 型と同義と解釈して問題ありません。
    https://html.spec.whatwg.org/multipage/infrastructure.html#reflecting-content-attributes-in-idl-attributes

    キャンセル

  • 2016/04/07 10:58

    ・コメント&リンク提示ありがとうございました

    キャンセル

checkベストアンサー

+2

* 質問1 ・フォームで受け取った数値は必ず文字列になるのでしょうか?

はい。文字列です。 フォームのテキストボックスに 1 をいれた場合は "1" の文字列になります。

* 質問2 ・仮にフォームで受け取った数値でなかった場合、数値にする目的で文字列をevalしても良いでしょうか?

eval() の利用は避けるべきです。
文字列 -> 整数に変換するメソッドが javascript には存在しています。
- JavaScriptで文字列を数値に変換する:Number(), parseInt(), parseFloat() http://uxmilk.jp/11582

* 質問3 ・下記はどういう意味でしょうか?

算術式 (1 + 2) を計算する為に eval() を使う必要はありません。javascropt は算術式を計算する機能を持っているので。

  var a = eval(1 + 2);
でなく
  var a = 1 + 2;
とできるということです。
(eval は evaluate という単語(評価するという意味がある) の省略なので eval(1+2) という記述は不自然ではないが、こう書く必要はないということ)

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/04/04 11:31

    ・回答ありがとうございました
    ・参考になりました

    キャンセル

0

1.
フォームに入力される文字列が必ず数値とは限らないので、JavaScriptにかぎらず、ほとんどの言語
では普通は文字列として受け取ります。(例外もあるかもしれませんが。)

2.
(プログラムが動くという意味では)問題はないと思います。
ただし、JSは気をつけて実装しないと多くの脆弱性を生む可能性があるので、詳しくは、他の方の解答を参考にしてください。

3.
日本語がわかりづらいですね。英語の表現がわかりやすいです。算術式を引数にする使い方は推奨しないということでしょう。文字列を入れるべきということです。

Do not call eval() to evaluate an arithmetic expression

具体的にいうと、下記のような意味かと。

eval("2 + 2"); // 文字列だからOKeval("2");   // 文字列だからOK
× eval(2 + 2); // 算術式だからNG
×  eval(2)   // 2という数値(算術式)だからNG

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/04/03 15:03

    manabufukaiさんの解答を受けて、一部、脆弱性に関する記述を盛り込むよう加筆修正しました。

    キャンセル

  • 2016/04/04 11:38

    ・回答ありがとうございました

    >算術式を引数にする使い方は推奨しない
    ・参考になりました

    キャンセル

0

  1. 文字列になると思います。
  2. parseInt を使いましょう。
parseInt( '100', 10 ); // 100


3は、多分こういうことかなと。

var a = eval("2 + 2"); // 4
var b = 2 + 2; // 4

JavaScript の中でも特殊な立ち位置にある eval は避けれるなら避けて、それ以外解決方法がない場合に使用する、くらいにしておいたほうが良いと思います。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/04/04 11:32

    ・回答ありがとうございました
    ・参考になりました

    キャンセル

0

質問2に関して,JavaScript では昔から以下のような暗黙の型変換を利用したテクニックがあります。

var num_str = "100";
typeof num_str; // "string"

var num = num_str * 1;
typeof num; // "number"

var num2 = num_str - 0;
typeof num2; // "number"

数値を表す文字列に対して「*1」や「-0」のように算術を行うと,JavaScript では暗黙的に文字列を数値として扱う仕様となっています。「*1」や「-0」を使用すれば,数値の値自体は変化しないので,実質数値を表す文字列をそのまま数値として使用できます。ただし「+0」は使用できません。「+」は文字列の連結にも使用されるため,数値を表す文字列の方に影響されて「+0」とすると暗黙的に「0」の方が文字に変換されてしますからです。
また,他にも注意点があります。
1. 数値を表す文字列の中に数値以外の文字が含まれていないことを確認してから使用すること。数値以外の文字が含まれているとエラーとなります。
2. 算術式の評価順序によっては,正しく動作しないことがあるので,暗黙の型変換の仕様を正しく把握してから使用すること。

初心者が安易に使うべきものではないかもしれませんが,たまに見かけるので知っておいて損はないと思います。

あと,フォームで受け取った値を直接 eval() することは厳禁です。絶対やってはいけません。必ずといっていいほど脆弱性となります。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/04/10 10:21

    ・回答ありがとうございました

    >暗黙の型変換を利用したテクニック
    >他にも注意点があります
    ・初めて知りました
    ・こういう書き方も可能である以上、知っておかないと読めないと思いました
    ・参考になりました

    キャンセル

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

  • ただいまの回答率 88.37%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る