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

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

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

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

HTML

HTMLとは、ウェブ上の文書を記述・作成するためのマークアップ言語のことです。文章の中に記述することで、文書の論理構造などを設定することができます。ハイパーリンクを設定できるハイパーテキストであり、画像・リスト・表などのデータファイルをリンクする情報に結びつけて情報を整理します。現在あるネットワーク上のほとんどのウェブページはHTMLで作成されています。

CSS

CSSはXMLやHTMLで表現した色・レイアウト・フォントなどの要素を指示する仕様の1つです。

Q&A

解決済

2回答

781閲覧

[JavaScript]変数の正しい(綺麗な)書き方について

yanju

総合スコア4

JavaScript

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

HTML

HTMLとは、ウェブ上の文書を記述・作成するためのマークアップ言語のことです。文章の中に記述することで、文書の論理構造などを設定することができます。ハイパーリンクを設定できるハイパーテキストであり、画像・リスト・表などのデータファイルをリンクする情報に結びつけて情報を整理します。現在あるネットワーク上のほとんどのウェブページはHTMLで作成されています。

CSS

CSSはXMLやHTMLで表現した色・レイアウト・フォントなどの要素を指示する仕様の1つです。

0グッド

1クリップ

投稿2021/04/26 10:08

前提・実現したいこと

お世話になります。
JavaScript初心者で見様見真似でコードを書いているのですが、グローバル変数・ローカル変数の使い方がよく分からなくなり質問させていただきます。

※コードの内容
『画面右下にnextボタンがありクリックすると下へスクロールします。
ページ最下部へ到達すると[class="line-back"]が追加されbackボタンに切り替わります。
backボタンをクリックすると最上部へスクロールします。
最上部へ到達するとnextボタンに戻ります。』

元々は画像2枚目のようにグローバル変数として上にまとめて宣言していました。
あとからこれらの変数を使い回したいからです。

ですが、最初の時点で[class="line-back"]が存在しないため(?)改めて矢印の位置で宣言する必要が出てきました。
結果的に下の「該当のソースコード」のような形になったのですが、[lineNext]はグローバル変数、[lineBack]はローカル変数となりそれがモヤモヤします。([lineBack]を別の場所で使う時はまた改めて同じ書き方で宣言するのか?等)

根本的な理解が欠けているような気がしますが、このコードの書き方は正しいでしょうか?
それとも、もっと綺麗な書き方はあるでしょうか?
イメージ説明
イメージ説明

該当のソースコード

javascript

1const profile = document.querySelector('.profile'); 2const lineNext = document.querySelector('.line-next'); 3 4// ページ下部でline-back、ページ上部でline-nextに変更 5profile.onscroll = function () { 6 const clientHeight = profile.clientHeight; 7 const scrollHeight = profile.scrollHeight; 8 const lineBack = document.querySelector('.line-back'); 9 if (scrollHeight - (clientHeight + this.scrollTop) == 0) { 10 lineNext.innerHTML = "<span>back</span>"; 11 lineNext.classList.add('line-back'); 12 } else if (this.scrollTop == 0 && lineBack) { 13 lineBack.innerHTML = "<span>next</span>"; 14 lineBack.classList.remove('line-back'); 15 } 16} 17// クリックで下または上にスクロール 18lineNext.addEventListener('click', function () { 19 if (lineNext.classList.contains('line-back')) { 20 profile.scrollTo({ 21 top: 0, 22 behavior: 'smooth' 23 }); 24 } else { 25 const viewHeight = window.innerHeight 26 profile.scrollBy({ 27 top: viewHeight, 28 behavior: 'smooth' 29 }); 30 } 31});

html

1<!DOCTYPE html> 2<html lang="ja"> 3<head> 4 <meta charset="utf-8"> 5 <title>@@@@@@@@ - @@@@@@@@@@@@@@</title> 6 <meta name="description" content="@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"> 7 <meta name="viewport" content="width=device-width, initial-scale=1"> 8 <link rel="stylesheet" href="https://unpkg.com/ress/dist/ress.min.css"> 9 <link href="https://fonts.googleapis.com/css2?family=Philosopher&display=swap" rel="stylesheet"> 10 <link rel="stylesheet" href="css/sub.css"> 11</head> 12<body> 13 <div class="container-2"> 14 <div class="guide"> 15 <div class="id-wrapper"> 16 <div class="face"> 17 <a href="index.html"><img src="https://source.unsplash.com/user/erondu/300x300" alt="face photo"></a> 18 </div> 19 <h1 class="name"><a href="index.html"><ruby>@@@@<rt>@@@@@@@@</rt></ruby> <ruby>@@@@<rt>@@@@@@</rt></ruby></a></h1> 20 </div> 21 <nav class="global-nav"> 22 <ul class="nav-menu"> 23 <li><a href="profile.html">profile</a></li> 24 <li><a href="works.html">works</a></li> 25 <li><a href="contact.html">contact</a></li> 26 </ul> 27 </nav> 28 </div> 29 <div class="container-right"> 30 <div class="profile"> 31 <div class="parallax img-01"> 32 <h2>Profile</h2> 33 <div class="white-wrapper"> 34 <p><span>@@ @@</span></p> 35 <p>@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@</p> 36 <p>@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@</p> 37 <p>@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@</p> 38 </div> 39 <a id="scroll" class="line-next" href="#"><span>next</span></a> 40 </div> 41 <div class="content-box">Hobby ×4</div> 42 <div class="parallax img-02"> 43 <h2>Photography</h2> 44 <div class="white-wrapper"> 45 <p></p> 46 <p></p> 47 <p>@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@</p> 48 <p>@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@</p> 49 <p>@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@</p> 50 </div> 51 </div> 52 <div class="parallax img-03"> 53 <h2>Hiking</h2> 54 <div class="white-wrapper"> 55 <p>@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@</p> 56 <p>@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@</p> 57 <p>@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@</p> 58 </div> 59 </div> 60 <div class="parallax img-04"> 61 <h2>Trip</h2> 62 <div class="white-wrapper"> 63 <p>@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@</p> 64 <p>@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@</p> 65 <p>@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@</p> 66 </div> 67 </div> 68 <div class="parallax img-05"> 69 <h2>Cooking</h2> 70 <div class="white-wrapper"> 71 <p>@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@</p> 72 <p>@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@</p> 73 <p>@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@</p> 74 <p></p> 75 </div> 76 </div> 77 </div> 78 </div> 79 </div> 80 <footer> 81 <p>&copy; @@@@@@@@@@@@@@ 2021</p> 82 </footer> 83 </div> 84 <script type="text/javascript" src="scripts/portfolio.js"></script> 85</body> 86</html>

css

1@charset "UTF-8"; 2/* container 3--------------------------------------------------------- */ 4.container-2 { 5 display: grid; 6 grid-template-columns: 8fr 26fr; 7 height: 100vh; 8 animation: fadeIn 3s ease 0s 1 normal; 9} 10@keyframes fadeIn { 11 from { 12 opacity: 0; 13 } 14 to { 15 opacity: 1; 16 } 17} 18.container-right { 19 background-color: #f6f6f6; 20 color: #024058; 21} 22/* profile 23--------------------------------------------------------- */ 24.profile { 25 height: 100vh; /* 原因と思われるheight */ 26 overflow: scroll; 27 scroll-snap-type: y mandatory; 28} 29.parallax { 30 height: 100%; 31 background-attachment: fixed; 32 background-position: calc(50% + calc(4 / 34 * 100vw)); 33 background-size: cover; 34 background-repeat: no-repeat; 35 scroll-snap-align: start; 36} 37.parallax h2 { 38 position: relative; 39 top: 15%; 40 font-family: "Quicksand"; 41 color:#fff; 42 font-size: 80px; 43 text-align: center; 44 text-shadow: 0px 0px 24px #262626; 45} 46.white-wrapper { 47 display: inline-block; 48 position: relative; 49 top: 20%; 50 left: 50%; 51 padding: 16px; 52 border: solid 1px #c0c0c0; 53 background-color: rgba(255,255,255,0.8); 54} 55.white-wrapper p { 56 color: #024058; 57} 58.white-wrapper p span { 59 font-size: 20px; 60} 61.content-box { 62 height: 100vh; 63 background: #f89174; 64 font-family: "Quicksand"; 65 font-size: 80px; 66 line-height: 100vh; 67 text-align : center; 68 scroll-snap-align: start; 69} 70.img-01 { 71 background-image: url(https://source.unsplash.com/user/erondu/1500x1000); 72} 73.img-02 { 74 background-image: url(https://source.unsplash.com/user/erondu/1400x1000); 75} 76.img-03 { 77 background-image: url(https://source.unsplash.com/user/erondu/1300x1000); 78} 79.img-04 { 80 background-image: url(https://source.unsplash.com/user/erondu/1200x1000); 81} 82.img-05 { 83 background-image: url(https://source.unsplash.com/user/erondu/1100x1000); 84} 85.line-next { 86 display: inline-block; 87 position: absolute; 88 right: 40px; 89 bottom: 40px; 90 width: 1px; 91 height: 100px; 92 background-color: #024058; 93 transition: all 1.0s; 94} 95.line-next::after { 96 content: ''; 97 display: block; 98 position: absolute; 99 left: 0; 100 width: 1px; 101 background-color: #fff; 102 animation: line-down 4s ease infinite; 103} 104@keyframes line-down { 105 0% { 106 bottom: 100px; 107 height: 0; 108 } 109 20% { 110 bottom: 0; 111 height: 100px; 112 } 113 40% { 114 bottom: 0; 115 height: 0; 116 } 117 100% { 118 bottom: 0; 119 height: 0; 120 } 121} 122.line-back { 123 display: inline-block; 124 position: absolute; 125 right: 40px; 126 bottom: 40px; 127 width: 1px; 128 height: 100px; 129 background-color: #024058; 130 transition: all 1.0s; 131} 132.line-back::after { 133 content: ''; 134 display: block; 135 position: absolute; 136 left: 0; 137 width: 1px; 138 background-color: #fff; 139 animation: line-up 4s ease infinite; 140} 141@keyframes line-up { 142 0% { 143 top: 100px; 144 height: 0; 145 } 146 20% { 147 top: 0; 148 height: 100px; 149 } 150 40% { 151 top: 0; 152 height: 0; 153 } 154 100% { 155 top: 0; 156 height: 0; 157 } 158} 159.line-next span { 160 font-family: "Quicksand"; 161 font-size: 12px; 162 writing-mode: vertical-rl; 163 animation: fadeIn 3s ease 0s 1 normal; 164} 165.line-back span { 166 position: absolute; 167 bottom: 0; 168 font-family: "Quicksand"; 169 font-size: 12px; 170 writing-mode: vertical-rl; 171 animation: fadeIn 3s ease 0s 1 normal; 172} 173/* guide 174--------------------------------------------------------- */ 175.guide { 176 display: grid; 177 grid-template-rows: 13fr 8fr; 178 place-items: center; 179 height: 100vh; 180} 181.id-wrapper { 182 max-width: 90%; 183} 184.face { 185 margin: 0 auto; 186 max-width: 240px; 187} 188.face img { 189 border-radius: 50%; 190} 191.name { 192 font-family: serif; 193 letter-spacing: 0.1em; 194 text-align: center; 195 ruby-position: under; 196} 197.name rt { 198 font-size: 8px; 199 letter-spacing: 1em; 200 opacity: 0.5; 201} 202.global-nav { 203 align-self: start; 204} 205.nav-menu a { 206 position: relative; 207 font-family: serif; 208 font-size: 24px; 209} 210.nav-menu a:hover { 211 opacity: 1; 212} 213.nav-menu a::after { 214 content: ""; 215 position: absolute; 216 bottom: -4px; 217 left: 0; 218 width: 100%; 219 height: 2px; 220 background-color: #fff; 221 transform: scale(0, 1); 222 transform-origin: center top; 223 transition: transform 250ms; 224} 225.nav-menu a:hover::after { 226 transform: scale(1, 1); 227} 228/* footer 229--------------------------------------------------------- */ 230footer { 231 position: fixed; 232 bottom: 1vh; 233 left: 1vw; 234} 235footer p { 236 font-family: serif; 237 font-size: 12px; 238 opacity: 0.7; 239} 240/* intersection 241--------------------------------------------------------- */ 242html { 243 font-size: 100%; 244} 245body { 246 font-family: "Helvetica Neue", Helvetica, Arial, "YuGothic", "Yu Gothic", "游ゴシック体", "游ゴシック", "ヒラギノ角ゴ ProN W3", "Hiragino Kaku Gothic ProN", "ヒラギノ角ゴ Pro W3", "Hiragino Kaku Gothic Pro", "メイリオ", "Meiryo", "MS ゴシック", "MS Gothic", sans-serif; 247 background-color: #024058; 248 color: #fff; 249 line-height: 1.7; 250 font-size: 16px; 251} 252a { 253 color: #fff; 254 text-decoration: none; 255} 256img { 257 max-width: 100%; 258} 259ul { 260 list-style: none; 261} 262* { 263 box-sizing: border-box; 264}

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

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

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

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

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

satokei

2021/04/26 10:36

lineNext と lineBack は同じ要素を指しているので、 そもそも lineBack は必要がないように思いました。
guest

回答2

0

ベストアンサー

lineNext と lineBack は同じ要素を指しているので、
そもそも lineBack は必要がないように思いました。

とコメントしたので、コード例です。

js

1const profile = document.querySelector('.profile'); 2const line = document.querySelector('.line-next'); 3 4// ページ下部でline-back、ページ上部でline-nextに変更 5profile.onscroll = function() { 6 const clientHeight = profile.clientHeight; 7 const scrollHeight = profile.scrollHeight; 8 const isBack = line.classList.contains('line-back'); 9 if (scrollHeight - (clientHeight + this.scrollTop) == 0) { 10 line.innerHTML = "<span>back</span>"; 11 line.classList.add('line-back'); 12 } else if (this.scrollTop == 0 && isBack) { 13 line.innerHTML = "<span>next</span>"; 14 line.classList.remove('line-back'); 15 } 16} 17// クリックで下または上にスクロール 18line.addEventListener('click', function() { 19 if (line.classList.contains('line-back')) { 20 profile.scrollTo({ 21 top: 0, 22 behavior: 'smooth' 23 }); 24 } else { 25 const viewHeight = window.innerHeight 26 profile.scrollBy({ 27 top: viewHeight, 28 behavior: 'smooth' 29 }); 30 } 31});

投稿2021/04/27 01:33

satokei

総合スコア1217

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

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

yanju

2021/04/27 08:04

satokeiさん、ありがとうございます。動作確認できました! 自分で試して返信するつもりでした。失礼しました。 const profile = document.querySelector('.profile'); const lineNext = document.querySelector('.line-next'); この2つがグローバル変数になってしまうのが気になっていたのですがそれは特に問題ないという認識で大丈夫でしょうか?
satokei

2021/04/27 09:06 編集

小さいコード量なら気にする必要はないと思いますし、const なので問題はでにくいかと。 とはいえ、グローバル変数を常に気にしていた方が安全だとは思います。
yanju

2021/04/27 14:55

支障が出そうなら都度対応していけばよいということですね! 今回はコード例までありがとうございました。
guest

0

DOMの形成を待ってから指定すればよいでしょう。

javascript

1window.addEventListener('DOMContentLoaded', ()=>{ 2 const lineBack=document.querySelector('.line-back'); 3}); 4

投稿2021/04/26 10:53

yambejp

総合スコア116724

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

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

yanju

2021/04/26 15:06

ありがとうございます! このような形でしょうか? const profile = document.querySelector('.profile'); const clientHeight = profile.clientHeight; const scrollHeight = profile.scrollHeight; const lineNext = document.querySelector('.line-next'); window.addEventListener('DOMContentLoaded', () => { const lineBack = document.querySelector('.line-back'); }); 下記のエラーが出てしまい、backからnextへ切り替わりませんでした。 『Uncaught ReferenceError: lineBack is not defined at HTMLDivElement.profile.onscroll』 認識が間違っていたらすみません。
yambejp

2021/04/27 00:09

全部addEventListenerのコールバックに突っ込んでください
yanju

2021/04/27 07:47

理解が追いついておらず申し訳ございません こういうことでしょうか? window.addEventListener('DOMContentLoaded', () => { const profile = document.querySelector('.profile'); const clientHeight = profile.clientHeight; const scrollHeight = profile.scrollHeight; const lineNext = document.querySelector('.line-next'); const lineBack = document.querySelector('.line-back'); }); こちらで試すと 『Uncaught ReferenceError: lineNext is not defined』というエラーになってしまいました。
yanju

2021/04/27 08:11

すみません、ようやく理解できました! JSファイルのコード全てをDOMの形成後に読み込ませるということですね。 これは実務などでよく使われるテクニックなのでしょうか?調べ方などあればぜひ教えてほしいです。
yambejp

2021/04/27 08:44

> これは実務などでよく使われるテクニックなのでしょうか? 私の知る限りよく使われるテクニックです。 ただし、動的に追加したHTML要素や、あとからつけたセレクタ(idやclassやカスタムデータほか) で指定するHTML要素はつかめないので、その場合は別の手段が必要です
yanju

2021/04/27 14:52

なるほど勉強になりました! また機会があればよろしくお願いします。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問