diff options
author | Peter Bengtsson <mail@peterbe.com> | 2020-12-08 14:43:23 -0500 |
---|---|---|
committer | Peter Bengtsson <mail@peterbe.com> | 2020-12-08 14:43:23 -0500 |
commit | 218934fa2ed1c702a6d3923d2aa2cc6b43c48684 (patch) | |
tree | a9ef8ac1e1b8fe4207b6d64d3841bfb8990b6fd0 /files/zh-tw/learn/javascript/building_blocks | |
parent | 074785cea106179cb3305637055ab0a009ca74f2 (diff) | |
download | translated-content-218934fa2ed1c702a6d3923d2aa2cc6b43c48684.tar.gz translated-content-218934fa2ed1c702a6d3923d2aa2cc6b43c48684.tar.bz2 translated-content-218934fa2ed1c702a6d3923d2aa2cc6b43c48684.zip |
initial commit
Diffstat (limited to 'files/zh-tw/learn/javascript/building_blocks')
7 files changed, 2718 insertions, 0 deletions
diff --git a/files/zh-tw/learn/javascript/building_blocks/build_your_own_function/index.html b/files/zh-tw/learn/javascript/building_blocks/build_your_own_function/index.html new file mode 100644 index 0000000000..80b134992a --- /dev/null +++ b/files/zh-tw/learn/javascript/building_blocks/build_your_own_function/index.html @@ -0,0 +1,246 @@ +--- +title: 建立自己的功能函數 +slug: Learn/JavaScript/Building_blocks/Build_your_own_function +translation_of: Learn/JavaScript/Building_blocks/Build_your_own_function +--- +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenuNext("Learn/JavaScript/Building_blocks/Functions","Learn/JavaScript/Building_blocks/Return_values", "Learn/JavaScript/Building_blocks")}}</div> + +<p class="summary">通過前一篇文章中討論的大部分基本理論,本文提供了實踐經驗。 在這裡,您將學習構建自己的自定義功能函數。 在此過程中,我們還將解釋處理函數的一些有用細節。</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Prerequisites:</th> + <td>Basic computer literacy, a basic understanding of HTML and CSS, <a href="/en-US/docs/Learn/JavaScript/First_steps">JavaScript first steps</a>, <a href="/en-US/docs/Learn/JavaScript/Building_blocks/Functions">Functions — reusable blocks of code</a>.</td> + </tr> + <tr> + <th scope="row">Objective:</th> + <td>To provide some practice in building a custom function, and explain a few more useful associated details.</td> + </tr> + </tbody> +</table> + +<h2 id="Active_learning_Let's_build_a_function">Active learning: Let's build a function</h2> + +<p>The custom function we are going to build will be called <code>displayMessage()</code>. It will display a custom message box on a web page and will act as a customized replacement for a browser's built-in <a href="/en-US/docs/Web/API/Window/alert">alert()</a> function. We've seen this before, but let's just refresh our memories. Type the following in your browser's JavaScript console, on any page you like:</p> + +<pre class="brush: js">alert('This is a message');</pre> + +<p>The <code>alert</code> function takes a single argument — the string that is displayed in the alert box. Try varying the string to change the message.</p> + +<p>The <code>alert</code> function is limited: you can alter the message, but you can't easily vary anything else, such as the color, icon, or anything else. We'll build one that will prove to be more fun.</p> + +<div class="note"> +<p><strong>Note</strong>: This example should work in all modern browsers fine, but the styling might look a bit funny in slightly older browsers. We'd recommend you doing this exercise in a modern browser like Firefox, Opera, or Chrome.</p> +</div> + +<h2 id="The_basic_function">The basic function</h2> + +<p>To begin with, let's put together a basic function.</p> + +<div class="note"> +<p><strong>Note</strong>: For function naming conventions, you should follow the same rules as <a href="/en-US/Learn/JavaScript/First_steps/Variables#An_aside_on_variable_naming_rules">variable naming conventions</a>. This is fine, as you can tell them apart — function names appear with parentheses after them, and variables don't.</p> +</div> + +<ol> + <li>Start by accessing the <a href="https://github.com/mdn/learning-area/blob/master/javascript/building-blocks/functions/function-start.html">function-start.html</a> file and making a local copy. You'll see that the HTML is simple — the body contains just a single button. We've also provided some basic CSS to style the custom message box, and an empty {{htmlelement("script")}} element to put our JavaScript in.</li> + <li>Next, add the following inside the <code><script></code> element: + <pre class="brush: js">function displayMessage() { + +}</pre> + We start off with the keyword <code>function</code>, which means we are defining a function. This is followed by the name we want to give to our function, a set of parentheses, and a set of curly braces. Any parameters we want to give to our function go inside the parentheses, and the code that runs when we call the function goes inside the curly braces.</li> + <li>Finally, add the following code inside the curly braces: + <pre class="brush: js">var html = document.querySelector('html'); + +var panel = document.createElement('div'); +panel.setAttribute('class', 'msgBox'); +html.appendChild(panel); + +var msg = document.createElement('p'); +msg.textContent = 'This is a message box'; +panel.appendChild(msg); + +var closeBtn = document.createElement('button'); +closeBtn.textContent = 'x'; +panel.appendChild(closeBtn); + +closeBtn.onclick = function() { + panel.parentNode.removeChild(panel); +}</pre> + </li> +</ol> + +<p>This is quite a lot of code to go through, so we'll walk you through it bit by bit.</p> + +<p>The first line uses a DOM API function called {{domxref("document.querySelector()")}} to select the {{htmlelement("html")}} element and store a reference to it in a variable called <code>html</code>, so we can do things to it later on:</p> + +<pre class="brush: js">var html = document.querySelector('html');</pre> + +<p>The next section uses another DOM API function called {{domxref("Document.createElement()")}} to create a {{htmlelement("div")}} element and store a reference to it in a variable called <code>panel</code>. This element will be the outer container of our message box.</p> + +<p>We then use yet another DOM API function called {{domxref("Element.setAttribute()")}} to set a <code>class</code> attribute on our panel with a value of <code>msgBox</code>. This is to make it easier to style the element — if you look at the CSS on the page, you'll see that we are using a <code>.msgBox</code> class selector to style the message box and its contents.</p> + +<p>Finally, we call a DOM function called {{domxref("Node.appendChild()")}} on the <code>html</code> variable we stored earlier, which nests one element inside the other as a child of it. We specify the panel <code><div></code> as the child we want to append inside the <code><html></code> element. We need to do this as the element we created won't just appear on the page on its own — we need to specify where to put it.</p> + +<pre class="brush: js">var panel = document.createElement('div'); +panel.setAttribute('class', 'msgBox'); +html.appendChild(panel);</pre> + +<p>The next two sections make use of the same <code>createElement()</code> and <code>appendChild()</code> functions we've already seen to create two new elements — a {{htmlelement("p")}} and a {{htmlelement("button")}} — and insert them in the page as children of the panel <code><div></code>. We use their {{domxref("Node.textContent")}} property — which represents the text content of an element — to insert a message inside the paragraph, and an 'x' inside the button. This button will be what needs to be clicked/activated when the user wants to close the message box.</p> + +<pre class="brush: js">var msg = document.createElement('p'); +msg.textContent = 'This is a message box'; +panel.appendChild(msg); + +var closeBtn = document.createElement('button'); +closeBtn.textContent = 'x'; +panel.appendChild(closeBtn);</pre> + +<p>Finally, we use an {{domxref("GlobalEventHandlers.onclick")}} event handler to make it so that when the button is clicked, some code is run to delete the whole panel from the page — to close the message box.</p> + +<p>Briefly, the <code>onclick</code> handler is a property available on the button (or in fact, any element on the page) that can be set to a function to specify what code to run when the button is clicked. You'll learn a lot more about these in our later events article. We are making the <code>onclick</code> handler equal to an anonymous function, which contains the code to run when the button is clicked. The line inside the function uses the {{domxref("Node.removeChild()")}} DOM API function to specify that we want to remove a specific child element of the HTML element — in this case the panel <code><div></code>.</p> + +<pre class="brush: js">closeBtn.onclick = function() { + panel.parentNode.removeChild(panel); +}</pre> + +<p>Basically, this whole block of code is generating a block of HTML that looks like so, and inserting it into the page:</p> + +<pre class="brush: html"><div class="msgBox"> + <p>This is a message box</p> + <button>x</button> +</div></pre> + +<p>That was a lot of code to work through — don't worry too much if you don't remember exactly how every bit of it works right now! The main part we want to focus on here is the function's structure and usage, but we wanted to show something interesting for this example.</p> + +<h2 id="Calling_the_function">Calling the function</h2> + +<p>You've now got your function definition written into your <code><script></code> element just fine, but it will do nothing as it stands.</p> + +<ol> + <li>Try including the following line below your function to call it: + <pre class="brush: js">displayMessage();</pre> + This line invokes the function, making it run immediately. When you save your code and reload it in the browser, you'll see the little message box appear immediately, only once. We are only calling it once, after all.</li> + <li> + <p>Now open your browser developer tools on the example page, go to the JavaScript console and type the line again there, you'll see it appear again! So this is fun — we now have a reusable function that we can call any time we like.</p> + + <p>But we probably want it to appear in response to user and system actions. In a real application, such a message box would probably be called in response to new data being available, or an error having occurred, or the user trying to delete their profile ("are you sure about this?"), or the user adding a new contact and the operation completing successfully ... etc.</p> + + <p>In this demo, we'll get the message box to appear when the user clicks the button.</p> + </li> + <li>Delete the previous line you added.</li> + <li>Next, we'll select the button and store a reference to it in a variable. Add the following line to your code, above the function definition: + <pre class="brush: js">var btn = document.querySelector('button');</pre> + </li> + <li>Finally, add the following line below the previous one: + <pre class="brush: js">btn.onclick = displayMessage;</pre> + In a similar way to our <code>closeBtn.onclick...</code> line inside the function, here we are calling some code in response to a button being clicked. But in this case, instead of calling an anonymous function containing some code, we are calling our function name directly.</li> + <li>Try saving and refreshing the page — now you should see the message box appear when you click the button.</li> +</ol> + +<p>You might be wondering why we haven't included the parentheses after the function name. This is because we don't want to call the function immediately — only after the button has been clicked. If you try changing the line to</p> + +<pre class="brush: js">btn.onclick = displayMessage();</pre> + +<p>and saving and reloading, you'll see that the message box appears without the button being clicked! The parentheses in this context are sometimes called the "function invocation operator". You only use them when you want to run the function immediately in the current scope. In the same respect, the code inside the anonymous function is not run immediately, as it is inside the function scope.</p> + +<p>If you tried the last experiment, make sure to undo the last change before carrying on.</p> + +<h2 id="Improving_the_function_with_parameters">Improving the function with parameters</h2> + +<p>As it stands, the function is still not very useful — we don't want to just show the same default message every time. Let's improve our function by adding some parameters, allowing us to call it with some different options.</p> + +<ol> + <li>First of all, update the first line of the function: + <pre class="brush: js">function displayMessage() {</pre> + to this: + + <pre class="brush: js">function displayMessage(msgText, msgType) {</pre> + Now when we call the function, we can provide two variable values inside the parentheses to specify the message to display in the message box, and the type of message it is.</li> + <li>To make use of the first parameter, update the following line inside your function: + <pre class="brush: js">msg.textContent = 'This is a message box';</pre> + to + + <pre class="brush: js">msg.textContent = msgText;</pre> + </li> + <li>Last but not least, you now need to update your function call to include some updated message text. Change the following line: + <pre class="brush: js">btn.onclick = displayMessage;</pre> + to this block: + + <pre class="brush: js">btn.onclick = function() { + displayMessage('Woo, this is a different message!'); +};</pre> + If we want to specify parameters inside parentheses for the function we are calling, then we can't call it directly — we need to put it inside an anonymous function so that it isn't in the immediate scope and therefore isn't called immediately. Now it will not be called until the button is clicked.</li> + <li>Reload and try the code again and you'll see that it still works just fine, except that now you can also vary the message inside the parameter to get different messages displayed in the box!</li> +</ol> + +<h3 id="A_more_complex_parameter">A more complex parameter</h3> + +<p>On to the next parameter. This one is going to involve slightly more work — we are going to set it so that depending on what the <code>msgType</code> parameter is set to, the function will display a different icon and a different background color.</p> + +<ol> + <li>First of all, download the icons needed for this exercise (<a href="https://raw.githubusercontent.com/mdn/learning-area/master/javascript/building-blocks/functions/icons/warning.png">warning</a> and <a href="https://raw.githubusercontent.com/mdn/learning-area/master/javascript/building-blocks/functions/icons/chat.png">chat</a>) from GitHub. Save them in a new folder called <code>icons</code> in the same location as your HTML file. + + <div class="note"><strong>Note</strong>: <a href="https://www.iconfinder.com/icons/1031466/alarm_alert_error_warning_icon">warning</a> and <a href="https://www.iconfinder.com/icons/1031441/chat_message_text_icon">chat</a> icons found on iconfinder.com, and designed by <a href="https://www.iconfinder.com/nazarr">Nazarrudin Ansyari</a>. Thanks!</div> + </li> + <li>Next, find the CSS inside your HTML file. We'll make a few changes to make way for the icons. First, update the <code>.msgBox</code> width from: + <pre class="brush: css">width: 200px;</pre> + to + + <pre class="brush: css">width: 242px;</pre> + </li> + <li>Next, add the following lines inside the <code>.msgBox p { ... }</code> rule: + <pre class="brush: css">padding-left: 82px; +background-position: 25px center; +background-repeat: no-repeat;</pre> + </li> + <li>Now we need to add code to our <code>displayMessage()</code> function to handle displaying the icons. Add the following block just above the closing curly brace (<code>}</code>) of your function: + <pre class="brush: js">if (msgType === 'warning') { + msg.style.backgroundImage = 'url(icons/warning.png)'; + panel.style.backgroundColor = 'red'; +} else if (msgType === 'chat') { + msg.style.backgroundImage = 'url(icons/chat.png)'; + panel.style.backgroundColor = 'aqua'; +} else { + msg.style.paddingLeft = '20px'; +}</pre> + Here, if the <code>msgType</code> parameter is set as <code>'warning'</code>, the warning icon is displayed and the panel's background color is set to red. If it is set to <code>'chat'</code>, the chat icon is displayed and the panel's background color is set to aqua blue. If the <code>msgType</code> parameter is not set at all (or to something different), then the <code>else { ... }</code> part of the code comes into play, and the paragraph is simply given default padding and no icon, with no background panel color set either. This provides a default state if no <code>msgType</code> parameter is provided, meaning that it is an optional parameter!</li> + <li>Let's test out our updated function, try updating the <code>displayMessage()</code> call from this: + <pre class="brush: js">displayMessage('Woo, this is a different message!');</pre> + to one of these: + + <pre class="brush: js">displayMessage('Your inbox is almost full — delete some mails', 'warning'); +displayMessage('Brian: Hi there, how are you today?','chat');</pre> + You can see how useful our (now not so) little function is becoming.</li> +</ol> + +<div class="note"> +<p><strong>Note</strong>: If you have trouble getting the example to work, feel free to check your code against the <a href="https://github.com/mdn/learning-area/blob/master/javascript/building-blocks/functions/function-stage-4.html">finished version on GitHub</a> (<a href="http://mdn.github.io/learning-area/javascript/building-blocks/functions/function-stage-4.html">see it running live</a> also), or ask us for help.</p> +</div> + +<h2 id="Conclusion">Conclusion</h2> + +<p>Congratulations on reaching the end! This article took you through the entire process of building up a practical custom function, which with a bit more work could be transplanted into a real project. In the next article we'll wrap up functions by explaining another essential related concept — return values.</p> + +<ul> +</ul> + +<p>{{PreviousMenuNext("Learn/JavaScript/Building_blocks/Functions","Learn/JavaScript/Building_blocks/Return_values", "Learn/JavaScript/Building_blocks")}}</p> + +<p> </p> + +<h2 id="In_this_module">In this module</h2> + +<ul> + <li><a href="/en-US/docs/Learn/JavaScript/Building_blocks/conditionals">Making decisions in your code — conditionals</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Building_blocks/Looping_code">Looping code</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Building_blocks/Functions">Functions — reusable blocks of code</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Building_blocks/Build_your_own_function">Build your own function</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Building_blocks/Return_values">Function return values</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Building_blocks/Events">Introduction to events</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Building_blocks/Image_gallery">Image gallery</a></li> +</ul> + +<p> </p> diff --git a/files/zh-tw/learn/javascript/building_blocks/conditionals/index.html b/files/zh-tw/learn/javascript/building_blocks/conditionals/index.html new file mode 100644 index 0000000000..8b63b1034d --- /dev/null +++ b/files/zh-tw/learn/javascript/building_blocks/conditionals/index.html @@ -0,0 +1,789 @@ +--- +title: 在代碼中做出決定 - 條件 +slug: Learn/JavaScript/Building_blocks/conditionals +translation_of: Learn/JavaScript/Building_blocks/conditionals +--- +<div>{{LearnSidebar}}</div> + +<div>{{NextMenu("Learn/JavaScript/Building_blocks/Looping_code", "Learn/JavaScript/Building_blocks")}}</div> + +<p class="summary">在任何編程語言中,代碼都需要根據不同的輸入做出決策並相應地執行操作。 例如,在遊戲中,如果玩家的生命數量為0,則遊戲結束。 在天氣應用程序中,如果在早上查看,則顯示日出圖形; 如果是夜晚,則顯示星星和月亮。 在本文中,我們將探討條件結構如何在JavaScript中工作。</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Prerequisites:</th> + <td>Basic computer literacy, a basic understanding of HTML and CSS, <a href="/en-US/docs/Learn/JavaScript/First_steps">JavaScript first steps</a>.</td> + </tr> + <tr> + <th scope="row">Objective:</th> + <td>To understand how to use conditional structures in JavaScript.</td> + </tr> + </tbody> +</table> + +<h2 id="你可以擁有一個條件..!">你可以擁有一個條件..!</h2> + +<p>從小到大,人們(和其它動物)作出決定的時間會影響到他們的生活 ("我應該吃一個或兩個餅乾?") ("我應該留在我的家鄉並在我父親的農場工作還是應該要到美國研讀天體物理學?")</p> + +<p>條件敘述句(Conditional statements)讓我們能將這些決定的過程在Javascript表示出來,從一定得做出的選擇(例如:「吃一個或兩個餅乾」),到這些選擇的結果(或許「吃一個餅乾」會出現「還是會餓」這種結果,而「吃兩個餅乾」的結果會是「吃飽了,但因為吃了全部餅乾而被媽媽罵」)。</p> + +<p><img alt="" src="https://mdn.mozillademos.org/files/13703/cookie-choice-small.png" style="display: block; margin: 0 auto;"></p> + +<h2 id="if_..._else_敘述句">if ... else 敘述句</h2> + +<p>讓我們來看Javascript中最常見的條件敘述句 <code><a href="/en-US/docs/Web/JavaScript/Reference/Statements/if...else">if ... else</a></code><a href="/en-US/docs/Web/JavaScript/Reference/Statements/if...else"> statement</a>.</p> + +<h3 id="基本的_if_..._else_語法">基本的 if ... else 語法</h3> + +<p>最基本的 <code>if...else</code> 語法看起來像以下 {{glossary("虛擬碼")}}:</p> + +<pre>if (condition) { + code to run if condition is true +} else { + run some other code instead +}</pre> + +<p>這邊我們可以得知基礎的架構:</p> + +<ol> + <li>關鍵字 <code>if</code> 和後頭的括號。</li> + <li>想測試的條件放在括號中(通常像是「這個值是否大於其他值」或是「這個值是否存在」等等)。這裡的條件會使用先前提過的 <a href="/en-US/Learn/JavaScript/First_steps/Math#Comparison_operators">比較運算子</a>(<a href="/en-US/Learn/JavaScript/First_steps/Math#Comparison_operators">comparison operators</a>),並且最後會回傳 <code>true</code> 或是 <code>false</code>。</li> + <li>第一組大括號,在大括號裡面有一些程式碼 — 內容可以是任何我們所需要執行的程式碼,並且只有在條件句回傳 <code>true</code> 才會執行。</li> + <li>關鍵字 <code>else</code>。</li> + <li>另一組大括號,在大括號中我們一樣是放置所需的程式碼,並只有在條件句回傳 <code>false</code> 才會執行。</li> +</ol> + +<p>這個程式碼的架構很容易理解 — 「如果條件回傳 <code>true</code> ,則執行程式A,否則執行程式B」。</p> + +<p>值得注意的是,<code>else</code> 和第二組大括號並不是必要的。如以下範例也能夠執行:</p> + +<pre>if (condition) { + code to run if condition is true +} + +run some other code</pre> + +<p>然而,在這邊有一點要注意:在這個例子中的第二個區塊並沒有被條件式控制,也就是說無論條件式回傳的是 <code>true</code> 或是 <code>false</code>,它都會執行。這並不一定是件壞事,但它可能不會是你要的,通常你可能是想要執行程式碼的一個區塊或是另一塊,而不是兩個都執行。</p> + +<p>最後一點,你可能有時候會看到 <code>if...else</code> 敘述是不加大括弧的:</p> + +<pre>if (condition) code to run if condition is true +else run some other code instead</pre> + +<p>這當然也是有效的程式碼,但不太建議這樣用。使用大括弧能夠很清楚地看到程式區塊、縮排,也能夠擁有多行程式碼,對於程式的可讀性會提高許多。</p> + +<h3 id="A_real_example">A real example</h3> + +<p>To understand this syntax better, let's consider a real example. Imagine a child being asked for help with a chore by their mother or father. The parent might say "Hey sweetheart, if you help me by going and doing the shopping, I'll give you some extra allowance so you can afford that toy you wanted." In JavaScript, we could represent this like so:</p> + +<pre class="brush: js">var shoppingDone = false; + +if (shoppingDone === true) { + var childsAllowance = 10; +} else { + var childsAllowance = 5; +}</pre> + +<p>This code as shown will always result in the <code>shoppingDone</code> variable returning <code>false</code>, meaning disappointment for our poor child. It'd be up to us to provide a mechanism for the parent to set the <code>shoppingDone</code> variable to <code>true</code> if the child did the shopping.</p> + +<div class="note"> +<p><strong>Note</strong>: You can see a more <a href="https://github.com/mdn/learning-area/blob/master/javascript/building-blocks/allowance-updater.html">complete version of this example on GitHub</a> (also see it <a href="http://mdn.github.io/learning-area/javascript/building-blocks/allowance-updater.html">running live</a>.)</p> +</div> + +<h3 id="else_if">else if</h3> + +<p>The last example provided us with two choices, or outcomes — but what if we want more than two?</p> + +<p>There is a way to chain on extra choices/outcomes to your <code>if...else</code> — using <code>else if</code>. Each extra choice requires an additional block to put in between <code>if() { ... }</code> and <code>else { ... }</code> — check out the following more involved example, which could be part of a simple weather forecast application:</p> + +<pre class="brush: html"><label for="weather">Select the weather type today: </label> +<select id="weather"> + <option value="">--Make a choice--</option> + <option value="sunny">Sunny</option> + <option value="rainy">Rainy</option> + <option value="snowing">Snowing</option> + <option value="overcast">Overcast</option> +</select> + +<p></p></pre> + +<pre class="brush: js">var select = document.querySelector('select'); +var para = document.querySelector('p'); + +select.addEventListener('change', setWeather); + +function setWeather() { + var choice = select.value; + + if (choice === 'sunny') { + para.textContent = 'It is nice and sunny outside today. Wear shorts! Go to the beach, or the park, and get an ice cream.'; + } else if (choice === 'rainy') { + para.textContent = 'Rain is falling outside; take a rain coat and a brolly, and don\'t stay out for too long.'; + } else if (choice === 'snowing') { + para.textContent = 'The snow is coming down — it is freezing! Best to stay in with a cup of hot chocolate, or go build a snowman.'; + } else if (choice === 'overcast') { + para.textContent = 'It isn\'t raining, but the sky is grey and gloomy; it could turn any minute, so take a rain coat just in case.'; + } else { + para.textContent = ''; + } +} + +</pre> + +<p>{{ EmbedLiveSample('else_if', '100%', 100, "", "", "hide-codepen-jsfiddle") }}</p> + +<ol> + <li>Here we've got an HTML {{htmlelement("select")}} element allowing us to make different weather choices, and a simple paragraph.</li> + <li>In the JavaScript, we are storing a reference to both the {{htmlelement("select")}} and {{htmlelement("p")}} elements, and adding an event listener to the <code><select></code> element so that when its value is changed, the <code>setWeather()</code> function is run.</li> + <li>When this function is run, we first set a variable called <code>choice</code> to the current value selected in the <code><select></code> element. We then use a conditional statement to show different text inside the paragraph depending on what the value of <code>choice</code> is. Notice how all the conditions are tested in <code>else if() {...}</code> blocks, except for the first one, which is tested in an <code>if() {...} block</code>.</li> + <li>The very last choice, inside the <code>else {...}</code> block, is basically a "last resort" option — the code inside it will be run if none of the conditions are <code>true</code>. In this case, it serves to empty the text out of the paragraph if nothing is selected, for example if a user decides to re-select the "--Make a choice--" placeholder option shown at the beginning.</li> +</ol> + +<div class="note"> +<p><strong>Note</strong>: You can also <a href="https://github.com/mdn/learning-area/blob/master/javascript/building-blocks/simple-else-if.html">find this example on GitHub</a> (<a href="http://mdn.github.io/learning-area/javascript/building-blocks/simple-else-if.html">see it running live</a> on there also.)</p> +</div> + +<h3 id="A_note_on_comparison_operators">A note on comparison operators</h3> + +<p>Comparison operators are used to test the conditions inside our conditional statements. We first looked at comparison operators back in our <a href="/en-US/Learn/JavaScript/First_steps/Math#Comparison_operators">Basic math in JavaScript — numbers and operators</a> article. Our choices are:</p> + +<ul> + <li><code>===</code> and <code>!==</code> — test if one value is identical to, or not identical to, another.</li> + <li><code><</code> and <code>></code> — test if one value is less than or greater than another.</li> + <li><code><=</code> and <code>>=</code> — test if one value is less than or equal to, or greater than or equal to, another.</li> +</ul> + +<div class="note"> +<p><strong>Note</strong>: Review the material at the previous link if you want to refresh your memories on these.</p> +</div> + +<p>We wanted to make a special mention of testing boolean (<code>true</code>/<code>false</code>) values, and a common pattern you'll come across again and again. Any value that is not <code>false</code>, <code>undefined</code>, <code>null</code>, <code>0</code>, <code>NaN</code>, or an empty string (<code>''</code>) actually returns <code>true</code> when tested as a conditional statement, therefore you can simply use a variable name on its own to test whether it is <code>true</code>, or even that it exists (i.e. it is not undefined.) So for example:</p> + +<pre class="brush: js">var cheese = 'Cheddar'; + +if (cheese) { + console.log('Yay! Cheese available for making cheese on toast.'); +} else { + console.log('No cheese on toast for you today.'); +}</pre> + +<p>And, returning to our previous example about the child doing a chore for their parent, you could write it like this:</p> + +<pre class="brush: js">var shoppingDone = false; + +if (shoppingDone) { // don't need to explicitly specify '=== true' + var childsAllowance = 10; +} else { + var childsAllowance = 5; +}</pre> + +<h3 id="Nesting_if_..._else">Nesting if ... else</h3> + +<p>It is perfectly OK to put one <code>if...else</code> statement inside another one — to nest them. For example, we could update our weather forecast application to show a further set of choices depending on what the temperature is:</p> + +<pre class="brush: js">if (choice === 'sunny') { + if (temperature < 86) { + para.textContent = 'It is ' + temperature + ' degrees outside — nice and sunny. Let\'s go out to the beach, or the park, and get an ice cream.'; + } else if (temperature >= 86) { + para.textContent = 'It is ' + temperature + ' degrees outside — REALLY HOT! If you want to go outside, make sure to put some suncream on.'; + } +}</pre> + +<p>Even though the code all works together, each <code>if...else</code> statement works completely independently of the other one.</p> + +<h3 id="Logical_operators_AND_OR_and_NOT">Logical operators: AND, OR and NOT</h3> + +<p>If you want to test multiple conditions without writing nested <code>if...else</code> statements, <a href="/en-US/docs/Web/JavaScript/Reference/Operators/Logical_Operators">logical operators</a> can help you. When used in conditions, the first two do the following:</p> + +<ul> + <li><code>&&</code> — AND; allows you to chain together two or more expressions so that all of them have to individually evaluate to <code>true</code> for the whole expression to return <code>true</code>.</li> + <li><code>||</code> — OR; allows you to chain together two or more expressions so that one or more of them have to individually evaluate to <code>true</code> for the whole expression to return <code>true</code>.</li> +</ul> + +<p>To give you an AND example, the previous example snippet can be rewritten to this:</p> + +<pre class="brush: js">if (choice === 'sunny' && temperature < 86) { + para.textContent = 'It is ' + temperature + ' degrees outside — nice and sunny. Let\'s go out to the beach, or the park, and get an ice cream.'; +} else if (choice === 'sunny' && temperature >= 86) { + para.textContent = 'It is ' + temperature + ' degrees outside — REALLY HOT! If you want to go outside, make sure to put some suncream on.'; +}</pre> + +<p>So for example, the first code block will only be run if <code>choice === 'sunny'</code> <em>and</em> <code>temperature < 86</code> return <code>true</code>.</p> + +<p>Let's look at a quick OR example:</p> + +<pre class="brush: js">if (iceCreamVanOutside || houseStatus === 'on fire') { + console.log('You should leave the house quickly.'); +} else { + console.log('Probably should just stay in then.'); +}</pre> + +<p>The last type of logical operator, NOT, expressed by the <code>!</code> operator, can be used to negate an expression. Let's combine it with OR in the above example:</p> + +<pre class="brush: js">if (!(iceCreamVanOutside || houseStatus === 'on fire')) { + console.log('Probably should just stay in then.'); +} else { + console.log('You should leave the house quickly.'); +}</pre> + +<p>In this snippet, if the OR statement returns <code>true</code>, the NOT operator will negate it so that the overall expression returns <code>false</code>.</p> + +<p>You can combine as many logical statements together as you want, in whatever structure. The following example executes the code inside only if both OR statements return true, meaning that the overall AND statement will return true:</p> + +<pre class="brush: js">if ((x === 5 || y > 3 || z <= 10) && (loggedIn || userName === 'Steve')) { + // run the code +}</pre> + +<p>A common mistake when using the logical OR operator in conditional statements is to try to state the variable whose value you are checking once, and then give a list of values it could be to return true, separated by <code>||</code> (OR) operators. For example:</p> + +<pre class="example-bad brush: js">if (x === 5 || 7 || 10 || 20) { + // run my code +}</pre> + +<p>In this case the condition inside <code>if(...)</code> will always evaluate to true since 7 (or any other non-zero value) always evaluates to true. This condition is actually saying "if x equals 5, or 7 is true — which it always is". This is logically not what we want! To make this work you've got to specify a complete test either side of each OR operator:</p> + +<pre class="brush: js">if (x === 5 || x === 7 || x === 10 ||x === 20) { + // run my code +}</pre> + +<h2 id="switch_statements">switch statements</h2> + +<p><code>if...else</code> statements do the job of enabling conditional code well, but they are not without their downsides. They are mainly good for cases where you've got a couple of choices, and each one requires a reasonable amount of code to be run, and/or the conditions are complex (e.g. multiple logical operators). For cases where you just want to set a variable to a certain choice of value or print out a particular statement depending on a condition, the syntax can be a bit cumbersome, especially if you've got a large number of choices.</p> + +<p><a href="/en-US/docs/Web/JavaScript/Reference/Statements/switch"><code>switch</code> statements</a> are your friend here — they take a single expression/value as an input, and then look through a number of choices until they find one that matches that value, executing the corresponding code that goes along with it. Here's some more pseudocode, to give you an idea:</p> + +<pre>switch (expression) { + case choice1: + run this code + break; + + case choice2: + run this code instead + break; + + // include as many cases as you like + + default: + actually, just run this code +}</pre> + +<p>Here we've got:</p> + +<ol> + <li>The keyword <code>switch</code>, followed by a set of parentheses.</li> + <li>An expression or value inside the parentheses.</li> + <li>The keyword <code>case</code>, followed by a choice that the expression/value could be, followed by a colon.</li> + <li>Some code to run if the choice matches the expression.</li> + <li>A <code>break</code> statement, followed by a semi-colon. If the previous choice matches the expression/value, the browser stops executing the code block here, and moves on to any code that appears below the switch statement.</li> + <li>As many other cases (bullets 3–5) as you like.</li> + <li>The keyword <code>default</code>, followed by exactly the same code pattern as one of the cases (bullets 3–5), except that <code>default</code> does not have a choice after it, and you don't need to <code>break</code> statement as there is nothing to run after this in the block anyway. This is the default option that runs if none of the choices match.</li> +</ol> + +<div class="note"> +<p><strong>Note</strong>: You don't have to include the <code>default</code> section — you can safely omit it if there is no chance that the expression could end up equaling an unknown value. If there is a chance of this however, you need to include it to handle unknown cases.</p> +</div> + +<h3 id="A_switch_example">A switch example</h3> + +<p>Let's have a look at a real example — we'll rewrite our weather forecast application to use a switch statement instead:</p> + +<pre class="brush: html"><label for="weather">Select the weather type today: </label> +<select id="weather"> + <option value="">--Make a choice--</option> + <option value="sunny">Sunny</option> + <option value="rainy">Rainy</option> + <option value="snowing">Snowing</option> + <option value="overcast">Overcast</option> +</select> + +<p></p></pre> + +<pre class="brush: js">var select = document.querySelector('select'); +var para = document.querySelector('p'); + +select.addEventListener('change', setWeather); + + +function setWeather() { + var choice = select.value; + + switch (choice) { + case 'sunny': + para.textContent = 'It is nice and sunny outside today. Wear shorts! Go to the beach, or the park, and get an ice cream.'; + break; + case 'rainy': + para.textContent = 'Rain is falling outside; take a rain coat and a brolly, and don\'t stay out for too long.'; + break; + case 'snowing': + para.textContent = 'The snow is coming down — it is freezing! Best to stay in with a cup of hot chocolate, or go build a snowman.'; + break; + case 'overcast': + para.textContent = 'It isn\'t raining, but the sky is grey and gloomy; it could turn any minute, so take a rain coat just in case.'; + break; + default: + para.textContent = ''; + } +}</pre> + +<p>{{ EmbedLiveSample('A_switch_example', '100%', 100, "", "", "hide-codepen-jsfiddle") }}</p> + +<div class="note"> +<p><strong>Note</strong>: You can also <a href="https://github.com/mdn/learning-area/blob/master/javascript/building-blocks/simple-switch.html">find this example on GitHub</a> (see it <a href="http://mdn.github.io/learning-area/javascript/building-blocks/simple-switch.html">running live</a> on there also.)</p> +</div> + +<h2 id="三元運算符">三元運算符</h2> + +<p>There is one final bit of syntax we want to introduce you to, before we get you to play with some examples. The <a href="/en-US/docs/Web/JavaScript/Reference/Operators/Conditional_Operator">ternary or conditional operator</a> is a small bit of syntax that tests a condition and returns one value/expression if it is <code>true</code>, and another if it is <code>false</code> — this can be useful in some situations, and can take up a lot less code than an <code>if...else</code> block if you simply have two choices that are chosen between via a <code>true</code>/<code>false</code> condition. The pseudocode looks like this:</p> + +<pre>( condition ) ? run this code : run this code instead</pre> + +<p>So let's look at a simple example:</p> + +<pre class="brush: js">var greeting = ( isBirthday ) ? 'Happy birthday Mrs. Smith — we hope you have a great day!' : 'Good morning Mrs. Smith.';</pre> + +<p>Here we have a variable called <code>isBirthday</code> — if this is <code>true</code>, we give our guest a happy birthday message; if not, we give her the standard daily greeting.</p> + +<h3 id="Ternary_operator_example">Ternary operator example</h3> + +<p>You don't just have to set variable values with the ternary operator; you can also run functions, or lines of code — anything you like. The following live example shows a simple theme chooser where the styling for the site is applied using a ternary operator.</p> + +<pre class="brush: html"><label for="theme">Select theme: </label> +<select id="theme"> + <option value="white">White</option> + <option value="black">Black</option> +</select> + +<h1>This is my website</h1></pre> + +<pre class="brush: js">var select = document.querySelector('select'); +var html = document.querySelector('html'); +document.body.style.padding = '10px'; + +function update(bgColor, textColor) { + html.style.backgroundColor = bgColor; + html.style.color = textColor; +} + +select.onchange = function() { + ( select.value === 'black' ) ? update('black','white') : update('white','black'); +} +</pre> + +<p>{{ EmbedLiveSample('Ternary_operator_example', '100%', 300, "", "", "hide-codepen-jsfiddle") }}</p> + +<p>Here we've got a {{htmlelement('select')}} element to choose a theme (black or white), plus a simple {{htmlelement('h1')}} to display a website title. We also have a function called <code>update()</code>, which takes two colors as parameters (inputs). The website's background color is set to the first provided color, and its text color is set to the second provided color.</p> + +<p>Finally, we've also got an <a href="/en-US/docs/Web/API/GlobalEventHandlers/onchange">onchange</a> event listener that serves to run a function containing a ternary operator. It starts with a test condition — <code>select.value === 'black'</code>. If this returns <code>true</code>, we run the <code>update()</code> function with parameters of black and white, meaning that we end up with background color of black and text color of white. If it returns <code>false</code>, we run the <code>update()</code> function with parameters of white and black, meaning that the site color are inverted.</p> + +<div class="note"> +<p><strong>Note</strong>: You can also <a href="https://github.com/mdn/learning-area/blob/master/javascript/building-blocks/simple-ternary.html">find this example on GitHub</a> (see it <a href="http://mdn.github.io/learning-area/javascript/building-blocks/simple-ternary.html">running live</a> on there also.)</p> +</div> + +<h2 id="Active_learning_A_simple_calendar">Active learning: A simple calendar</h2> + +<p>In this example you are going to help us finish a simple calendar application. In the code you've got:</p> + +<ul> + <li>A {{htmlelement("select")}} element to allow the user to choose between different months.</li> + <li>An <code>onchange</code> event handler to detect when the value selected in the <code><select></code> menu is changed.</li> + <li>A function called <code>createCalendar()</code> that draws the calendar and displays the correct month in the {{htmlelement("h1")}} element.</li> +</ul> + +<p>We need you to write a conditional statement inside the <code>onchange</code> handler function, just below the <code>// ADD CONDITIONAL HERE</code> comment. It should:</p> + +<ol> + <li>Look at the selected month (stored in the <code>choice</code> variable. This will be the <code><select></code> element value after the value changes, so "January" for example.)</li> + <li>Set a variable called <code>days</code> to be equal to the number of days in the selected month. To do this you'll have to look up the number of days in each month of the year. You can ignore leap years for the purposes of this example.</li> +</ol> + +<p>Hints:</p> + +<ul> + <li>You are advised to use logical OR to group multiple months together into a single condition; many of them share the same number of days.</li> + <li>Think about which number of days is the most common, and use that as a default value.</li> +</ul> + +<p>If you make a mistake, you can always reset the example with the "Reset" button. If you get really stuck, press "Show solution" to see a solution.</p> + +<div class="hidden"> +<h6 id="Playable_code">Playable code</h6> + +<pre class="brush: html"><h2>Live output</h2> +<div class="output" style="height: 500px;overflow: auto;"> + <label for="month">Select month: </label> + <select id="month"> + <option value="January">January</option> + <option value="February">February</option> + <option value="March">March</option> + <option value="April">April</option> + <option value="May">May</option> + <option value="June">June</option> + <option value="July">July</option> + <option value="August">August</option> + <option value="September">September</option> + <option value="October">October</option> + <option value="November">November</option> + <option value="December">December</option> + </select> + + <h1></h1> + + <ul></ul> +</div> + +<h2>Editable code</h2> +<p class="a11y-label">Press Esc to move focus away from the code area (Tab inserts a tab character).</p> + +<textarea id="code" class="playable-code" style="height: 400px;width: 95%"> +var select = document.querySelector('select'); +var list = document.querySelector('ul'); +var h1 = document.querySelector('h1'); + +select.onchange = function() { + var choice = select.value; + + // ADD CONDITIONAL HERE + + createCalendar(days, choice); +} + +function createCalendar(days, choice) { + list.innerHTML = ''; + h1.textContent = choice; + for (var i = 1; i <= days; i++) { + var listItem = document.createElement('li'); + listItem.textContent = i; + list.appendChild(listItem); + } +} + +createCalendar(31,'January'); +</textarea> + +<div class="playable-buttons"> + <input id="reset" type="button" value="Reset"> + <input id="solution" type="button" value="Show solution"> +</div> +</pre> + +<pre class="brush: css">.output * { + box-sizing: border-box; +} + +.output ul { + padding-left: 0; +} + +.output li { + display: block; + float: left; + width: 25%; + border: 2px solid white; + padding: 5px; + height: 40px; + background-color: #4A2DB6; + color: white; +} + +html { + font-family: sans-serif; +} + +h2 { + font-size: 16px; +} + +.a11y-label { + margin: 0; + text-align: right; + font-size: 0.7rem; + width: 98%; +} + +body { + margin: 10px; + background: #f5f9fa; +}</pre> + + + + + +<pre class="brush: js">var textarea = document.getElementById('code'); +var reset = document.getElementById('reset'); +var solution = document.getElementById('solution'); +var code = textarea.value; +var userEntry = textarea.value; + +function updateCode() { + eval(textarea.value); +} + +reset.addEventListener('click', function() { + textarea.value = code; + userEntry = textarea.value; + solutionEntry = jsSolution; + solution.value = 'Show solution'; + updateCode(); +}); + +solution.addEventListener('click', function() { + if(solution.value === 'Show solution') { + textarea.value = solutionEntry; + solution.value = 'Hide solution'; + } else { + textarea.value = userEntry; + solution.value = 'Show solution'; + } + updateCode(); +}); + +var jsSolution = 'var select = document.querySelector(\'select\');\nvar list = document.querySelector(\'ul\');\nvar h1 = document.querySelector(\'h1\');\n\nselect.onchange = function() {\n var choice = select.value;\n var days = 31;\n if(choice === \'February\') {\n days = 28;\n } else if(choice === \'April\' || choice === \'June\' || choice === \'September\'|| choice === \'November\') {\n days = 30;\n }\n\n createCalendar(days, choice);\n}\n\nfunction createCalendar(days, choice) {\n list.innerHTML = \'\';\n h1.textContent = choice;\n for(var i = 1; i <= days; i++) {\n var listItem = document.createElement(\'li\');\n listItem.textContent = i;\n list.appendChild(listItem);\n }\n }\n\ncreateCalendar(31,\'January\');'; +var solutionEntry = jsSolution; + +textarea.addEventListener('input', updateCode); +window.addEventListener('load', updateCode); + +// stop tab key tabbing out of textarea and +// make it write a tab at the caret position instead + +textarea.onkeydown = function(e){ + if (e.keyCode === 9) { + e.preventDefault(); + insertAtCaret('\t'); + } + + if (e.keyCode === 27) { + textarea.blur(); + } +}; + +function insertAtCaret(text) { + var scrollPos = textarea.scrollTop; + var caretPos = textarea.selectionStart; + + var front = (textarea.value).substring(0, caretPos); + var back = (textarea.value).substring(textarea.selectionEnd, textarea.value.length); + textarea.value = front + text + back; + caretPos = caretPos + text.length; + textarea.selectionStart = caretPos; + textarea.selectionEnd = caretPos; + textarea.focus(); + textarea.scrollTop = scrollPos; +} + +// Update the saved userCode every time the user updates the text area code + +textarea.onkeyup = function(){ + // We only want to save the state when the user code is being shown, + // not the solution, so that solution is not saved over the user code + if(solution.value === 'Show solution') { + userEntry = textarea.value; + } else { + solutionEntry = textarea.value; + } + + updateCode(); +};</pre> + + +</div> + +<p>{{ EmbedLiveSample('Playable_code', '100%', 1110, "", "", "hide-codepen-jsfiddle") }}</p> + +<h2 id="Active_learning_More_color_choices!">Active learning: More color choices!</h2> + +<p>In this example you are going to take the ternary operator example we saw earlier and convert the ternary operator into a switch statement that will allow us to apply more choices to the simple website. Look at the {{htmlelement("select")}} — this time you'll see that it has not two theme options, but five. You need to add a switch statement just underneath the <code>// ADD SWITCH STATEMENT</code> comment:</p> + +<ul> + <li>It should accept the <code>choice</code> variable as its input expression.</li> + <li>For each case, the choice should equal one of the possible values that can be selected, i.e. white, black, purple, yellow, or psychedelic.</li> + <li>For each case, the <code>update()</code> function should be run, and be passed two color values, the first one for the background color, and the second one for the text color. Remember that color values are strings, so need to be wrapped in quotes.</li> +</ul> + +<p>If you make a mistake, you can always reset the example with the "Reset" button. If you get really stuck, press "Show solution" to see a solution.</p> + +<div class="hidden"> +<h6 id="Playable_code_2">Playable code 2</h6> + +<pre class="brush: html"><h2>Live output</h2> +<div class="output" style="height: 300px;"> + <label for="theme">Select theme: </label> + <select id="theme"> + <option value="white">White</option> + <option value="black">Black</option> + <option value="purple">Purple</option> + <option value="yellow">Yellow</option> + <option value="psychedelic">Psychedelic</option> + </select> + + <h1>This is my website</h1> +</div> + +<h2>Editable code</h2> +<p class="a11y-label">Press Esc to move focus away from the code area (Tab inserts a tab character).</p> + +<textarea id="code" class="playable-code" style="height: 450px;width: 95%"> +var select = document.querySelector('select'); +var html = document.querySelector('.output'); + +select.onchange = function() { + var choice = select.value; + + // ADD SWITCH STATEMENT +} + +function update(bgColor, textColor) { + html.style.backgroundColor = bgColor; + html.style.color = textColor; +}</textarea> + +<div class="playable-buttons"> + <input id="reset" type="button" value="Reset"> + <input id="solution" type="button" value="Show solution"> +</div> +</pre> + + + + + + + +<pre class="brush: css">html { + font-family: sans-serif; +} + +h2 { + font-size: 16px; +} + +.a11y-label { + margin: 0; + text-align: right; + font-size: 0.7rem; + width: 98%; +} + +body { + margin: 10px; + background: #f5f9fa; +}</pre> + + + + + + + + + +<pre class="brush: js">var textarea = document.getElementById('code'); +var reset = document.getElementById('reset'); +var solution = document.getElementById('solution'); +var code = textarea.value; +var userEntry = textarea.value; + +function updateCode() { + eval(textarea.value); +} + +reset.addEventListener('click', function() { + textarea.value = code; + userEntry = textarea.value; + solutionEntry = jsSolution; + solution.value = 'Show solution'; + updateCode(); +}); + +solution.addEventListener('click', function() { + if(solution.value === 'Show solution') { + textarea.value = solutionEntry; + solution.value = 'Hide solution'; + } else { + textarea.value = userEntry; + solution.value = 'Show solution'; + } + updateCode(); +}); + +var jsSolution = 'var select = document.querySelector(\'select\');\nvar html = document.querySelector(\'.output\');\n\nselect.onchange = function() {\n var choice = select.value;\n\n switch(choice) {\n case \'black\':\n update(\'black\',\'white\');\n break;\n case \'white\':\n update(\'white\',\'black\');\n break;\n case \'purple\':\n update(\'purple\',\'white\');\n break;\n case \'yellow\':\n update(\'yellow\',\'darkgray\');\n break;\n case \'psychedelic\':\n update(\'lime\',\'purple\');\n break;\n }\n}\n\nfunction update(bgColor, textColor) {\n html.style.backgroundColor = bgColor;\n html.style.color = textColor;\n}'; +var solutionEntry = jsSolution; + +textarea.addEventListener('input', updateCode); +window.addEventListener('load', updateCode); + +// stop tab key tabbing out of textarea and +// make it write a tab at the caret position instead + +textarea.onkeydown = function(e){ + if (e.keyCode === 9) { + e.preventDefault(); + insertAtCaret('\t'); + } + + if (e.keyCode === 27) { + textarea.blur(); + } +}; + +function insertAtCaret(text) { + var scrollPos = textarea.scrollTop; + var caretPos = textarea.selectionStart; + + var front = (textarea.value).substring(0, caretPos); + var back = (textarea.value).substring(textarea.selectionEnd, textarea.value.length); + textarea.value = front + text + back; + caretPos = caretPos + text.length; + textarea.selectionStart = caretPos; + textarea.selectionEnd = caretPos; + textarea.focus(); + textarea.scrollTop = scrollPos; +} + +// Update the saved userCode every time the user updates the text area code + +textarea.onkeyup = function(){ + // We only want to save the state when the user code is being shown, + // not the solution, so that solution is not saved over the user code + if(solution.value === 'Show solution') { + userEntry = textarea.value; + } else { + solutionEntry = textarea.value; + } + + updateCode(); +};</pre> + + +</div> + +<p>{{ EmbedLiveSample('Playable_code_2', '100%', 950, "", "", "hide-codepen-jsfiddle") }}</p> + +<h2 id="Conclusion">Conclusion</h2> + +<p>And that's all you really need to know about conditional structures in JavaScript right now! I'm sure you'll have understood these concepts and worked through the examples with ease; if there is anything you didn't understand, feel free to read through the article again, or <a href="/en-US/Learn#Contact_us">contact us</a> to ask for help.</p> + +<h2 id="See_also">See also</h2> + +<ul> + <li><a href="/en-US/Learn/JavaScript/First_steps/Math#Comparison_operators">Comparison operators</a></li> + <li><a href="/en-US/docs/Web/JavaScript/Guide/Control_flow_and_error_handling#Conditional_statements">Conditional statements in detail</a></li> + <li><a href="/en-US/docs/Web/JavaScript/Reference/Statements/if...else">if...else reference</a></li> + <li><a href="/en-US/docs/Web/JavaScript/Reference/Operators/Conditional_Operator">Conditional (ternary) operator reference</a></li> +</ul> + +<p>{{NextMenu("Learn/JavaScript/Building_blocks/Looping_code", "Learn/JavaScript/Building_blocks")}}</p> + +<h2 id="In_this_module">In this module</h2> + +<ul> + <li><a href="/en-US/docs/Learn/JavaScript/Building_blocks/conditionals">Making decisions in your code — conditionals</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Building_blocks/Looping_code">Looping code</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Building_blocks/Functions">Functions — reusable blocks of code</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Building_blocks/Build_your_own_function">Build your own function</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Building_blocks/Return_values">Function return values</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Building_blocks/Events">Introduction to events</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Building_blocks/Image_gallery">Image gallery</a></li> +</ul> diff --git a/files/zh-tw/learn/javascript/building_blocks/functions/index.html b/files/zh-tw/learn/javascript/building_blocks/functions/index.html new file mode 100644 index 0000000000..719180656f --- /dev/null +++ b/files/zh-tw/learn/javascript/building_blocks/functions/index.html @@ -0,0 +1,396 @@ +--- +title: 函數 - 可重複使用的代碼塊 +slug: Learn/JavaScript/Building_blocks/Functions +translation_of: Learn/JavaScript/Building_blocks/Functions +--- +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenuNext("Learn/JavaScript/Building_blocks/Looping_code","Learn/JavaScript/Building_blocks/Build_your_own_function", "Learn/JavaScript/Building_blocks")}}</div> + +<p class="summary">編碼中的另一個基本概念是函數,它允許您存儲一段代碼,該代碼在定義的塊內執行單個任務,然後在需要時使用一個簡短命令調用該代碼 - 而不必輸入相同的代碼 代碼多次。 在本文中,我們將探索函數背後的基本概念,例如基本語法,如何調用和定義它們,範圍和參數。</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Prerequisites:</th> + <td>Basic computer literacy, a basic understanding of HTML and CSS, <a href="/en-US/docs/Learn/JavaScript/First_steps">JavaScript first steps</a>.</td> + </tr> + <tr> + <th scope="row">Objective:</th> + <td>To understand the fundamental concepts behind JavaScript functions.</td> + </tr> + </tbody> +</table> + +<h2 id="Where_do_I_find_functions">Where do I find functions?</h2> + +<p>In JavaScript, you'll find functions everywhere. In fact, we've been using functions all the way through the course so far; we've just not been talking about them very much. Now is the time, however, for us to start talking about functions explicitly, and really exploring their syntax.</p> + +<p>Pretty much anytime you make use of a JavaScript structure that features a pair of parentheses — <code>()</code> — and you're <strong>not</strong> using a common built-in language structure like a <a href="/en-US/Learn/JavaScript/Building_blocks/Looping_code#The_standard_for_loop">for loop</a>, <a href="/en-US/Learn/JavaScript/Building_blocks/Looping_code#while_and_do_..._while">while or do...while loop</a>, or <a href="/en-US/Learn/JavaScript/Building_blocks/conditionals#if_..._else_statements">if...else statement</a>, you are making use of a function.</p> + +<h2 id="Built-in_browser_functions">Built-in browser functions</h2> + +<p>We've made use of functions built in to the browser a lot in this course. Every time we manipulated a text string, for example:</p> + +<pre class="brush: js">var myText = 'I am a string'; +var newString = myText.replace('string', 'sausage'); +console.log(newString); +// the replace() string function takes a string, +// replaces one substring with another, and returns +// a new string with the replacement made</pre> + +<p>Or every time we manipulated an array:</p> + +<pre class="brush: js">var myArray = ['I', 'love', 'chocolate', 'frogs']; +var madeAString = myArray.join(' '); +console.log(madeAString); +// the join() function takes an array, joins +// all the array items together into a single +// string, and returns this new string</pre> + +<p>Or every time we generated a random number:</p> + +<pre class="brush: js">var myNumber = Math.random(); +// the random() function generates a random +// number between 0 and 1, and returns that +// number</pre> + +<p>...we were using a function!</p> + +<div class="note"> +<p><strong>Note</strong>: Feel free to enter these lines into your browser's JavaScript console to re-familiarize yourself with their functionality, if needed.</p> +</div> + +<p>The JavaScript language has many built-in functions to allow you to do useful things without having to write all that code yourself. In fact, some of the code you are calling when you <strong>invoke</strong> (a fancy word for run, or execute) a built in browser function couldn't be written in JavaScript — many of these functions are calling parts of the background browser code, which is written largely in low-level system languages like C++, not web languages like JavaScript.</p> + +<p>Bear in mind that some built-in browser functions are not part of the core JavaScript language — some are defined as part of browser APIs, which build on top of the default language to provide even more functionality (refer to <a href="/en-US/Learn/JavaScript/First_steps/What_is_JavaScript#So_what_can_it_really_do">this early section of our course</a> for more descriptions). We'll look at using browser APIs in more detail in a later module.</p> + +<h2 id="Functions_versus_methods">Functions versus methods</h2> + +<p>One thing we need to clear up before we move on — technically speaking, built in browser functions are not functions — they are <strong>methods</strong>. This sounds a bit scary and confusing, but don't worry — the words function and method are largely interchangeable, at least for our purposes, at this stage in your learning.</p> + +<p>The distinction is that methods are functions defined inside objects. Built-in browser functions (methods) and variables (which are called <strong>properties</strong>) are stored inside structured objects, to make the code more efficient and easier to handle.</p> + +<p>You don't need to learn about the inner workings of structured JavaScript objects yet — you can wait until our later module that will teach you all about the inner workings of objects, and how to create your own. For now, we just wanted to clear up any possible confusion of method versus function — you are likely to meet both terms as you look at the available related resources across the Web.</p> + +<h2 id="Custom_functions">Custom functions</h2> + +<p>You've also seen a lot of <strong>custom functions</strong> in the course so far — functions defined in your code, not inside the browser. Anytime you saw a custom name with parentheses straight after it, you were using a custom function. In our <a href="http://mdn.github.io/learning-area/javascript/building-blocks/loops/random-canvas-circles.html">random-canvas-circles.html</a> example (see also the full <a href="https://github.com/mdn/learning-area/blob/master/javascript/building-blocks/loops/random-canvas-circles.html">source code</a>) from our <a href="/en-US/docs/Learn/JavaScript/Building_blocks/Looping_code">loops article</a>, we included a custom <code>draw()</code> function that looked like this:</p> + +<pre class="brush: js">function draw() { + ctx.clearRect(0,0,WIDTH,HEIGHT); + for (var i = 0; i < 100; i++) { + ctx.beginPath(); + ctx.fillStyle = 'rgba(255,0,0,0.5)'; + ctx.arc(random(WIDTH), random(HEIGHT), random(50), 0, 2 * Math.PI); + ctx.fill(); + } +}</pre> + +<p>This function draws 100 random circles inside an {{htmlelement("canvas")}} element. Every time we want to do that, we can just invoke the function with this</p> + +<pre class="brush: js">draw();</pre> + +<p>rather than having to write all that code out again every time we want to repeat it. And functions can contain whatever code you like — you can even call other functions from inside functions. The above function for example calls the <code>random()</code> function three times, which is defined by the following code:</p> + +<pre class="brush: js">function random(number) { + return Math.floor(Math.random()*number); +}</pre> + +<p>We needed this function because the browser's built-in <a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/random">Math.random()</a> function only generates a random decimal number between 0 and 1. We wanted a random whole number between 0 and a specified number.</p> + +<h2 id="Invoking_functions">Invoking functions</h2> + +<p>You are probably clear on this by now, but just in case ... to actually use a function after it has been defined, you've got to run — or invoke — it. This is done by including the name of the function in the code somewhere, followed by parentheses.</p> + +<pre class="brush: js">function myFunction() { + alert('hello'); +} + +myFunction() +// calls the function once</pre> + +<h2 id="Anonymous_functions">Anonymous functions</h2> + +<p>You may see functions defined and invoked in slightly different ways. So far we have just created a function like so:</p> + +<pre class="brush: js">function myFunction() { + alert('hello'); +}</pre> + +<p>But you can also create a function that doesn't have a name:</p> + +<pre class="brush: js">function() { + alert('hello'); +}</pre> + +<p>This is called an <strong>anonymous function</strong> — it has no name! It also won't do anything on its own. You generally use an anonymous function along with an event handler, for example the following would run the code inside the function whenever the associated button is clicked:</p> + +<pre class="brush: js">var myButton = document.querySelector('button'); + +myButton.onclick = function() { + alert('hello'); +}</pre> + +<p>The above example would require there to be a {{htmlelement("button")}} element available on the page to select and click. You've already seen this structure a few times throughout the course, and you'll learn more about and see it in use in the next article.</p> + +<p>You can also assign an anonymous function to be the value of a variable, for example:</p> + +<pre class="brush: js">var myGreeting = function() { + alert('hello'); +}</pre> + +<p>This function could now be invoked using:</p> + +<pre class="brush: js">myGreeting();</pre> + +<p>This effectively gives the function a name; you can also assign the function to be the value of multiple variables, for example:</p> + +<pre class="brush: js">var anotherGreeting = function() { + alert('hello'); +}</pre> + +<p>This function could now be invoked using either of</p> + +<pre class="brush: js">myGreeting(); +anotherGreeting();</pre> + +<p>But this would just be confusing, so don't do it! When creating functions, it is better to just stick to this form:</p> + +<pre class="brush: js">function myGreeting() { + alert('hello'); +}</pre> + +<p>You will mainly use anonymous functions to just run a load of code in response to an event firing — like a button being clicked — using an event handler. Again, this looks something like this:</p> + +<pre class="brush: js">myButton.onclick = function() { + alert('hello'); + // I can put as much code + // inside here as I want +}</pre> + +<h2 id="Function_parameters">Function parameters</h2> + +<p>Some functions require <strong>parameters</strong> to be specified when you are invoking them — these are values that need to be included inside the function parentheses, which it needs to do its job properly.</p> + +<div class="note"> +<p><strong>Note</strong>: Parameters are sometimes called arguments, properties, or even attributes.</p> +</div> + +<p>As an example, the browser's built-in <a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/random">Math.random()</a> function doesn't require any parameters. When called, it always returns a random number between 0 and 1:</p> + +<pre class="brush: js">var myNumber = Math.random();</pre> + +<p>The browser's built-in string <a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replace">replace()</a> function however needs two parameters — the substring to find in the main string, and the substring to replace that string with:</p> + +<pre class="brush: js">var myText = 'I am a string'; +var newString = myText.replace('string', 'sausage');</pre> + +<div class="note"> +<p><strong>Note</strong>: When you need to specify multiple parameters, they are separated by commas.</p> +</div> + +<p>It should also be noted that sometimes parameters are optional — you don't have to specify them. If you don't, the function will generally adopt some kind of default behavior. As an example, the array <a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/join">join()</a> function's parameter is optional:</p> + +<pre class="brush: js">var myArray = ['I', 'love', 'chocolate', 'frogs']; +var madeAString = myArray.join(' '); +// returns 'I love chocolate frogs' +var madeAString = myArray.join(); +// returns 'I,love,chocolate,frogs'</pre> + +<p>If no parameter is included to specify a joining/delimiting character, a comma is used by default.</p> + +<h2 id="Function_scope_and_conflicts">Function scope and conflicts</h2> + +<p>Let's talk a bit about {{glossary("scope")}} — a very important concept when dealing with functions. When you create a function, the variables and other things defined inside the function are inside their own separate <strong>scope</strong>, meaning that they are locked away in their own separate compartments, unreachable from inside other functions or from code outside the functions.</p> + +<p>The top level outside all your functions is called the <strong>global scope</strong>. Values defined in the global scope are accessible from everywhere in the code.</p> + +<p>JavaScript is set up like this for various reasons — but mainly because of security and organization. Sometimes you don't want variables to be accessible from everywhere in the code — external scripts that you call in from elsewhere could start to mess with your code and cause problems because they happen to be using the same variable names as other parts of the code, causing conflicts. This might be done maliciously, or just by accident.</p> + +<p>For example, say you have an HTML file that is calling in two external JavaScript files, and both of them have a variable and a function defined that use the same name:</p> + +<pre class="brush: html"><!-- Excerpt from my HTML --> +<script src="first.js"></script> +<script src="second.js"></script> +<script> + greeting(); +</script></pre> + +<pre class="brush: js">// first.js +var name = 'Chris'; +function greeting() { + alert('Hello ' + name + ': welcome to our company.'); +}</pre> + +<pre class="brush: js">// second.js +var name = 'Zaptec'; +function greeting() { + alert('Our company is called ' + name + '.'); +}</pre> + +<p>Both functions you want to call are called <code>greeting()</code>, but you can only ever access the <code>second.js</code> file's <code>greeting()</code> function — it is applied to the HTML later on in the source code, so its variable and function overwrite the ones in <code>first.js</code>.</p> + +<div class="note"> +<p><strong>Note</strong>: You can see this example <a href="http://mdn.github.io/learning-area/javascript/building-blocks/functions/conflict.html">running live on GitHub</a> (see also the <a href="https://github.com/mdn/learning-area/tree/master/javascript/building-blocks/functions">source code</a>).</p> +</div> + +<p>Keeping parts of your code locked away in functions avoids such problems, and is considered best practice.</p> + +<p>It is a bit like a zoo. The lions, zebras, tigers, and penguins are kept in their own enclosures, and only have access to the things inside their enclosures — in the same manner as the function scopes. If they were able to get into other enclosures, problems would occur. At best, different animals would feel really uncomfortable inside unfamiliar habitats — a lion or tiger would feel terrible inside the penguins' watery, icy domain. At worst, the lions and tigers might try to eat the penguins!</p> + +<p><img alt="" src="https://mdn.mozillademos.org/files/14079/MDN-mozilla-zoo.png" style="display: block; margin: 0 auto;"></p> + +<p>The zoo keeper is like the global scope — he or she has the keys to access every enclosure, to restock food, tend to sick animals, etc.</p> + +<h3 id="Active_learning_Playing_with_scope">Active learning: Playing with scope</h3> + +<p>Let's look at a real example to demonstrate scoping.</p> + +<ol> + <li>First, make a local copy of our <a href="https://github.com/mdn/learning-area/blob/master/javascript/building-blocks/functions/function-scope.html">function-scope.html</a> example. This contains two functions called <code>a()</code> and <code>b()</code>, and three variables — <code>x</code>, <code>y</code>, and <code>z</code> — two of which are defined inside the functions, and one in the global scope. It also contains a third function called <code>output()</code>, which takes a single parameter and outputs it in a paragraph on the page.</li> + <li>Open the example up in a browser and in your text editor.</li> + <li>Open the JavaScript console in your browser developer tools. In the JavaScript console, enter the following command: + <pre class="brush: js">output(x);</pre> + You should see the value of variable <code>x</code> output to the screen.</li> + <li>Now try entering the following in your console + <pre class="brush: js">output(y); +output(z);</pre> + Both of these should return an error along the lines of "<a href="/en-US/docs/Web/JavaScript/Reference/Errors/Not_defined">ReferenceError: y is not defined</a>". Why is that? Because of function scope — <code>y</code> and <code>z</code> are locked inside the <code>a()</code> and <code>b()</code> functions, so <code>output()</code> can't access them when called from the global scope.</li> + <li>However, what about when it's called from inside another function? Try editing <code>a()</code> and <code>b()</code> so they look like this: + <pre class="brush: js">function a() { + var y = 2; + output(y); +} + +function b() { + var z = 3; + output(z); +}</pre> + Save the code and reload it in your browser, then try calling the <code>a()</code> and <code>b()</code> functions from the JavaScript console: + + <pre class="brush: js">a(); +b();</pre> + You should see the <code>y</code> and <code>z</code> values output in the page. This works fine, as the <code>output()</code> function is being called inside the other functions — in the same scope as the variables it is printing are defined in, in each case. <code>output()</code> itself is available from anywhere, as it is defined in the global scope.</li> + <li>Now try updating your code like this: + <pre class="brush: js">function a() { + var y = 2; + output(x); +} + +function b() { + var z = 3; + output(x); +}</pre> + Save and reload again, and try this again in your JavaScript console: + + <pre class="brush: js">a(); +b();</pre> + Both the <code>a()</code> and <code>b()</code> call should output the value of x — 1. These work fine because even though the <code>output()</code> calls are not in the same scope as <code>x</code> is defined in, <code>x</code> is a global variable so is available inside all code, everywhere.</li> + <li>Finally, try updating your code like this: + <pre class="brush: js">function a() { + var y = 2; + output(z); +} + +function b() { + var z = 3; + output(y); +}</pre> + Save and reload again, and try this again in your JavaScript console: + + <pre class="brush: js">a(); +b();</pre> + This time the <code>a()</code> and <code>b()</code> calls will both return that annoying "<a href="/en-US/docs/Web/JavaScript/Reference/Errors/Not_defined">ReferenceError: z is not defined</a>" error — this is because the <code>output()</code> calls and the variables they are trying to print are not defined inside the same function scopes — the variables are effectively invisible to those function calls.</li> +</ol> + +<div class="note"> +<p><strong>Note</strong>: The same scoping rules do not apply to loop (e.g. <code>for() { ... }</code>) and conditional blocks (e.g. <code>if() { ... }</code>) — they look very similar, but they are not the same thing! Take care not to get these confused.</p> +</div> + +<div class="note"> +<p><strong>Note</strong>: The <a href="/en-US/docs/Web/JavaScript/Reference/Errors/Not_defined">ReferenceError: "x" is not defined</a> error is one of the most common you'll encounter. If you get this error and you are sure that you have defined the variable in question, check what scope it is in.</p> +</div> + +<ul> +</ul> + +<h3 id="Functions_inside_functions">Functions inside functions</h3> + +<p>Keep in mind that you can call a function from anywhere, even inside another function. This is often used as a way to keep code tidy — if you have a big complex function, it is easier to understand if you break it down into several sub-functions:</p> + +<pre class="brush: js">function myBigFunction() { + var myValue; + + subFunction1(); + subFunction2(); + subFunction3(); +} + +function subFunction1() { + console.log(myValue); +} + +function subFunction2() { + console.log(myValue); +} + +function subFunction3() { + console.log(myValue); +} +</pre> + +<p>Just make sure that the values being used inside the function are properly in scope. The example above would throw an error <code>ReferenceError: myValue is not defined</code>, because although the <code>myValue</code> variable is defined in the same scope as the function calls, it is not defined inside the function definitions — the actual code that is run when the functions are called. To make this work, you'd have to pass the value into the function as a parameter, like this:</p> + +<pre class="brush: js">function myBigFunction() { + var myValue = 1; + + subFunction1(myValue); + subFunction2(myValue); + subFunction3(myValue); +} + +function subFunction1(value) { + console.log(value); +} + +function subFunction2(value) { + console.log(value); +} + +function subFunction3(value) { + console.log(value); +}</pre> + +<h2 id="Conclusion">Conclusion</h2> + +<p>This article has explored the fundamental concepts behind functions, paving the way for the next one in which we get practical and take you through the steps to building up your own custom function.</p> + +<h2 id="See_also">See also</h2> + +<ul> + <li><a href="/en-US/docs/Web/JavaScript/Guide/Functions">Functions detailed guide</a> — covers some advanced features not included here.</li> + <li><a href="/en-US/docs/Web/JavaScript/Reference/Functions">Functions reference</a></li> + <li><a href="/en-US/docs/Web/JavaScript/Reference/Functions/Default_parameters">Default parameters</a>, <a href="/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions">Arrow functions</a> — advanced concept references</li> +</ul> + +<ul> +</ul> + +<p>{{PreviousMenuNext("Learn/JavaScript/Building_blocks/Looping_code","Learn/JavaScript/Building_blocks/Build_your_own_function", "Learn/JavaScript/Building_blocks")}}</p> + +<p> </p> + +<h2 id="In_this_module">In this module</h2> + +<ul> + <li><a href="/en-US/docs/Learn/JavaScript/Building_blocks/conditionals">Making decisions in your code — conditionals</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Building_blocks/Looping_code">Looping code</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Building_blocks/Functions">Functions — reusable blocks of code</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Building_blocks/Build_your_own_function">Build your own function</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Building_blocks/Return_values">Function return values</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Building_blocks/Events">Introduction to events</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Building_blocks/Image_gallery">Image gallery</a></li> +</ul> + +<p> </p> diff --git a/files/zh-tw/learn/javascript/building_blocks/image_gallery/index.html b/files/zh-tw/learn/javascript/building_blocks/image_gallery/index.html new file mode 100644 index 0000000000..32c5a1867a --- /dev/null +++ b/files/zh-tw/learn/javascript/building_blocks/image_gallery/index.html @@ -0,0 +1,135 @@ +--- +title: 影像圖庫 +slug: Learn/JavaScript/Building_blocks/Image_gallery +tags: + - JavaScript + - 事件 + - 事件處理器 + - 優先國際化 + - 初學者 + - 學習 + - 條件式 + - 編碼腳本 + - 評量 + - 迴圈 +translation_of: Learn/JavaScript/Building_blocks/Image_gallery +--- +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenu("Learn/JavaScript/Building_blocks/Events", "Learn/JavaScript/Building_blocks")}}</div> + +<p class="summary">現在我們已經看過了基本的JavaScript組建,我們將讓你做一個測試,從建立一個在很多網站上常見的事物 — JavaScript基礎的影像圖庫,來測試你對迴圈、函數、條件式及事件的知識。</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">先修課程:</th> + <td>在進行這個評量前,你應已閱讀、練習了本模組中所有的文章。</td> + </tr> + <tr> + <th scope="row">目的:</th> + <td>測試對JavaScript中迴圈、函數、條件式及事件的瞭解程度。</td> + </tr> + </tbody> +</table> + +<h2 id="從這裡開始">從這裡開始</h2> + +<p>要進行這個評量,你要先下載 <a href="https://github.com/mdn/learning-area/blob/master/javascript/building-blocks/gallery/gallery-start.zip?raw=true">grab the ZIP</a> 檔案,解壓縮在你電腦中的某個檔案夾作為範例。</p> + +<div class="note"> +<p><strong>提醒:</strong>你也可以在某些網站進行評鑑,如 <a class="external external-icon" href="http://jsbin.com/">JSBin</a> 或<a class="external external-icon" href="https://thimble.mozilla.org/">Thimble</a>。你可以把這些HTML、CSS和JavaScript貼到這些線上編輯器中。如果你用了一個沒法把JavaScript/CSS分別放在不同面板的線上編輯器,你可以放心的把這些<code><script></code>/<code><style></code>元件改成inline貼進HTML網頁裡。</p> +</div> + +<h2 id="專案簡報">專案簡報</h2> + +<p>你手上已有我們提供的一些 HTML、CSS 和圖片資料,以及幾行 JavaScript 程式碼;你要寫一些必要的 JavaScript 讓它變成可運作的程式。這些 HTML 的 body 看起來如下:</p> + +<pre class="brush: html"><h1>Image gallery example</h1> + +<div class="full-img"> + <img class="displayed-img" src="images/pic1.jpg"> + <div class="overlay"></div> + <button class="dark">Darken</button> +</div> + +<div class="thumb-bar"> + +</div></pre> + +<p>完成後看起來像下圖:</p> + +<p><img alt="" src="https://mdn.mozillademos.org/files/13787/gallery.png" style="display: block; margin: 0 auto;"></p> + +<ul> +</ul> + +<p>範例 CSS 檔案中最有趣的部分是:</p> + +<ul> + <li>在 <code>full-img <div></code> 裡有的三個組成元素使用絕對位置 — <code><img></code> 展示全尺寸圖片,在它正上方有個與它尺寸相同的空 <code><div></code> (用來放置用半透明的背景色彩讓圖片產生變暗效果的層),然後 <code><button></code> 用來控制變暗效果。</li> + <li>設定 <code>thumb-bar <div></code> (一般叫做「縮圖」的圖片)裡的圖片讓它縮小成原來的20%,之後讓它浮(float)在左邊讓縮圖能一個個相鄰的排成一列。</li> +</ul> + +<p>在你的 JavaScript 裡需要:</p> + +<ul> + <li>讓所有圖片迴圈(Loop) through all the images, 在 <code>thumb-bar <div></code> 裡的每個 <code><img></code> 塞進一個 <code><img></code> ,讓圖片內嵌在頁面上。</li> + <li>在 <code>thumb-bar <div></code> 裡的每個 <code><img></code> 添加一個 <code>onclick</code> 處理器使這個圖片被點擊時會放大展示在 <code>displayed-img <img></code> 裡。</li> + <li>在 <code><button></code> 添加一個 <code>onclick</code> 處理器,當點擊時,全尺寸圖片產生暗化效果,再次點擊時移除暗化效果。</li> +</ul> + +<p>為了讓你更清楚,你可以看看這個 <a href="http://mdn.github.io/learning-area/javascript/building-blocks/gallery/">完成的範例</a> (但別偷看原始碼!)</p> + +<h2 id="一步步完成">一步步完成</h2> + +<p>接下來幾節描述你該怎麼做。</p> + +<h3 id="讓所有圖片迴圈">讓所有圖片迴圈</h3> + +<p>我們已提供了幾行程式碼:將<code>thumb-bar</code>和 <code><div></code>儲存在 <code>thumbBar</code>這個變數裡、建立一個新的 <code><img></code> 元件、將它的 <code>src</code> 屬性設定在一個值為 <code>xxx</code> 的佔位符中,以及在 <code>thumbBar</code> 裡增加新 <code><img></code> 。</p> + +<p>你要做的是:</p> + +<ol> + <li>Put the section of code below the "Looping through images" comment inside a loop that loops through all 5 images — you just need to loop through five numbers, one representing each image.</li> + <li>In each loop iteration, replace the <code>xxx</code> placeholder value with a string that will equal the path to the image in each case. We are setting the value of the <code>src</code> attribute to this value in each case. Bear in mind that in each case, the image is inside the images directory and its name is <code>pic1.jpg</code>, <code>pic2.jpg</code>, etc.</li> +</ol> + +<h3 id="在每個縮圖上添加onclick事件處理器">在每個縮圖上添加onclick事件處理器</h3> + +<p>In each loop iteration, you need to add an <code>onclick</code> handler to the current <code>newImage</code> — this should:</p> + +<ol> + <li>在每個 <code><img></code> 中把<code>"src"</code>作為運行<code>getAttribute()</code> 函數的參數,取得現在這張圖片的 <code>src</code> 屬性的值。但是要怎麼抓到現在這張圖片?如果用<code>newImage</code> 是做不到的,當在添加事件處理器前,迴圈已經先完成了;所以你每次都獲得前一個 <code><img></code>的回傳的 <code>src</code> 值。解法是,記住,在每個事件中,事件處理器的目標是 <code><img></code> ,如何獲得事件物件的資訊呢?</li> + <li>Run a function, passing it the returned <code>src</code> value as a parameter. You can call this function whatever you like.</li> + <li>This event handler function should set the <code>src</code> attribute value of the <code>displayed-img <img></code> to the <code>src</code> value passed in as a parameter. We've already provided you with a line that stores a reference to the relevant <code><img></code> in a variable called <code>displayedImg</code>. Note that we want a defined named function here.</li> +</ol> + +<h3 id="寫一個讓暗化亮化按鈕可以運作的處理器">寫一個讓暗化/亮化按鈕可以運作的處理器</h3> + +<p>That just leaves our darken/lighten <code><button></code> — we've already provided a line that stores a reference to the <code><button></code> in a variable called <code>btn</code>. You need to add an <code>onclick</code> handler that:</p> + +<ol> + <li>Checks the current class name set on the <code><button></code> — you can again achieve this by using <code>getAttribute()</code>.</li> + <li>If the class name is <code>"dark"</code>, changes the <code><button></code> class to <code>"light"</code> (using <code><a href="/en-US/docs/Web/API/Element/setAttribute">setAttribute()</a></code>), its text content to "Lighten", and the {{cssxref("background-color")}} of the overlay <code><div></code> to <code>"rgba(0,0,0,0.5)"</code>.</li> + <li>If the class name not <code>"dark"</code>, changes the <code><button></code> class to <code>"dark"</code>, its text content back to "Darken", and the {{cssxref("background-color")}} of the overlay <code><div></code> to <code>"rgba(0,0,0,0)"</code>.</li> +</ol> + +<p>The following lines provide a basis for achieving the changes stipulated in points 2 and 3 above.</p> + +<pre class="brush: js">btn.setAttribute('class', xxx); +btn.textContent = xxx; +overlay.style.backgroundColor = xxx;</pre> + +<h2 id="提醒與提示">提醒與提示</h2> + +<ul> + <li>你完全不需要去編輯任何的HTML或CSS。</li> +</ul> + +<h2 id="評量">評量</h2> + +<p>If you are following this assessment as part of an organized course, you should be able to give your work to your teacher/mentor for marking. If you are self-learning, then you can get the marking guide fairly easily by asking on the <a href="https://discourse.mozilla-community.org/t/learning-web-development-marking-guides-and-questions/16294">Learning Area Discourse thread</a>, or in the <a href="irc://irc.mozilla.org/mdn">#mdn</a> IRC channel on <a href="https://wiki.mozilla.org/IRC">Mozilla IRC</a>. Try the exercise first — there is nothing to be gained by cheating!</p> + +<p>{{PreviousMenu("Learn/JavaScript/Building_blocks/Events", "Learn/JavaScript/Building_blocks")}}</p> diff --git a/files/zh-tw/learn/javascript/building_blocks/index.html b/files/zh-tw/learn/javascript/building_blocks/index.html new file mode 100644 index 0000000000..500b7d28ed --- /dev/null +++ b/files/zh-tw/learn/javascript/building_blocks/index.html @@ -0,0 +1,52 @@ +--- +title: JavaScript building blocks +slug: Learn/JavaScript/Building_blocks +tags: + - JavaScript + - TopicStub + - 事件 + - 入門者 + - 函式 + - 指南 + - 模組 + - 評量 + - 迴圈 +translation_of: Learn/JavaScript/Building_blocks +--- +<div>{{LearnSidebar}}</div> + +<p class="summary">在本單元中,我們繼續介紹所有JavaScript的關鍵基本功能,將注意力轉向常見的代碼塊類型,如條件語句,循環,函數和事件。 你已經在課程中看到了這些東西,但只是順便說一下 - 在這裡我們將明確地討論它。</p> + +<h2 id="先決條件">先決條件</h2> + +<p>開始這個模組之前,你應該已經熟悉 <a href="/en-US/docs/Learn/HTML/Introduction_to_HTML">HTML</a> 和 <a href="/en-US/docs/Learn/CSS/Introduction_to_CSS">CSS</a> 的基礎知識了,你也應該閱讀完前一個模組 - <a href="/en-US/docs/Learn/JavaScript/First_steps">JavaScript 入門</a> - 的內容了。</p> + +<div class="note"> +<p><strong>注意</strong>: 假如你正使用平板、電腦或任何無法讓你可以建立檔案的裝置時,你可以試著透過線上程式碼工具 (像是 <a href="http://jsbin.com/">JSBin</a> 或 <a href="https://thimble.mozilla.org/">Thimble</a>) 測試文章的測試碼。</p> +</div> + +<h2 id="指南">指南</h2> + +<dl> + <dt><a href="https://developer.mozilla.org/zh-TW/docs/Learn/JavaScript/Building_blocks/%E6%A2%9D%E4%BB%B6">在代碼中做出決定 - 條件</a></dt> + <dd>在任何編程語言中,代碼都需要根據不同的輸入做出決策並相應地執行操作。 例如,在遊戲中,如果玩家的生命數量為0,則遊戲結束。 在天氣應用程序中,如果在早上查看,則顯示日出圖形; 如果是夜晚,則顯示星星和月亮。 在本文中,我們將探討條件結構如何在JavaScript中工作。</dd> + <dt><a href="https://developer.mozilla.org/zh-TW/docs/Learn/JavaScript/Building_blocks/Looping_code" rel="nofollow">程式碼迴圈</a></dt> + <dd>有時候你需要超過一行的程式碼完成一項任務,舉例來說:尋找一個擁有許多名字的清單。透過編輯程式,迴圈可以幫助你完美的完成這項工作,在本文中,我們將探討迴圈的結構如何在 JavaScript 中運作。</dd> + <dt><a href="https://developer.mozilla.org/zh-TW/docs/Learn/JavaScript/Building_blocks/Functions" rel="nofollow">函式 — 可重複使用的程式碼區塊</a></dt> + <dd>撰寫程式的另一個基本概念是函式 (function),它允許你在一個定義好的區塊內,存放一些程式碼。定義好的函式後,無論你需要在一個單一簡短的指令列用到它,或者是重複使用相同的片段程式碼,你都可以不段重複地呼叫這些函式執行對應的內容。在本文中,我們將探索函式的基本概念,像是基本語法、如何定義函式內容、以及函式將會使用的參數。</dd> + <dt><a href="https://developer.mozilla.org/zh-TW/docs/Learn/JavaScript/Building_blocks/Build_your_own_function" rel="nofollow">建立自己的函式</a></dt> + <dd>前面許多文章已經提到大部分的基本理論基礎了,在本文中,我們將分享一個實際的經驗,你將學習到關於打造自定義函式的實務範例。透過這樣的學習方式,我們也進一步解釋一些函式相關的細節知識。</dd> + <dt><a href="https://developer.mozilla.org/zh-TW/docs/Learn/JavaScript/Building_blocks/Return_values" rel="nofollow">函式回傳值</a></dt> + <dd>這堂課程中最後一個想要說明的基本概念就是函式的回傳值,一些函式執行完畢後,不會回傳一個數值;但有些函式則會。理解這些函式的回傳值是重要的概念,本文中,你將學會如何在自定義的函式中,回傳有用的數值提供給其他函式使用。</dd> + <dt><a href="https://developer.mozilla.org/zh-TW/docs/Learn/JavaScript/Building_blocks/Events" rel="nofollow">事件介紹</a></dt> + <dd>事件代表你所撰寫的程式在一套系統內所產生的動作或發生的事情,舉例來說:假如一位使用者在網頁點擊一個按鈕時,你可能想要讓使用者點擊該按鈕後,在畫面呈現一個訊息方塊。在本課程最後一篇文章內,我們將討論一些與事件相關的重要概念、以及這些事件在瀏覽器中,如何呈現給使用者。</dd> +</dl> + +<h2 id="評量">評量</h2> + +<p>下方的試題將會測驗你對於上述幾項概念的 JavaScript 基本知識。</p> + +<dl> + <dt><a href="https://developer.mozilla.org/zh-TW/docs/Learn/JavaScript/Building_blocks/Image_gallery">圖庫</a></dt> + <dd>我們已經看過許多 JavaScript 的基礎程式碼,我們將測驗你關於迴圈、函式、條件式迴圈與事件等相關的知識,測驗的方式是透過建立一個由 JavaScript 打造而成的圖庫應用程式。</dd> +</dl> diff --git a/files/zh-tw/learn/javascript/building_blocks/looping_code/index.html b/files/zh-tw/learn/javascript/building_blocks/looping_code/index.html new file mode 100644 index 0000000000..0e1e400b4d --- /dev/null +++ b/files/zh-tw/learn/javascript/building_blocks/looping_code/index.html @@ -0,0 +1,928 @@ +--- +title: 循環代碼 +slug: Learn/JavaScript/Building_blocks/Looping_code +translation_of: Learn/JavaScript/Building_blocks/Looping_code +--- +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenuNext("Learn/JavaScript/Building_blocks/conditionals","Learn/JavaScript/Building_blocks/Functions", "Learn/JavaScript/Building_blocks")}}</div> + +<p class="summary">編程語言對於快速完成重複性任務非常有用,從多個基本計算到幾乎任何其他需要完成大量類似工作的情況。 在這裡,我們將看看JavaScript中可用於處理此類需求的循環結構。</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Prerequisites:</th> + <td>Basic computer literacy, a basic understanding of HTML and CSS, <a href="/en-US/docs/Learn/JavaScript/First_steps">JavaScript first steps</a>.</td> + </tr> + <tr> + <th scope="row">Objective:</th> + <td>To understand how to use loops in JavaScript.</td> + </tr> + </tbody> +</table> + +<h2 id="保持循環">保持循環</h2> + +<p>循環,循環,循環。 除了與受歡迎的早餐穀物,過山車和音樂作品有關聯,它們還是編程中的關鍵概念。 編程循環都是一遍又一遍地做同一件事-在編程方面被稱為迭代。</p> + +<p>讓我們考慮一個農民的例子,他要確保他有足夠的食物來養家糊口。 他可能使用以下循環來實現此目的:</p> + +<p><br> + <img alt="" src="https://mdn.mozillademos.org/files/13755/loop_js-02-farm.png" style="display: block; margin: 0 auto;"></p> + +<p>循環通常具有以下一項或多項功能:</p> + +<ul> + <li> 一個用一定值初始化的計數器-這是循環的起點(上面的“開始:我沒有食物”)。</li> + <li>一種條件,它是對/錯測試,用於確定循環是繼續運行還是停止(通常在計數器達到某個值時)。 “我是否有足夠的食物?”對此進行了說明。 以上。 假設他需要10份食物來養家糊口的話。</li> + <li>一個迭代器,通常在每個連續循環上使計數器增加一小部分,直到條件不再成立為止。 上面我們沒有明確說明這一點,但是我們可以考慮一下農民每小時可以收集2份食物。 每小時之後,他收集的食物數量增加了2,然後他檢查是否有足夠的食物。 如果他已達到10個部分(此時條件不再成立,則循環退出),他可以停止收集並回家。</li> +</ul> + +<p>In {{glossary("pseudocode")}}, this would look something like the following:</p> + +<pre class="notranslate">loop(food = 0; foodNeeded = 10) { + if (food = foodNeeded) { + exit loop; + // We have enough food; let's go home + } else { + food += 2; // Spend an hour collecting 2 more food + // loop will then run again + } +}</pre> + +<p>因此,所需的食物數量設置為10,而農民當前擁有的食物數量設置為0。在循環的每次迭代中,我們檢查農民擁有的食物數量是否等於他所需的數量。 如果是這樣,我們可以退出循環。 如果不是這樣,農民將花一個小時收集兩份食物,然後循環再次運行。</p> + +<h3 id="不用麻煩">不用麻煩</h3> + +<p>在這一點上,您可能了解了循環背後的高級概念,但您可能在想:“好,很好,但這如何幫助我編寫更好的JavaScript代碼?” 如前所述,循環與一次又一次地執行同一操作有關,這對於快速完成重複性任務非常有用。</p> + +<p>通常,代碼在每次循環的每次迭代中都會略有不同,這意味著您可以完成全部相似但略有不同的任務,一般情況,如果您要執行許多不同的計算,則需要不斷地執行不同的式子,而不能一遍又一遍重複!</p> + +<p>讓我們看一個示例,以完美地說明為什麼循環是如此便利。 Let's say we wanted to draw 100 random circles on a {{htmlelement("canvas")}} element (press the <em>Update</em> button to run the example again and again to see different random sets):</p> + +<div class="hidden"> +<h6 id="Hidden_code">Hidden code</h6> + +<pre class="brush: html notranslate"><!DOCTYPE html> +<html> + <head> + <meta charset="utf-8"> + <title>Random canvas circles</title> + <style> + html { + width: 100%; + height: inherit; + background: #ddd; + } + + canvas { + display: block; + } + + body { + margin: 0; + } + + button { + position: absolute; + top: 5px; + left: 5px; + } + </style> + </head> + <body> + + <button>Update</button> + + <canvas></canvas> + + + <script> + var btn = document.querySelector('button'); + var canvas = document.querySelector('canvas'); + var ctx = canvas.getContext('2d'); + + var WIDTH = document.documentElement.clientWidth; + var HEIGHT = document.documentElement.clientHeight; + + canvas.width = WIDTH; + canvas.height = HEIGHT; + + function random(number) { + return Math.floor(Math.random()*number); + } + + function draw() { + ctx.clearRect(0,0,WIDTH,HEIGHT); + for (var i = 0; i < 100; i++) { + ctx.beginPath(); + ctx.fillStyle = 'rgba(255,0,0,0.5)'; + ctx.arc(random(WIDTH), random(HEIGHT), random(50), 0, 2 * Math.PI); + ctx.fill(); + } + } + + btn.addEventListener('click',draw); + + </script> + + </body> +</html></pre> +</div> + +<p>{{ EmbedLiveSample('Hidden_code', '100%', 400, "", "", "hide-codepen-jsfiddle") }}</p> + +<p>您現在不必了解所有代碼,但讓我們看一下實際繪製100個圓圈的代碼部分:</p> + +<pre class="brush: js notranslate">for (var i = 0; i < 100; i++) { + ctx.beginPath(); + ctx.fillStyle = 'rgba(255,0,0,0.5)'; + ctx.arc(random(WIDTH), random(HEIGHT), random(50), 0, 2 * Math.PI); + ctx.fill(); +}</pre> + +<ul> + <li><code>代碼前面定義的random(),返回0到x-1之間的整數。</code></li> + <li><code>WIDTH和HEIGHT是內部瀏覽器窗口的寬度和高度。</code></li> +</ul> + +<p>您應該了解基本概念-我們正在使用一個循環來運行此代碼的100次迭代,每個迭代在頁面上的隨機位置繪製一個圓圈。 無論我們繪製100個圓,1000個還是10,000個,所需的代碼量都是相同的。 只需更改一個數字。</p> + +<p>如果我們不在此處使用循環,則必須為每個要繪製的圓重複以下代碼:</p> + +<pre class="brush: js notranslate">ctx.beginPath(); +ctx.fillStyle = 'rgba(255,0,0,0.5)'; +ctx.arc(random(WIDTH), random(HEIGHT), random(50), 0, 2 * Math.PI); +ctx.fill();</pre> + +<p>這將變得很無聊,並且很難很快維護。 循環確實是最好的。</p> + +<h2 id="循環的規範">循環的規範</h2> + +<p>讓我們開始探索一些特定的循環結構。 第一個是for循環,您將在大多數時候使用它,它具有以下語法:</p> + +<pre class="notranslate">for (initializer; exit-condition; final-expression) { + // code to run +}</pre> + +<p>這裡我們有:</p> + +<ol> + <li>關鍵字“ for”,即跟隨其後的一些括號。</li> + <li>在括號內,我們有三個項目,以 ; 分隔: + <ol> + <li>初始化程序-通常是一個設置為數字的變量,該變量將遞增以計算循環運行的次數。 有時也稱為計數器變量。</li> + <li>退出條件-如前所述,它定義了循環何時應停止循環。 通常,這是一個具有比較運算符的表達式,該測試用於檢驗是否滿足退出條件。</li> + <li>最終表達式—每當循環經過完整的迭代時,總是對它進行評估(或運行)。 它通常用於遞增(或在某些情況下遞減)計數器變量,以使其更接近退出條件值。</li> + </ol> + </li> + <li>一些花括號包含一個代碼塊-每次循環迭代時都將運行此代碼。</li> +</ol> + +<p>讓我們看一個真實的例子,以便我們可以更清楚地看到它們的作用。</p> + +<pre class="brush: js notranslate">var cats = ['Bill', 'Jeff', 'Pete', 'Biggles', 'Jasmin']; +var info = 'My cats are called '; +var para = document.querySelector('p'); + +for (var i = 0; i < cats.length; i++) { + info += cats[i] + ', '; +} + +para.textContent = info;</pre> + +<p>這為我們提供了以下輸出:</p> + +<div class="hidden"> +<h6 id="Hidden_code_2">Hidden code 2</h6> + +<pre class="brush: html notranslate"><!DOCTYPE html> +<html> + <head> + <meta charset="utf-8"> + <title>Basic for loop example</title> + <style> + + </style> + </head> + <body> + + <p></p> + + + <script> + var cats = ['Bill', 'Jeff', 'Pete', 'Biggles', 'Jasmin']; + var info = 'My cats are called '; + var para = document.querySelector('p'); + + for (var i = 0; i < cats.length; i++) { + info += cats[i] + ', '; + } + + para.textContent = info; + + </script> + + </body> +</html></pre> +</div> + +<p>{{ EmbedLiveSample('Hidden_code_2', '100%', 60, "", "", "hide-codepen-jsfiddle") }}</p> + +<div class="note"> +<p><strong>Note</strong>: You can find this <a href="https://github.com/mdn/learning-area/blob/master/javascript/building-blocks/loops/basic-for.html">example code on GitHub</a> too (also <a href="http://mdn.github.io/learning-area/javascript/building-blocks/loops/basic-for.html">see it running live</a>).</p> +</div> + +<p>這顯示了一個循環,該循環用於遍歷數組中的項目並對其進行處理-這是JavaScript中非常常見的模式。 這裡:</p> + +<ol> + <li>迭代器i從0開始(變量i = 0)。</li> + <li>它被告知運行,直到它不再小於cats數組的長度為止。 這很重要,退出條件顯示了循環仍將運行的條件。 因此,在這種情況下,儘管i <cats.length仍然為true,循環仍將運行。</li> + <li>在循環內部,我們將當前循環項(cats [i]是cats [無論 i 當時是什麼])與一個逗號和一個空格連接到info變量的末尾。 所以: + <ol> + <li>在第一次運行中,i = 0,因此cats [0] +','將連接到info(“ Bill,”)上。</li> + <li>在第二次運行中,i = 1,因此cats [1] +','將連接到info(“ Jeff,”)上</li> + <li>等等。 每次循環運行後,將1加到i(i ++),然後該過程將再次開始。</li> + </ol> + </li> + <li>當 i 等於cats.length時,循環將停止,瀏覽器將繼續循環下方的下一段代碼。</li> +</ol> + +<div class="note"> +<p><strong>Note</strong>: We have made the exit condition <code>i < cats.length</code>, not <code>i <= cats.length</code>, because computers count from 0, not 1 — we are starting <code>i</code> at <code>0</code>, and going up to <code>i = 4</code> (the index of the last array item). <code>cats.length</code> returns 5, as there are 5 items in the array, but we don't want to get up to <code>i = 5</code>, as that would return <code>undefined</code> for the last item (there is no array item with an index of 5). So therefore we want to go up to 1 less than <code>cats.length</code> (<code>i <</code>), not the same as <code>cats.length</code> (<code>i <=</code>).</p> +</div> + +<div class="note"> +<p><strong>Note</strong>: A common mistake with exit conditions is making them use "equal to" (<code>===</code>) rather than say "less than or equal to" (<code><=</code>). If we wanted to run our loop up to <code>i = 5</code>, the exit condition would need to be <code>i <= cats.length</code>. If we set it to <code>i === cats.length</code>, the loop would not run at all because <code>i</code> is not equal to <code>5</code> on the first loop iteration, so it would stop immediately.</p> +</div> + +<p>我們剩下的一個小問題是最終輸出語句的格式不太正確:</p> + +<blockquote> +<p>My cats are called Bill, Jeff, Pete, Biggles, Jasmin,</p> +</blockquote> + +<p>理想情況下,我們希望在最終循環迭代中更改串聯,以使句子的末尾沒有逗號。 好吧,沒問題-我們可以很高興地在for循環中插入一個條件來處理這種特殊情況:</p> + +<pre class="brush: js notranslate">for (var i = 0; i < cats.length; i++) { + if (i === cats.length - 1) { + info += 'and ' + cats[i] + '.'; + } else { + info += cats[i] + ', '; + } +}</pre> + +<div class="note"> +<p><strong>Note</strong>: You can find this <a href="https://github.com/mdn/learning-area/blob/master/javascript/building-blocks/loops/basic-for-improved.html">example code on GitHub</a> too (also <a href="http://mdn.github.io/learning-area/javascript/building-blocks/loops/basic-for-improved.html">see it running live</a>).</p> +</div> + +<div class="warning"> +<p><strong>Important</strong>: With for — as with all loops — you must make sure that the initializer is iterated so that it eventually reaches the exit condition. If not, the loop will go on forever, and either the browser will force it to stop, or it will crash. This is called an <strong>infinite loop</strong>.</p> +</div> + +<h2 id="中斷退出循環">中斷退出循環</h2> + +<p>如果要在所有迭代完成之前退出循環,可以使用break語句。 在查看switch語句時,我們已經在上一篇文章中遇到了這一問題—當在switch語句中遇到與輸入表達式匹配的case時,break語句立即退出switch語句並移至其後的代碼上。</p> + +<p>循環也是如此,-break語句將立即退出循環,並使瀏覽器繼續執行緊隨其後的任何代碼。</p> + +<p>假設我們要搜索一系列聯繫人和電話號碼,然後僅返回我們要查找的號碼? 首先,提供一些簡單的HTML-文本 {{htmlelement(“ input”)}} 允許我們輸入要搜索的名稱,{{htmlelement(“ button”)}} 元素以提交搜索,以及 {{htmlelement (“ p”)}} 元素以在以下位置顯示結果:</p> + +<pre class="brush: html notranslate"><label for="search">Search by contact name: </label> +<input id="search" type="text"> +<button>Search</button> + +<p></p></pre> + +<p>Now on to the JavaScript:</p> + +<pre class="brush: js notranslate">var contacts = ['Chris:2232322', 'Sarah:3453456', 'Bill:7654322', 'Mary:9998769', 'Dianne:9384975']; +var para = document.querySelector('p'); +var input = document.querySelector('input'); +var btn = document.querySelector('button'); + +btn.addEventListener('click', function() { + var searchName = input.value; + input.value = ''; + input.focus(); + for (var i = 0; i < contacts.length; i++) { + var splitContact = contacts[i].split(':'); + if (splitContact[0] === searchName) { + para.textContent = splitContact[0] + '\'s number is ' + splitContact[1] + '.'; + break; + } else { + para.textContent = 'Contact not found.'; + } + } +});</pre> + +<div class="hidden"> +<h6 id="Hidden_code_3">Hidden code 3</h6> + +<pre class="brush: html notranslate"><!DOCTYPE html> +<html> + <head> + <meta charset="utf-8"> + <title>Simple contact search example</title> + <style> + + </style> + </head> + <body> + + <label for="search">Search by contact name: </label> + <input id="search" type="text"> + <button>Search</button> + + <p></p> + + + <script> + var contacts = ['Chris:2232322', 'Sarah:3453456', 'Bill:7654322', 'Mary:9998769', 'Dianne:9384975']; + var para = document.querySelector('p'); + var input = document.querySelector('input'); + var btn = document.querySelector('button'); + + btn.addEventListener('click', function() { + var searchName = input.value; + input.value = ''; + input.focus(); + for (var i = 0; i < contacts.length; i++) { + var splitContact = contacts[i].split(':'); + if (splitContact[0] === searchName) { + para.textContent = splitContact[0] + '\'s number is ' + splitContact[1] + '.'; + break; + } else if (i === contacts.length-1) + para.textContent = 'Contact not found.'; + } + }); + </script> + + </body> +</html></pre> +</div> + +<p>{{ EmbedLiveSample('Hidden_code_3', '100%', 100, "", "", "hide-codepen-jsfiddle") }}</p> + +<ol> + <li>首先,我們有一些變量定義-我們有一個聯繫信息陣列,每個項目都是一個字符串,其中包含用冒號分隔的姓名和電話號碼。</li> + <li>接下來,我們將事件監聽器附加到按鈕(btn),以便在按下按鈕時,將運行一些代碼來執行搜索並返回結果。</li> + <li>我們將輸入到文本輸入中的值存儲在一個名為searchName的變量中,然後清空文本輸入並再次對其進行聚焦,以準備進行下一次搜索。</li> + <li>現在到有趣的部分,for循環: + <ol> + <li>我們從0開始啟動計數器,運行循環直到計數器不再小於contact.length,然後在每次循環之後將i遞增1。</li> + <li>在循環內部,我們首先將當前觸點(contacts [i])分割為冒號字符,並將得到的兩個值存儲在名為 splitContact 的數組中。</li> + <li>然後,我們使用條件語句來測試splitContact [0](聯繫人的姓名)是否等於輸入的searchName。 如果是這樣,我們在段落中輸入一個字符串以報告聯繫人的電話號碼,然後使用break結束循環。</li> + </ol> + </li> + <li> + <p>在(contacts.length-1)迭代之後,如果聯繫人姓名與輸入的搜索不匹配,則將段落文本設置為“找不到聯繫人。”,然後循環繼續進行迭代。</p> + </li> +</ol> + +<div class="note"> +<p>Note: You can view the <a href="https://github.com/mdn/learning-area/blob/master/javascript/building-blocks/loops/contact-search.html">full source code on GitHub</a> too (also <a href="http://mdn.github.io/learning-area/javascript/building-blocks/loops/contact-search.html">see it running live</a>).</p> +</div> + +<h2 id="Skipping_iterations_with_continue">Skipping iterations with continue</h2> + +<p>The <a href="/en-US/docs/Web/JavaScript/Reference/Statements/continue">continue</a> statement works in a similar manner to <code>break</code>, but instead of breaking out of the loop entirely, it skips to the next iteration of the loop. Let's look at another example that takes a number as an input, and returns only the numbers that are squares of integers (whole numbers).</p> + +<p>The HTML is basically the same as the last example — a simple text input, and a paragraph for output. The JavaScript is mostly the same too, although the loop itself is a bit different:</p> + +<pre class="brush: js notranslate">var num = input.value; + +for (var i = 1; i <= num; i++) { + var sqRoot = Math.sqrt(i); + if (Math.floor(sqRoot) !== sqRoot) { + continue; + } + + para.textContent += i + ' '; +}</pre> + +<p>Here's the output:</p> + +<div class="hidden"> +<h6 id="Hidden_code_4">Hidden code 4</h6> + +<pre class="brush: html notranslate"><!DOCTYPE html> +<html> + <head> + <meta charset="utf-8"> + <title>Integer squares generator</title> + <style> + + </style> + </head> + <body> + + <label for="number">Enter number: </label> + <input id="number" type="text"> + <button>Generate integer squares</button> + + <p>Output: </p> + + + <script> + var para = document.querySelector('p'); + var input = document.querySelector('input'); + var btn = document.querySelector('button'); + + btn.addEventListener('click', function() { + para.textContent = 'Output: '; + var num = input.value; + input.value = ''; + input.focus(); + for (var i = 1; i <= num; i++) { + var sqRoot = Math.sqrt(i); + if (Math.floor(sqRoot) !== sqRoot) { + continue; + } + + para.textContent += i + ' '; + } + }); + </script> + + </body> +</html></pre> +</div> + +<p>{{ EmbedLiveSample('Hidden_code_4', '100%', 100, "", "", "hide-codepen-jsfiddle") }}</p> + +<ol> + <li>In this case, the input should be a number (<code>num</code>). The <code>for</code> loop is given a counter starting at 1 (as we are not interested in 0 in this case), an exit condition that says the loop will stop when the counter becomes bigger than the input <code>num</code>, and an iterator that adds 1 to the counter each time.</li> + <li>Inside the loop, we find the square root of each number using <a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/sqrt">Math.sqrt(i)</a>, then check whether the square root is an integer by testing whether it is the same as itself when it has been rounded down to the nearest integer (this is what <a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/floor">Math.floor()</a> does to the number it is passed).</li> + <li>If the square root and the rounded down square root do not equal one another (<code>!==</code>), it means that the square root is not an integer, so we are not interested in it. In such a case, we use the <code>continue</code> statement to skip on to the next loop iteration without recording the number anywhere.</li> + <li>If the square root IS an integer, we skip past the if block entirely so the <code>continue</code> statement is not executed; instead, we concatenate the current <code>i</code> value plus a space on to the end of the paragraph content.</li> +</ol> + +<div class="note"> +<p><strong>Note</strong>: You can view the <a href="https://github.com/mdn/learning-area/blob/master/javascript/building-blocks/loops/integer-squares.html">full source code on GitHub</a> too (also <a href="http://mdn.github.io/learning-area/javascript/building-blocks/loops/integer-squares.html">see it running live</a>).</p> +</div> + +<h2 id="while_and_do_..._while">while and do ... while</h2> + +<p><code>for</code> is not the only type of loop available in JavaScript. There are actually many others and, while you don't need to understand all of these now, it is worth having a look at the structure of a couple of others so that you can recognize the same features at work in a slightly different way.</p> + +<p>First, let's have a look at the <a href="/en-US/docs/Web/JavaScript/Reference/Statements/while">while</a> loop. This loop's syntax looks like so:</p> + +<pre class="notranslate">initializer +while (exit-condition) { + // code to run + + final-expression +}</pre> + +<p>This works in a very similar way to the for loop, except that the initializer variable is set before the loop, and the final-expression is included inside the loop after the code to run — rather than these two items being included inside the parentheses. The exit-condition is included inside the parentheses, which are preceded by the <code>while</code> keyword rather than <code>for</code>.</p> + +<p>The same three items are still present, and they are still defined in the same order as they are in the for loop — this makes sense, as you still have to have an initializer defined before you can check whether it has reached the exit-condition; the final-condition is then run after the code inside the loop has run (an iteration has been completed), which will only happen if the exit-condition has still not been reached.</p> + +<p>Let's have a look again at our cats list example, but rewritten to use a while loop:</p> + +<pre class="brush: js notranslate">var i = 0; + +while (i < cats.length) { + if (i === cats.length - 1) { + info += 'and ' + cats[i] + '.'; + } else { + info += cats[i] + ', '; + } + + i++; +}</pre> + +<div class="note"> +<p><strong>Note</strong>: This still works just the same as expected — have a look at it <a href="http://mdn.github.io/learning-area/javascript/building-blocks/loops/while.html">running live on GitHub</a> (also view the <a href="https://github.com/mdn/learning-area/blob/master/javascript/building-blocks/loops/while.html">full source code</a>).</p> +</div> + +<p>The <a href="/en-US/docs/Web/JavaScript/Reference/Statements/do...while">do...while</a> loop is very similar, but provides a variation on the while structure:</p> + +<pre class="notranslate">initializer +do { + // code to run + + final-expression +} while (exit-condition)</pre> + +<p>In this case, the initializer again comes first, before the loop starts. The <code>do</code> keyword directly precedes the curly braces containing the code to run and the final-expression.</p> + +<p>The differentiator here is that the exit-condition comes after everything else, wrapped in parentheses and preceded by a <code>while</code> keyword. In a <code>do...while</code> loop, the code inside the curly braces is always run once before the check is made to see if it should be executed again (in while and for, the check comes first, so the code might never be executed).</p> + +<p>Let's rewrite our cat listing example again to use a <code>do...while</code> loop:</p> + +<pre class="brush: js notranslate">var i = 0; + +do { + if (i === cats.length - 1) { + info += 'and ' + cats[i] + '.'; + } else { + info += cats[i] + ', '; + } + + i++; +} while (i < cats.length);</pre> + +<div class="note"> +<p><strong>Note</strong>: Again, this works just the same as expected — have a look at it <a href="http://mdn.github.io/learning-area/javascript/building-blocks/loops/do-while.html">running live on GitHub</a> (also view the <a href="https://github.com/mdn/learning-area/blob/master/javascript/building-blocks/loops/do-while.html">full source code</a>).</p> +</div> + +<div class="warning"> +<p><strong>Important</strong>: With while and do...while — as with all loops — you must make sure that the initializer is iterated so that it eventually reaches the exit condition. If not, the loop will go on forever, and either the browser will force it to stop, or it will crash. This is called an <strong>infinite loop</strong>.</p> +</div> + +<h2 id="Active_learning_Launch_countdown!">Active learning: Launch countdown!</h2> + +<p>In this exercise, we want you to print out a simple launch countdown to the output box, from 10 down to Blast off. Specifically, we want you to:</p> + +<ul> + <li>Loop from 10 down to 0. We've provided you with an initializer — <code>var i = 10;</code>.</li> + <li>For each iteration, create a new paragraph and append it to the output <code><div></code>, which we've selected using <code>var output = document.querySelector('.output');</code>. In comments, we've provided you with three code lines that need to be used somewhere inside the loop: + <ul> + <li><code>var para = document.createElement('p');</code> — creates a new paragraph.</li> + <li><code>output.appendChild(para);</code> — appends the paragraph to the output <code><div></code>.</li> + <li><code>para.textContent =</code> — makes the text inside the paragraph equal to whatever you put on the right hand side, after the equals sign.</li> + </ul> + </li> + <li>Different iteration numbers require different text to be put in the paragraph for that iteration (you'll need a conditional statement and multiple <code>para.textContent =</code> lines): + <ul> + <li>If the number is 10, print "Countdown 10" to the paragraph.</li> + <li>If the number is 0, print "Blast off!" to the paragraph.</li> + <li>For any other number, print just the number to the paragraph.</li> + </ul> + </li> + <li>Remember to include an iterator! However, in this example we are counting down after each iteration, not up, so you <strong>don't</strong> want <code>i++</code> — how do you iterate downwards?</li> +</ul> + +<p>If you make a mistake, you can always reset the example with the "Reset" button. If you get really stuck, press "Show solution" to see a solution.</p> + +<div class="hidden"> +<h6 id="Active_learning">Active learning</h6> + +<pre class="brush: html notranslate"><h2>Live output</h2> +<div class="output" style="height: 410px;overflow: auto;"> + +</div> + +<h2>Editable code</h2> +<p class="a11y-label">Press Esc to move focus away from the code area (Tab inserts a tab character).</p> +<textarea id="code" class="playable-code" style="height: 300px;width: 95%"> +var output = document.querySelector('.output'); +output.innerHTML = ''; + +// var i = 10; + +// var para = document.createElement('p'); +// para.textContent = ; +// output.appendChild(para); +</textarea> + +<div class="playable-buttons"> + <input id="reset" type="button" value="Reset"> + <input id="solution" type="button" value="Show solution"> +</div> +</pre> + +<p class="brush: js"></p> + +<p class="brush: js"></p> + +<p class="brush: js"></p> + +<pre class="brush: css notranslate">html { + font-family: sans-serif; +} + +h2 { + font-size: 16px; +} + +.a11y-label { + margin: 0; + text-align: right; + font-size: 0.7rem; + width: 98%; +} + +body { + margin: 10px; + background: #f5f9fa; +}</pre> + +<p class="brush: js"></p> + +<p class="brush: js"></p> + +<p class="brush: js"></p> + +<p class="brush: js"></p> + +<pre class="brush: js notranslate">var textarea = document.getElementById('code'); +var reset = document.getElementById('reset'); +var solution = document.getElementById('solution'); +var code = textarea.value; +var userEntry = textarea.value; + +function updateCode() { + eval(textarea.value); +} + +reset.addEventListener('click', function() { + textarea.value = code; + userEntry = textarea.value; + solutionEntry = jsSolution; + solution.value = 'Show solution'; + updateCode(); +}); + +solution.addEventListener('click', function() { + if(solution.value === 'Show solution') { + textarea.value = solutionEntry; + solution.value = 'Hide solution'; + } else { + textarea.value = userEntry; + solution.value = 'Show solution'; + } + updateCode(); +}); + +var jsSolution = 'var output = document.querySelector(\'.output\');\noutput.innerHTML = \'\';\n\nvar i = 10;\n\nwhile(i >= 0) {\n var para = document.createElement(\'p\');\n if(i === 10) {\n para.textContent = \'Countdown \' + i;\n } else if(i === 0) {\n para.textContent = \'Blast off!\';\n } else {\n para.textContent = i;\n }\n\n output.appendChild(para);\n\n i--;\n}'; +var solutionEntry = jsSolution; + +textarea.addEventListener('input', updateCode); +window.addEventListener('load', updateCode); + +// stop tab key tabbing out of textarea and +// make it write a tab at the caret position instead + +textarea.onkeydown = function(e){ + if (e.keyCode === 9) { + e.preventDefault(); + insertAtCaret('\t'); + } + + if (e.keyCode === 27) { + textarea.blur(); + } +}; + +function insertAtCaret(text) { + var scrollPos = textarea.scrollTop; + var caretPos = textarea.selectionStart; + + var front = (textarea.value).substring(0, caretPos); + var back = (textarea.value).substring(textarea.selectionEnd, textarea.value.length); + textarea.value = front + text + back; + caretPos = caretPos + text.length; + textarea.selectionStart = caretPos; + textarea.selectionEnd = caretPos; + textarea.focus(); + textarea.scrollTop = scrollPos; +} + +// Update the saved userCode every time the user updates the text area code + +textarea.onkeyup = function(){ + // We only want to save the state when the user code is being shown, + // not the solution, so that solution is not saved over the user code + if(solution.value === 'Show solution') { + userEntry = textarea.value; + } else { + solutionEntry = textarea.value; + } + + updateCode(); +};</pre> + +<p class="brush: js"></p> +</div> + +<p>{{ EmbedLiveSample('Active_learning', '100%', 880, "", "", "hide-codepen-jsfiddle") }}</p> + +<h2 id="Active_learning_Filling_in_a_guest_list">Active learning: Filling in a guest list</h2> + +<p>In this exercise, we want you to take a list of names stored in an array, and put them into a guest list. But it's not quite that easy — we don't want to let Phil and Lola in because they are greedy and rude, and always eat all the food! We have two lists, one for guests to admit, and one for guests to refuse.</p> + +<p>Specifically, we want you to:</p> + +<ul> + <li>Write a loop that will iterate from 0 to the length of the <code>people</code> array. You'll need to start with an initializer of <code>var i = 0;</code>, but what exit condition do you need?</li> + <li>During each loop iteration, check if the current array item is equal to "Phil" or "Lola" using a conditional statement: + <ul> + <li>If it is, concatenate the array item to the end of the <code>refused</code> paragraph's <code>textContent</code>, followed by a comma and a space.</li> + <li>If it isn't, concatenate the array item to the end of the <code>admitted</code> paragraph's <code>textContent</code>, followed by a comma and a space.</li> + </ul> + </li> +</ul> + +<p>We've already provided you with:</p> + +<ul> + <li><code>var i = 0;</code> — Your initializer.</li> + <li><code>refused.textContent +=</code> — the beginnings of a line that will concatenate something on to the end of <code>refused.textContent</code>.</li> + <li><code>admitted.textContent +=</code> — the beginnings of a line that will concatenate something on to the end of <code>admitted.textContent</code>.</li> +</ul> + +<p>Extra bonus question — after completing the above tasks successfully, you will be left with two lists of names, separated by commas, but they will be untidy — there will be a comma at the end of each one. Can you work out how to write lines that slice the last comma off in each case, and add a full stop to the end? Have a look at the <a href="/en-US/docs/Learn/JavaScript/First_steps/Useful_string_methods">Useful string methods</a> article for help.</p> + +<p>If you make a mistake, you can always reset the example with the "Reset" button. If you get really stuck, press "Show solution" to see a solution.</p> + +<div class="hidden"> +<h6 id="Active_learning_2">Active learning 2</h6> + +<pre class="brush: html notranslate"><h2>Live output</h2> +<div class="output" style="height: 100px;overflow: auto;"> + <p class="admitted">Admit: </p> + <p class="refused">Refuse: </p> +</div> + +<h2>Editable code</h2> +<p class="a11y-label">Press Esc to move focus away from the code area (Tab inserts a tab character).</p> +<textarea id="code" class="playable-code" style="height: 400px;width: 95%"> +var people = ['Chris', 'Anne', 'Colin', 'Terri', 'Phil', 'Lola', 'Sam', 'Kay', 'Bruce']; + +var admitted = document.querySelector('.admitted'); +var refused = document.querySelector('.refused'); +admitted.textContent = 'Admit: '; +refused.textContent = 'Refuse: ' + +// var i = 0; + +// refused.textContent += ; +// admitted.textContent += ; + +</textarea> + +<div class="playable-buttons"> + <input id="reset" type="button" value="Reset"> + <input id="solution" type="button" value="Show solution"> +</div> +</pre> + +<pre class="brush: css notranslate">html { + font-family: sans-serif; +} + +h2 { + font-size: 16px; +} + +.a11y-label { + margin: 0; + text-align: right; + font-size: 0.7rem; + width: 98%; +} + +body { + margin: 10px; + background: #f5f9fa; +}</pre> + +<pre class="brush: js notranslate">var textarea = document.getElementById('code'); +var reset = document.getElementById('reset'); +var solution = document.getElementById('solution'); +var code = textarea.value; +var userEntry = textarea.value; + +function updateCode() { + eval(textarea.value); +} + +reset.addEventListener('click', function() { + textarea.value = code; + userEntry = textarea.value; + solutionEntry = jsSolution; + solution.value = 'Show solution'; + updateCode(); +}); + +solution.addEventListener('click', function() { + if(solution.value === 'Show solution') { + textarea.value = solutionEntry; + solution.value = 'Hide solution'; + } else { + textarea.value = userEntry; + solution.value = 'Show solution'; + } + updateCode(); +}); + +var jsSolution = 'var people = [\'Chris\', \'Anne\', \'Colin\', \'Terri\', \'Phil\', \'Lola\', \'Sam\', \'Kay\', \'Bruce\'];\n\nvar admitted = document.querySelector(\'.admitted\');\nvar refused = document.querySelector(\'.refused\');\n\nadmitted.textContent = \'Admit: \';\nrefused.textContent = \'Refuse: \'\nvar i = 0;\n\ndo {\n if(people[i] === \'Phil\' || people[i] === \'Lola\') {\n refused.textContent += people[i] + \', \';\n } else {\n admitted.textContent += people[i] + \', \';\n }\n i++;\n} while(i < people.length);\n\nrefused.textContent = refused.textContent.slice(0,refused.textContent.length-2) + \'.\';\nadmitted.textContent = admitted.textContent.slice(0,admitted.textContent.length-2) + \'.\';'; +var solutionEntry = jsSolution; + +textarea.addEventListener('input', updateCode); +window.addEventListener('load', updateCode); + +// stop tab key tabbing out of textarea and +// make it write a tab at the caret position instead + +textarea.onkeydown = function(e){ + if (e.keyCode === 9) { + e.preventDefault(); + insertAtCaret('\t'); + } + + if (e.keyCode === 27) { + textarea.blur(); + } +}; + +function insertAtCaret(text) { + var scrollPos = textarea.scrollTop; + var caretPos = textarea.selectionStart; + + var front = (textarea.value).substring(0, caretPos); + var back = (textarea.value).substring(textarea.selectionEnd, textarea.value.length); + textarea.value = front + text + back; + caretPos = caretPos + text.length; + textarea.selectionStart = caretPos; + textarea.selectionEnd = caretPos; + textarea.focus(); + textarea.scrollTop = scrollPos; +} + +// Update the saved userCode every time the user updates the text area code + +textarea.onkeyup = function(){ + // We only want to save the state when the user code is being shown, + // not the solution, so that solution is not saved over the user code + if(solution.value === 'Show solution') { + userEntry = textarea.value; + } else { + solutionEntry = textarea.value; + } + + updateCode(); +};</pre> +</div> + +<p>{{ EmbedLiveSample('Active_learning_2', '100%', 680, "", "", "hide-codepen-jsfiddle") }}</p> + +<h2 id="Which_loop_type_should_you_use">Which loop type should you use?</h2> + +<p>For basic uses, <code>for</code>, <code>while</code>, and <code>do...while</code> loops are largely interchangeable. They can all be used to solve the same problems, and which one you use will largely depend on your personal preference — which one you find easiest to remember or most intuitive. Let's have a look at them again.</p> + +<p>First <code>for</code>:</p> + +<pre class="notranslate">for (initializer; exit-condition; final-expression) { + // code to run +}</pre> + +<p><code>while</code>:</p> + +<pre class="notranslate">initializer +while (exit-condition) { + // code to run + + final-expression +}</pre> + +<p>and finally <code>do...while</code>:</p> + +<pre class="notranslate">initializer +do { + // code to run + + final-expression +} while (exit-condition)</pre> + +<p>We would recommend <code>for</code>, at least to begin with, as it is probably the easiest for remembering everything — the initializer, exit-condition, and final-expression all have to go neatly into the parentheses, so it is easy to see where they are and check that you aren't missing them.</p> + +<div class="note"> +<p><strong>Note</strong>: There are other loop types/features too, which are useful in advanced/specialized situations and beyond the scope of this article. If you want to go further with your loop learning, read our advanced <a href="/en-US/docs/Web/JavaScript/Guide/Loops_and_iteration">Loops and iteration guide</a>.</p> +</div> + +<h2 id="Conclusion">Conclusion</h2> + +<p>This article has revealed to you the basic concepts behind, and different options available when, looping code in JavaScript. You should now be clear on why loops are a good mechanism for dealing with repetitive code, and be raring to use them in your own examples!</p> + +<p>If there is anything you didn't understand, feel free to read through the article again, or <a href="/en-US/Learn#Contact_us">contact us</a> to ask for help.</p> + +<h2 id="See_also">See also</h2> + +<ul> + <li><a href="/en-US/docs/Web/JavaScript/Guide/Loops_and_iteration">Loops and iteration in detail</a></li> + <li><a href="/en-US/docs/Web/JavaScript/Reference/Statements/for">for statement reference</a></li> + <li><a href="/en-US/docs/Web/JavaScript/Reference/Statements/while">while</a> and <a href="/en-US/docs/Web/JavaScript/Reference/Statements/do...while">do...while</a> references</li> + <li><a href="/en-US/docs/Web/JavaScript/Reference/Statements/break">break</a> and <a href="/en-US/docs/Web/JavaScript/Reference/Statements/continue">continue</a> references</li> + <li> + <p class="entry-title"><a href="https://www.impressivewebs.com/javascript-for-loop/">What’s the Best Way to Write a JavaScript For Loop?</a> — some advanced loop best practices</p> + </li> +</ul> + +<p>{{PreviousMenuNext("Learn/JavaScript/Building_blocks/conditionals","Learn/JavaScript/Building_blocks/Functions", "Learn/JavaScript/Building_blocks")}}</p> + +<h2 id="In_this_module">In this module</h2> + +<ul> + <li><a href="/en-US/docs/Learn/JavaScript/Building_blocks/conditionals">Making decisions in your code — conditionals</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Building_blocks/Looping_code">Looping code</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Building_blocks/Functions">Functions — reusable blocks of code</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Building_blocks/Build_your_own_function">Build your own function</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Building_blocks/Return_values">Function return values</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Building_blocks/Events">Introduction to events</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Building_blocks/Image_gallery">Image gallery</a></li> +</ul> diff --git a/files/zh-tw/learn/javascript/building_blocks/return_values/index.html b/files/zh-tw/learn/javascript/building_blocks/return_values/index.html new file mode 100644 index 0000000000..f77f37d46c --- /dev/null +++ b/files/zh-tw/learn/javascript/building_blocks/return_values/index.html @@ -0,0 +1,172 @@ +--- +title: 函數回傳值 +slug: Learn/JavaScript/Building_blocks/Return_values +translation_of: Learn/JavaScript/Building_blocks/Return_values +--- +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenuNext("Learn/JavaScript/Building_blocks/Build_your_own_function","Learn/JavaScript/Building_blocks/Events", "Learn/JavaScript/Building_blocks")}}</div> + +<p class="summary">我們將在本課程中討論最後一個基本概念,即關閉函數 - 回傳值。 有些函數在完成後沒有回傳重要值,但其他函數會,並且了解它們的值是什麼,如何在代碼中使用它們以及如何使自己的自定義函數返回有用值非常重要。 我們將在下面介紹所有這些內容。</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Prerequisites:</th> + <td> + <p>Basic computer literacy, a basic understanding of HTML and CSS, <a href="/en-US/docs/Learn/JavaScript/First_steps">JavaScript first steps</a>, <a href="/en-US/docs/Learn/JavaScript/Building_blocks/Functions">Functions — reusable blocks of code</a>.</p> + </td> + </tr> + <tr> + <th scope="row">Objective:</th> + <td>To understand function return values, and how to make use of them.</td> + </tr> + </tbody> +</table> + +<h2 id="What_are_return_values">What are return values?</h2> + +<p><strong>Return values</strong> are just what they sound like — values returned by the function when it completes. You've already met return values a number of times, although you may not have thought about them explicitly. Let's return to some familiar code:</p> + +<pre class="brush: js">var myText = 'I am a string'; +var newString = myText.replace('string', 'sausage'); +console.log(newString); +// the replace() string function takes a string, +// replaces one substring with another, and returns +// a new string with the replacement made</pre> + +<p>We saw exactly this block of code in our first function article. We are invoking the <a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replace">replace()</a> function on the <code>myText</code> string, and passing it two parameters — the substring to find, and the substring to replace it with. When this function completes (finishes running), it returns a value, which is a new string with the replacement made. In the code above, we are saving this return value as the value of the <code>newString</code> variable.</p> + +<p>If you look at the replace function MDN reference page, you'll see a section called <a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replace#Return_value">Return value</a>. It is very useful to know and understand what values are returned by functions, so we try to include this information wherever possible.</p> + +<p>Some functions don't return a return value as such (in our reference pages, the return value is listed as <code>void</code> or <code>undefined</code> in such cases). For example, in the <a href="https://github.com/mdn/learning-area/blob/master/javascript/building-blocks/functions/function-stage-4.html#L50">displayMessage() function</a> we built in the previous article, no specific value is returned as a result of the function being invoked. It just makes a box appear somewhere on the screen — that's it!</p> + +<p>Generally, a return value is used where the function is an intermediate step in a calculation of some kind. You want to get to a final result, which involves some values. Those values need to be calculated by a function, which then returns the results so they can be used in the next stage of the calculation.</p> + +<h3 id="Using_return_values_in_your_own_functions">Using return values in your own functions</h3> + +<p>To return a value from a custom function, you need to use ... wait for it ... the <a href="/en-US/docs/Web/JavaScript/Reference/Statements/return">return</a> keyword. We saw this in action recently in our <a href="https://github.com/mdn/learning-area/blob/master/javascript/building-blocks/loops/random-canvas-circles.html">random-canvas-circles.html</a> example. Our <code>draw()</code> function draws 100 random circles somewhere on an HTML {{htmlelement("canvas")}}:</p> + +<pre class="brush: js">function draw() { + ctx.clearRect(0,0,WIDTH,HEIGHT); + for (var i = 0; i < 100; i++) { + ctx.beginPath(); + ctx.fillStyle = 'rgba(255,0,0,0.5)'; + ctx.arc(random(WIDTH), random(HEIGHT), random(50), 0, 2 * Math.PI); + ctx.fill(); + } +}</pre> + +<p>Inside each loop iteration, three calls are made to the <code>random()</code> function, to generate a random value for the current circle's x coordinate, y coordinate, and radius, respectively. The <code>random()</code> function takes one parameter — a whole number — and it returns a whole random number between 0 and that number. It looks like this:</p> + +<pre class="brush: js">function randomNumber(number) { + return Math.floor(Math.random()*number); +}</pre> + +<p>This could be written as follows:</p> + +<pre class="brush: js">function randomNumber(number) { + var result = Math.floor(Math.random()*number); + return result; +}</pre> + +<p>But the first version is quicker to write, and more compact.</p> + +<p>We are returning the result of the calculation <code>Math.floor(Math.random()*number)</code> each time the function is called. This return value appears at the point the function was called, and the code continues. So for example, if we ran the following line:</p> + +<pre class="brush: js">ctx.arc(random(WIDTH), random(HEIGHT), random(50), 0, 2 * Math.PI);</pre> + +<p>and the three <code>random()</code> calls returned the values 500, 200, and 35, respectively, the line would actually be run as if it were this:</p> + +<pre class="brush: js">ctx.arc(500, 200, 35, 0, 2 * Math.PI);</pre> + +<p>The function calls on the line are run first and their return values substituted for the function calls, before the line itself is then executed.</p> + +<h2 id="Active_learning_our_own_return_value_function">Active learning: our own return value function</h2> + +<p>Let's have a go at writing our own functions featuring return values.</p> + +<ol> + <li>First of all, make a local copy of the <a href="https://github.com/mdn/learning-area/blob/master/javascript/building-blocks/functions/function-library.html">function-library.html</a> file from GitHub. This is a simple HTML page containing a text {{htmlelement("input")}} field and a paragraph. There's also a {{htmlelement("script")}} element in which we have stored a reference to both HTML elements in two variables. This little page will allow you to enter a number into the text box, and display different numbers related to it in the paragraph below.</li> + <li>Let's add some useful functions to this <code><script></code> element. Below the existing two lines of JavaScript, add the following function definitions: + <pre class="brush: js">function squared(num) { + return num * num; +} + +function cubed(num) { + return num * num * num; +} + +function factorial(num) { + var x = num; + while (x > 1) { + num *= x-1; + x--; + } + return num; +}</pre> + The <code>squared()</code> and <code>cubed()</code> functions are fairly obvious — they return the square or cube of the number given as a parameter. The <code>factorial()</code> function returns the <a href="https://en.wikipedia.org/wiki/Factorial">factorial</a> of the given number.</li> + <li>Next, we're going to include a way to print out information about the number entered into the text input. Enter the following event handler below the existing functions: + <pre class="brush: js">input.onchange = function() { + var num = input.value; + if (isNaN(num)) { + para.textContent = 'You need to enter a number!'; + } else { + para.textContent = num + ' squared is ' + squared(num) + '. ' + + num + ' cubed is ' + cubed(num) + '. ' + + num + ' factorial is ' + factorial(num) + '.'; + } +}</pre> + + <p>Here we are creating an <code>onchange</code> event handler that runs whenever the change event fires on the text input — that is, when a new value is entered into the text input, and submitted (enter a value then press tab for example). When this anonymous function runs, the existing value entered into the input is stored in the <code>num</code> variable.</p> + + <p>Next, we do a conditional test — if the entered value is not a number, we print an error message into the paragraph. The test looks at whether the expression <code>isNaN(num)</code> returns true. We use the <a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/isNaN">isNaN()</a> function to test whether the num value is not a number — if so, it returns <code>true</code>, and if not, <code>false</code>.</p> + + <p>If the test returns <code>false</code>, the <code>num</code> value is a number, so we print out a sentence inside the paragraph element stating what the square, cube, and factorial of the number are. The sentence calls the <code>squared()</code>, <code>cubed()</code>, and <code>factorial()</code> functions to get the required values.</p> + </li> + <li>Save your code, load it in a browser, and try it out.</li> +</ol> + +<div class="note"> +<p><strong>Note</strong>: If you have trouble getting the example to work, feel free to check your code against the <a href="https://github.com/mdn/learning-area/blob/master/javascript/building-blocks/functions/function-library-finished.html">finished version on GitHub</a> (<a href="http://mdn.github.io/learning-area/javascript/building-blocks/functions/function-library-finished.html">see it running live</a> also), or ask us for help.</p> +</div> + +<p>At this point, we'd like you to have a go at writing out a couple of functions of your own and adding them to the library. How about the square or cube root of the number, or the circumference of a circle with a radius of length <code>num</code>?</p> + +<p>This exercise has brought up a couple of important points besides being a study on how to use the <code>return</code> statement. In addition, we have:</p> + +<ul> + <li>Looked at another example of writing error handling into our functions. It is generally a good idea to check that any necessary parameters have been provided, and in the right datatype, and if they are optional, that some kind of default value is provided to allow for that. This way, your program will be less likely to throw errors.</li> + <li>Thought about the idea of creating a function library. As you go further into your programming career, you'll start to do the same kinds of things over and over again. It is a good idea to start keeping your own library of utility functions that you use very often — you can then copy them over to your new code, or even just apply it to any HTML pages where you need it.</li> +</ul> + +<h2 id="Conclusion">Conclusion</h2> + +<p>So there we have it — functions are fun, very useful and, although there's a lot to talk about in regards to their syntax and functionality, fairly understandable given the right articles to study.</p> + +<p>If there is anything you didn't understand, feel free to read through the article again, or <a href="/en-US/Learn#Contact_us">contact us</a> to ask for help.</p> + +<h2 id="See_also">See also</h2> + +<ul> + <li><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions">Functions in-depth</a> — a detailed guide covering more advanced functions-related information.</li> + <li><a href="https://www.impressivewebs.com/callback-functions-javascript/">Callback functions in JavaScript</a> — a common JavaScript pattern is to pass a function into another function as an argument, which is then called inside the first function. This is a little beyond the scope of this course, but worth studying before too long.</li> +</ul> + +<p>{{PreviousMenuNext("Learn/JavaScript/Building_blocks/Build_your_own_function","Learn/JavaScript/Building_blocks/Events", "Learn/JavaScript/Building_blocks")}}</p> + +<p> </p> + +<h2 id="In_this_module">In this module</h2> + +<ul> + <li><a href="/en-US/docs/Learn/JavaScript/Building_blocks/conditionals">Making decisions in your code — conditionals</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Building_blocks/Looping_code">Looping code</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Building_blocks/Functions">Functions — reusable blocks of code</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Building_blocks/Build_your_own_function">Build your own function</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Building_blocks/Return_values">Function return values</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Building_blocks/Events">Introduction to events</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Building_blocks/Image_gallery">Image gallery</a></li> +</ul> + +<p> </p> |