🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
JavaScript

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

Q&A

解決済

3回答

767閲覧

letとvarの変数を定義する位置について。

hiroro0820

総合スコア13

JavaScript

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

0グッド

0クリップ

投稿2021/03/13 05:49

javascriptについてN予備校で学んでいます。
始めたばかりの初心者です。

いま、名前を入力すると、性格診断結果が表示されるというものを作っていて
jsのコードは下記になっています。

assesment.js

1'use strict'; 2const answers= [ 3 '{userName}のいいところは声です。{userName}の特徴的な声は皆を惹きつけ、心に残ります。', 4 '{userName}のいいところはまなざしです。{userName}に見つめられた人は、気になって仕方がないでしょう。', 5 '{userName}のいいところは情熱です。{userName}の情熱に周りの人は感化されます。', 6 '{userName}のいいところは厳しさです。{userName}の厳しさがものごとをいつも成功に導きます。', 7 '{userName}のいいところは知識です。博識な{userName}を多くの人が頼りにしています。', 8 '{userName}のいいところはユニークさです。{userName}だけのその特徴が皆を楽しくさせます。', 9 '{userName}のいいところは用心深さです。{userName}の洞察に、多くの人が助けられます。', 10 '{userName}のいいところは見た目です。内側から溢れ出る{userName}の良さに皆が気を惹かれます。', 11 '{userName}のいいところは決断力です。{userName}がする決断にいつも助けられる人がいます。', 12 '{userName}のいいところは思いやりです。{userName}に気をかけてもらった多くの人が感謝しています。', 13 '{userName}のいいところは感受性です。{userName}が感じたことに皆が共感し、わかりあうことができます。', 14 '{userName}のいいところは節度です。強引すぎない{userName}の考えに皆が感謝しています。', 15 '{userName}のいいところは好奇心です。新しいことに向かっていく{userName}の心構えが多くの人に魅力的に映ります。', 16 '{userName}のいいところは気配りです。{userName}の配慮が多くの人を救っています。', 17 '{userName}のいいところはその全てです。ありのままの{userName}自身がいいところなのです。', 18 '{userName}のいいところは自制心です。やばいと思ったときにしっかりと衝動を抑えられる{userName}が皆から評価されています。' 19] 20/** 21 * 22 * @param {string} userName ユーザーの名前 23 * @return {string} 診断結果 24 */ 25function assessment(userName){ 26 let sumOfcarCode= 0; 27 //全文字のコード番号を取得して足し合わせる 28 for (let i=0; i<userName.length; i++){ 29 sumOfcarCode= sumOfcarCode+ userName.charCodeAt(i); 30 } 31 //文字コード番号を回答の数で割って添え字の数値を求める 32 const index= sumOfcarCode% answers.length; 33 let result= answers[index]; 34 result= result.replace(/\{userName\}/g, userName); 35 return result.replace(/\{userName\}/g, userName); 36} 37//テストコード 38console.assert( 39 assessment('太郎')=== 40 '太郎のいいところは決断力です。太郎がする決断にいつも助けられる人がいます。', 41 '診断結果の文言の特定の部分を名前に書き換える処理が正しくありません' 42); 43console.assert( 44 assessment('太郎')=== 45 assessment('太郎'), 46 '入力が同じ名前なら同じ診断結果を出力する処理が正しくありません。' 47);

この時、質問なのですが

function assessment(userName){ let sumOfcarCode= 0; //全文字のコード番号を取得して足し合わせる for (let i=0; i<userName.length; i++){ sumOfcarCode= sumOfcarCode+ userName.charCodeAt(i); } //文字コード番号を回答の数で割って添え字の数値を求める const index= sumOfcarCode% answers.length; let result= answers[index]; result= result.replace(/\{userName\}/g, userName); return result.replace(/\{userName\}/g, userName); }

assessment関数内で定義されてる、sumOfcarCodeを関数外に出して、
下記のように定義すると、エラーが起こってしまうようです。

var sumOfcarCode= 0; function assessment(userName){ //全文字のコード番号を取得して足し合わせる for (let i=0; i<userName.length; i++){ sumOfcarCode= sumOfcarCode+ userName.charCodeAt(i); } //文字コード番号を回答の数で割って添え字の数値を求める const index= sumOfcarCode% answers.length; let result= answers[index]; result= result.replace(/\{userName\}/g, userName); return result.replace(/\{userName\}/g, userName); }

letとvarのスコープが関係ありそうな気がするのですが、
なぜエラーになるのでしょうか。。。

エラー内容は下記です。

Assertion failed: 入力が同じ名前なら同じ診断結果を出力する処理が正しくありません。 (anonymous) @ assesment.js:44

初心者なので右も左もわかりませんが、
よろしくお願いします。

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

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

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

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

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

guest

回答3

0

以下のテストコードで同じ名前の時に同じ出力が行われているか?というチェックを行っています。

javascript

1console.assert( 2 assessment('太郎')=== 3 assessment('太郎'), 4 '入力が同じ名前なら同じ診断結果を出力する処理が正しくありません。' 5);

関数内にあった初期化用の記述var sumOfcarCode= 0;
こちらを関数の外に出してしまったので初期化が行われず、同じ名前なのに同じ結果にならない、
つまり「テスト失敗、バグがあります」という注意書きが表示されるということになります。

varやletのスコープが原因ではなくて、デバッグ用のテストコードが正常に働いているという証拠です。

投稿2021/03/13 06:16

退会済みユーザー

退会済みユーザー

総合スコア0

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

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

hiroro0820

2021/03/13 06:50

回答していただいて、ありがとうございます。 すっきり解決しました!!
guest

0

ベストアンサー

関数の外に出すと、sumOfcarCode0を代入するのが関数実行前に1度だけなので、関数を呼ぶ度に累積していきますよ。
関数呼び出しの都度、0を代入する必要があるかと。

スコープとはまた別の話です。

投稿2021/03/13 06:10

編集2021/03/13 06:11
otn

総合スコア85882

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

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

hiroro0820

2021/03/13 06:52

回答していただき、ありがとうございます。 関数を呼び出す都度、0を代入しなきゃならなかったんですね! なるほど、、すっきりしました。。。 また、わからないことがでてきたら、教えていただけると嬉しいです!!
otn

2021/03/13 07:16

> 関数を呼び出す都度、0を代入しなきゃならなかったんですね! 理解がずれている気がします。 「正しいタイミングで、0を代入しないといけない」です。
hiroro0820

2021/03/13 12:23 編集

1度だけ関数を呼び出した時は、どちらも結果は同じだけど 0を代入する処理が外にある場合 二度目に、関数を呼び出した時は、0を代入する処理が行われないため 1度目で使われたsumOfcarCodeを元に、 sumOfcarCode= sumOfcarCode+ userName.charCodeAt(i); を行うから、sumOfcarCodeが累積していく っていう理解であってますか??
otn

2021/03/13 12:26

はい。そうです。
guest

0

//全文字のコード番号を取得して足し合わせる

ためにsumOfcarCode変数をおいています。
その目的のためにはassessmentが呼ばれるたびにsumOfcarCodeの初期値が0である必要があります。

うまく行かない方のコードは2回めのassessmentを呼び出して、forループ開始時にsumOfcarCodeの値が1回目の呼び出し時の結果のままになっています。そこに更に足し合わせるので結果が合わなくなっています。

つまりうまく行かない方のコードは、定義を外に出したからうまく行かないというよりは、
forループの前に初期化されていないのが原因です。

投稿2021/03/13 06:08

編集2021/03/13 06:11
ozwk

総合スコア13551

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.36%

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

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

質問する

関連した質問