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

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

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

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

Q&A

解決済

5回答

8427閲覧

3と3の倍数はアホと叫ぶようにしたい

haruniku

総合スコア527

JavaScript

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

1グッド

7クリップ

投稿2018/03/18 13:00

編集2018/03/18 13:50

いつもお世話になっております。
javascript初心者です。

現在、3と3の倍数になったときに「AHO!」と叫ぶプログラミングを作成しております。
やりたいことは至ってシンプルでブラウザ上で1ずつカウントアップされていく中で
3と6と9に到達したときに「AHO!」と表示させたいです。
3と6と9に到達したときにイベント起こす為に条件分岐作成したのですが、上手く作動していないのが現状です。

ご教示の程、宜しくお願いします。

<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>3と3の倍数はアホと叫ぶ</title> <script type="text/javascript"> var suuji = ["1","2","3","4","5","6","7","8","9","10"]; var aaa = 0; var bbb = setInterval(start, 1000); function start() { if (aaa < 10) { document.write(suuji[aaa] + " "); aaa++; }else{ clearInterval(bbb); // タイマー停止        document.write("AHO!"); } } </script> </body> </html>

試してみたこと①

var aaa = 0;の部分を3/0にしてみるも「AHO!」としか表示されず。

試したこと②

if (aaa < 10) { document.write(suuji[aaa] + " "); aaa++; }else if(aaa == 3){ document.write("AHO!"); }else{ clearInterval(bbb); } 3に到達したときにイベント起こすように条件分岐追加してみるも動きが停止してしまいました。
de9👍を押しています

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

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

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

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

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

kei344

2018/03/22 00:32

まだ質問が「受付中」になっていますが、いったん「解決済」にされてはいかがでしょうか。また、解決されていないなら状況を質問文に追記ください。
guest

回答5

0

ベストアンサー

まず、今回の質問文の改良点的な所が幾つか見受けられます。

  • document.writeは非推奨なのでやめよう
  • 数字がアホになるか否かの判定ロジックは関数として切り分けよう
  • 数字を入れるとアホ、もしくは数字を返すロジックも関数として切り分けよう
  • タイマー機能を改良しよう

document.writeは非推奨なのでやめよう

document.writeはJavaScript(以下JS)黎明期の書き方ですが、
これは様々な箇所で不具合が出るダメな子です。
結果、どのJSの書籍でも「document.write」は使うな!と明記される程嫌われている機能なので忘れてください。

DOMツリー構造を動的に変更するやり方を覚えましょう。
jQueryというライブラリを扱うのが初心者にはオススメです。
jQueryのDOMを挿入を覚えてください。

この反映は質問者さんへの課題として残しておきます。

従って、今回の回答文ではconsole.logとデベロッパーツールによる簡易的な表示方法を利用していきます。
F12キーを押すと、デベロッパーツールが立ち上がります。
console.log(123)という風に実行すると、デベロッパーツールのconsoleタブに結果を出力してくれます。


数字がアホになるか否かの判定ロジックは関数として切り分けよう

3の倍数でアホになる判定ロジックは関数として外部に切り出してください。
関数にしてしまえば、結果の確認がとても楽になりますよ。

isナベアツです!
numという数値の引数を要求しており、アホになりそうだったらtrue
普通の回答で数字を教えてくれそうならfalseになります。

JavaScript

1var isNabeatsu = function (num) { 2 return num % 3 === 0; 3} 4console.log(isNabeatsu(1)); // false 5console.log(isNabeatsu(2)); // false 6console.log(isNabeatsu(3)); // true 7console.log(isNabeatsu(4)); // false 8console.log(isNabeatsu(5)); // false 9console.log(isNabeatsu(6)); // true

よしよし、うまく動作しているようですね。
ですが、これはまだ3の倍数だけで判定するので、肝心の13や23等で反応しなさそうです。

JavaScript

1var isNabeatsu = function (num) { 2 return num % 3 === 0; 3} 4console.log(isNabeatsu(13)); // false 5console.log(isNabeatsu(23)); // false 6console.log(isNabeatsu(31)); // false

あらら、全滅です…
では、これを改良して完成させましょうか。
「数字の3が含まれている場合はfalseではなくtrueになる」が条件です。

この数字の3を探す…といった風な用途は「文字列検索」といいます。
JSには数値型や文字列型、配列、オブジェクト…など、様々な型が存在します。
それらの型には値を加工するのに使う便利な機能(メソッド)が用意されています。

先程3の倍数か否かを確認する為に、num % 3と入力しましたね。
数値型は数値計算に利用される型であり、他の型では数値計算は不可能です。
でも数字の3を探したい……こういう要望は文字列型が得意とする仕事なので数値型から文字列型へ変換(キャスト)する必要があります。

プログラマのテクニックの一つとして、数値として判断出来る値は基本的には数値型として所持しておき、
文字列検索がしたくなったらその時だけ、文字列型にキャストする使い方が分かりやすくオススメです。

今回はString.prototype.matchを利用することにしました。
正規表現を使って文字列を探す少々高難度の手法ですが、3という文字列を探すだけの正規表現は/3/とわりと簡単なので採用しました。
(他にも様々な方法で解決することが可能で、10人に頼めば10人共がちょっとずつ違う判定ロジックを持ってくると思います。探してみてね!!)

JavaScript

1// 文字列検索を行うmatchメソッドは文字列型限定のメソッド 2var num = 123; 3num.match(/3/); 4// Uncaught TypeError: num.match is not a function 5 6// JSでは.toString()を使えば全ての値が文字列型にキャストされる 7num.toString().match(/3/); 8// ["3", index: 2, input: "123", groups: undefined] 9 10// 値をカッコで包んだりしてそのまま.toString()で文字列型にして使うことも可能 11(17).toString().match(/3/); 12// null 13 14// 論理型にキャストするにはBooleanを使う 15Boolean((31).toString().match(/3/)); 16// true 17Boolean((16).toString().match(/3/)); 18// false

これを元にisナベアツ関数を完成させましょう。
「3で割り切れる数字」もしくは「数字の3がある」場合ですので、
論理和であるor演算子||を利用します。

JavaScript

1var isNabeatsu = function (num) { 2 return (num % 3 === 0) || Boolean(num.toString().match(/3/)); 3} 4console.log(isNabeatsu(1)); // false 5console.log(isNabeatsu(2)); // false 6console.log(isNabeatsu(3)); // true 7console.log(isNabeatsu(13)); // true 8console.log(isNabeatsu(23)); // true 9console.log(isNabeatsu(31)); // true 10console.log(isNabeatsu(25)); // false

いい感じに動作してますね。
isナベアツ関数完成です。


数字を入れるとアホ、もしくは数字を返すロジックも関数として切り分けよう

今度はtoナベアツ関数を作成しましょうか。
これも切り分ける事でテストが非常にしやすくなります。

もうアホになるべき数字か否かを判定する関数は出来ていますね?
今回は「特定条件でAHO!」か「そうでなければ数字をそのまま使う」ので、三項演算子を使ってみましょうか。
ついでに、AHO!という文字列が返ってくる可能性がある以上、もう片方の数字も文字列型にキャストして同じ文字列型に合わせておいたほうが使いやすそうですね。

JavaScript

1var isNabeatsu = function (num) { 2 return (num % 3 === 0) || Boolean(num.toString().match(/3/)); 3} 4var toNabeatsu = function (num) { 5 return isNabeatsu(num) ? 'AHO!' : num.toString(); 6} 7console.log(toNabeatsu(1)); // 1 8console.log(toNabeatsu(2)); // 2 9console.log(toNabeatsu(3)); // AHO! 10console.log(toNabeatsu(13)); // AHO! 11console.log(toNabeatsu(23)); // AHO! 12console.log(toNabeatsu(31)); // AHO!

はい完了。
このように同じ数字を入れると、必ず同じ値が返ってくるような処理は関数化しておくと、
このように動作確認が楽ですね。


早速これを質問文に組み込みましょう。
suuji変数に入っている配列を全て消化したら完了というロジックに変更しています。

JavaScript

1var isNabeatsu = function (num) { 2 return (num % 3 === 0) || Boolean(num.toString().match(/3/)); 3} 4var toNabeatsu = function (num) { 5 return isNabeatsu(num) ? 'AHO!' : num.toString(); 6} 7var suuji = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; 8var aaa = 0; 9var bbb = setInterval(start, 1000); 10 11function start() { 12 // 表示したい文字列は今回はconsole.logを使って表示 13 console.log(toNabeatsu(suuji[aaa])); 14 aaa++; 15 if (aaa >= suuji.length) { 16 clearInterval(bbb); // タイマー停止 17 } 18} 19// 1 20// 2 21// AHO! 22// 4 23// 5 24// AHO! 25// 7 26// 8 27// AHO! 28// 10

1秒おきにconsole.logが実行されて、表示されていく様が分かります。
10秒後に数字の値が全て表示されて、これで完了ですね。


【おまけ】

タイマー機能を改良しよう

見事動くようになりましたが、
関数はともかく、このsuujiaaabbbがキモいんですよねぇ……
何がキモいって、start関数の中から決め打ちで読みにいってるあたりです。

こういう変数は「状態変数」といって、
出来るだけ減らした方がかっこいいのです。

そのためのテクニックはいくつかありますが、今回は2つ加えます。

  • ループの仕組みをsetTimeoutを使った再起ループ化
  • start関数は引数の配列を監視して続けるかやめるか選ぶように

JavaScript

1var isNabeatsu = function (num) { 2 return (num % 3 === 0) || Boolean(num.toString().match(/3/)); 3} 4var toNabeatsu = function (num) { 5 return isNabeatsu(num) ? 'AHO!' : num.toString(); 6} 7var start = function (numbers) { 8 if (numbers[0] == null) return; 9 console.log(toNabeatsu(numbers[0])); 10 setTimeout(start.bind(null, numbers.slice(1)), 1000); 11} 12start([1, 2, 3, 4, 5, 6, 7, 8, 9, 10,]); 13// 1 14// 2 15// AHO! 16// 4 17// 5 18// AHO! 19// 7 20// 8 21// AHO! 22// 10

全ての関数にはfunction.prototype.bindというメソッドが用意されています。
まぁ、要するに関数に値を適用しつつ、実行しないで待ってくれるという必殺技があるんです。

JavaScript

1var add = function (a, b) { return a + b; } 2add(2, 3); 3// 5 4 5var add10 = add.bind(null, 10); 6add10(5); 7// 15

更に配列にはarray.prototype.sliceという配列の一部を切り出すメソッドがあります。
これを利用して金太郎アメのようにnumbers変数の関数を頭から1個ずつ削り取って利用する作りにしています。

JavaScript

1[1, 2, 3].slice(1) 2// [2, 3] 3 4[1, 2, 3].slice(1).slice(1) 5// [3]

全体的な流れとしてはこうです。

  • [1, 2, 3 ...]という配列がnumbersに入って実行
  • 先頭の1を取り出す
  • [1, 2, 3 ...].slice(1)を実行して、得た結果[2, 3 ...]を次のstartに格納しておく
  • 1秒後、次のstartが実行、今度は先頭の2を取り出す
  • これを繰り返し、最終的に空の配列[]を次のstartに格納
  • 1秒後、次のstartが実行、先頭のアイテムが無いので終了

投稿2018/03/18 14:58

編集2018/03/19 16:38
miyabi-sun

総合スコア21145

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

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

haruniku

2018/03/18 16:04 編集

親切ご丁寧に回答頂きありがとうございます。 私がやろうとしていたことがこんなに難しかったとは全然思っておりませんでした。 最後まで読みましたが、途中からチンプンカンプンになってきました(>_<) ただ、私みたいなど素人の為に1からご丁寧に解説して頂きとても嬉しいです。 しっかりとロジックを理解して一人前のエンジニアになるために頑張っていきたいと思います。 ありがとうございました!
miyabi-sun

2018/03/18 23:37

たまたま思いついたのがsplitなのですが、可読性的に考えてよろしくなかったですね。 情報提供ありがとうございます。 includesは非常に便利でドンピシャだと思うのですが、 今回のコードは意図的にES5を使っているのでincludesを使うと利用出来なくなってしまいます。 なのでindexOfですかね…それに差し替えようと思います。
miyabi-sun

2018/03/19 01:30

> 私がやろうとしていたことがこんなに難しかったとは全然思っておりませんでした 深夜のノリで書いたので、 中級者が1行で済ます横着テクニックを結構使ってます。 時間が出来たら平易なコードに修正したいなぁと考えています。 全体的なコードの動きは変わりませんので、デベロッパーツール等を駆使しながら1行ずつ打ち込んで確かめてみてください。
dodox86

2018/03/19 16:50

横からすみません。このまま読み物として完成しそうです。すばらしいです。>miyabi-sun
defghi1977

2018/03/20 02:31

確かに満遍なく多彩なテクニックが必要となるのでJavaScript入門記事として適していますね.
think49

2018/03/20 15:29

> 「数字の3が含まれている場合はfalseではなくtrueになる」が条件です。 この条件はどこから出てきたものでしょうか。 質問文には「3と3の倍数になったとき」とありますが、「文字列の3が含まれる場合」の条件が見つからず。 「世界のナベアツ」ネタで条件を加えてる…? http://anohitoha-ima.main.jp/post-534/
defghi1977

2018/03/21 02:51

>「文字列の3が含まれる場合」の条件 多分私のコードに尾ひれが付いてしまったのでしょう. 「3と3の倍数にaho」というパワーワードからナベアツが頭に浮かんで夜中のノリでコードを載せたら, 実は条件はもっと緩やかだったという.
miyabi-sun

2018/03/22 00:39

> 3と3の倍数になったとき ホントだ!騙された!!! > think49さん、defghi1977さん ありがとうございました。 騙されてました(´・ω・`)
think49

2018/03/22 04:42

To: defghi1977 さん、miyabi-sun さん 当初は質問者がコメント等で条件に言及している可能性を考えていました。 誤解が解けて良かったです。
defghi1977

2018/03/22 05:09

コードを載せた後に気が付いて, どうしようか迷っていたところにmiyabi-sunさんが後に続いて回答なさったために, おおぅどうすべえ…でも十分条件は満たしているから良いかな―と.(私の方で一言コメント残しとけばよかったですね)
guest

0

例えばこんな

HTML

1<output id="out" style="white-space:pre;"></output> 2<script> 3"use strict"; 4{ 5 let i = 0; 6 const max = 100, h = setInterval(() => { 7 let result = ++i % 3 == 0 || i.toString().match(/3/) ? "aho!" : i; 8 out.value += `${result}\n\r`; 9 if(i >= max){ 10 clearInterval(h); 11 } 12 }, 1000); 13} 14</script>

NOTE:
当初はdocument.writeを使っていましたが, FireFoxにおいてsetIntervalによる非同期処理と相性が悪かったため, 出力先を変更しています.

投稿2018/03/18 13:31

編集2018/03/18 15:34
defghi1977

総合スコア4756

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

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

haruniku

2018/03/18 13:51

回答ありがとうございます。 ごめんなさい、この書き方はjavascript以外の書き方でしょうか?
defghi1977

2018/03/18 13:53

これは完全なJavaScriptですが?
miyabi-sun

2018/03/18 15:13

紛れもないJavaSceiptですね。 この回答文では、ES2015という下位互換を残しながら、 他の人気言語の構文をいくつも取り入れた新しいバージョンの書き方を利用しています。 初めての人は面食らうかと思いますが、IE11以外のブラウザの殆どは対応しており普通に使えます。 実際に試してみて下さい。
defghi1977

2018/03/18 15:32

この手の質問だと大抵回答がコードの大喜利になってしまうので, このような記述の方法もあるよ程度に色々調べてみて下さい.
haruniku

2018/03/18 15:48

回答ありがとうございます。 そうだったんですね、ごめんなさい(>_<) 仰る通りに色々調べてみます。
guest

0

余計なお世話かもしれませんが、文字列比較を使わないバージョンも載せておきます。
ご参考にしてください。

html

1<!doctype html> 2<html> 3 <head> 4 <meta charset="utf-8"> 5 <title></title> 6 <script type="text/javascript"> 7window.onload = function() { 8 function aho(x) { 9 if (x % 3 == 0) 10 return true; 11 while (x > 0) { 12 if (x % 10 == 3) 13 return true; 14 x = Math.floor(x / 10); 15 } 16 return false; 17 } 18 var p = document.getElementById('number'); 19 var x = 1; 20 function update() { 21 p.innerHTML += aho(x) ? 'AHO!' : x; 22 p.innerHTML += '<br>'; 23 x++; 24 } 25 setInterval(update, 100); 26}; 27 </script> 28 </head> 29 <body> 30 <p id="number"></p> 31 </body> 32</html>

投稿2018/03/20 13:43

退会済みユーザー

退会済みユーザー

総合スコア0

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

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

0

javascript

1 2for (var i = 1; i < 11) { 3 if (i % 3 === 0) { 4 document.write("AHO!"); 5 } else { 6 document.write(i); 7 } 8}

投稿2018/03/18 13:21

退会済みユーザー

退会済みユーザー

総合スコア0

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

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

haruniku

2018/03/18 13:53 編集

回答ありがとうございます。 ごめんなさい、これだと単にコンソールで表示されるだけでわたしのやりたい事とは少し違います。 私のやりたいことはブラウザ上で1ずつカウントアップしていく中で3と3の倍数に到達したときにイベントを起こしたいです。
退会済みユーザー

退会済みユーザー

2018/03/18 15:35 編集

ヒントを出しているだけです。 全部書いたら、あなたのやることなくなっちゃうじゃん。
haruniku

2018/03/18 16:27 編集

カウントアップの処理方法はどうすればよろしいでしょうか? ヒントを頂けるとありがたいです(>_<)
defghi1977

2018/03/18 22:06

to harunikuさん 「カウントアップ」が意図するところ(何をどうしたいのか)が明らかとなっていない点と「イベント」の言葉の使い方がJavaScript本来の意味と異なる点でこれ以上答えることが出来ない(答える意味がない)のですよ.
x_x

2018/03/20 04:19

要件を半分しか満たしていないとはいえ、これで複数の低評価がつく理由を知りたい。
退会済みユーザー

退会済みユーザー

2018/07/11 08:53

> x_x さん 要件を満たしていないとは実は考えていません。 「3と3の倍数」って=「3の倍数」でしょ? 「3がつくとき」という「ナベアツ」と要件が異なってますから。
guest

0

注: document.write は文書ストリームに書き込みを行うため、閉じられた(ロード済みの)文書で document.write を呼び出すと、自動的に document.open が呼ばれ、文書はクリアされます

document.write - Web API インターフェイス | MDN

投稿2018/03/19 01:59

Lhankor_Mhy

総合スコア35813

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.51%

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

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

質問する

関連した質問