aboutsummaryrefslogtreecommitdiff
path: root/files/zh-tw/web/javascript/reference/functions/arrow_functions/index.html
diff options
context:
space:
mode:
authorPeter Bengtsson <mail@peterbe.com>2020-12-08 14:43:23 -0500
committerPeter Bengtsson <mail@peterbe.com>2020-12-08 14:43:23 -0500
commit218934fa2ed1c702a6d3923d2aa2cc6b43c48684 (patch)
treea9ef8ac1e1b8fe4207b6d64d3841bfb8990b6fd0 /files/zh-tw/web/javascript/reference/functions/arrow_functions/index.html
parent074785cea106179cb3305637055ab0a009ca74f2 (diff)
downloadtranslated-content-218934fa2ed1c702a6d3923d2aa2cc6b43c48684.tar.gz
translated-content-218934fa2ed1c702a6d3923d2aa2cc6b43c48684.tar.bz2
translated-content-218934fa2ed1c702a6d3923d2aa2cc6b43c48684.zip
initial commit
Diffstat (limited to 'files/zh-tw/web/javascript/reference/functions/arrow_functions/index.html')
-rw-r--r--files/zh-tw/web/javascript/reference/functions/arrow_functions/index.html340
1 files changed, 340 insertions, 0 deletions
diff --git a/files/zh-tw/web/javascript/reference/functions/arrow_functions/index.html b/files/zh-tw/web/javascript/reference/functions/arrow_functions/index.html
new file mode 100644
index 0000000000..8eac06ba55
--- /dev/null
+++ b/files/zh-tw/web/javascript/reference/functions/arrow_functions/index.html
@@ -0,0 +1,340 @@
+---
+title: 箭頭函式
+slug: Web/JavaScript/Reference/Functions/Arrow_functions
+translation_of: Web/JavaScript/Reference/Functions/Arrow_functions
+---
+<div>{{jsSidebar("Functions")}}</div>
+
+<p><strong>箭頭函式運算式</strong>(arrow function expression)擁有比<a href="/zh-TW/docs/Web/JavaScript/Reference/Operators/function">函式運算式</a>還簡短的語法。它沒有自己的 <code><a href="/zh-TW/docs/Web/JavaScript/Reference/Operators/this">this</a></code>、<a href="/zh-TW/docs/Web/JavaScript/Reference/Functions/arguments">arguments</a>、<a href="/zh-TW/docs/Web/JavaScript/Reference/Operators/super">super</a>、<a href="/zh-TW/docs/Web/JavaScript/Reference/Operators/new.target">new.target</a> 等語法。本函式運算式適用於非方法的函式,但不能被用作建構式(constructor)。</p>
+
+<div>{{EmbedInteractiveExample("pages/js/functions-arrow.html")}}</div>
+
+<h2 id="基本語法">基本語法</h2>
+
+<pre class="syntaxbox notranslate">(參數1, 參數2, …, 參數N) =&gt; { 陳述式; }
+
+(參數1, 參數2, …, 參數N) =&gt; 表示式;
+// 等相同(參數1, 參數2, …, 參數N) =&gt; { return 表示式; }
+
+// 只有一個參數時,括號才能不加:
+(單一參數) =&gt; { 陳述式; }
+單一參數 =&gt; { 陳述式; }
+
+//若無參數,就一定要加括號:
+() =&gt; { statements }
+</pre>
+
+<h2 id="進階語法">進階語法</h2>
+
+<pre class="syntaxbox notranslate">// 用大括號將內容括起來,返回一個物件字面值表示法:
+params =&gt; ({foo: bar})
+
+// 支援<a href="/zh-TW/docs/Web/JavaScript/Reference/Functions/rest_parameters">其餘參數</a>與<a href="/zh-TW/docs/Web/JavaScript/Reference/Functions/Default_parameters">預設參數</a>
+(param1, param2, ...rest) =&gt; { statements }
+(param1 = defaultValue1, param2, …, paramN = defaultValueN) =&gt; {
+statements }
+
+// 也支援 parameter list 的<a href="/zh-TW/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment">解構</a>
+var f = ([a, b] = [1, 2], {x: c} = {x: a + b}) =&gt; a + b + c; f(); // 6
+</pre>
+
+<h2 id="說明">說明</h2>
+
+<p>也可參閱 <a href="https://hacks.mozilla.org/2015/06/es6-in-depth-arrow-functions/">"ES6 In Depth: Arrow functions" on hacks.mozilla.org</a>。</p>
+
+<p>箭頭函式有兩個重要的特性:更短的函式寫法與 <code>this</code> 變數的非綁定。</p>
+
+<h3 id="更短的函式寫法">更短的函式寫法</h3>
+
+<pre class="brush: js notranslate">var elements = [
+ 'Hydrogen',
+ 'Helium',
+ 'Lithium',
+ 'Beryllium'
+];
+
+// 這段函式會輸出[8, 6, 7, 9]這個陣列
+elements.<a href="/zh-TW/docs/Web/JavaScript/Reference/Global_Objects/Array/map">map</a>(function(element) {
+ return element.length;
+});
+
+// 上方這種一般的函式,可以被改寫成下方的箭頭函式
+elements.map((element) =&gt; {
+  return element.length;
+}); // [8, 6, 7, 9]
+
+// 如果輸入的參數只有一個,我們可以移除掉外面的括號
+elements.map(element =&gt; {
+  return element.length;
+}); // [8, 6, 7, 9]
+
+// 當箭頭函式裡的內容只有'return'的時候,我們可以拿掉return和外面的大括號
+elements.map(element =&gt; element.length); // [8, 6, 7, 9]
+
+// 在這個範例中,因為我們只需要length這個屬性,所以也可以使用<a href="/zh-TW/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment">解構賦值</a>:
+// 下方的'length'對應到我們想取得的屬性,而'lengthFooBArX'只是很普通的變數名稱,
+// 可以被任意修改成你想要的名字
+elements.map(({ length: lengthFooBArX }) =&gt; lengthFooBArX); // [8, 6, 7, 9]
+
+// 上面這種解構賦值之後的參數也可以被改寫為下面這樣。但要注意的是,在這個範例中,
+// 我們不是要指定'length'這個值給一個虛構的屬性,而是這個變數的名稱'length'本身就是
+// 用來當成我們想從物件上取得的屬性
+elements.map(({ length }) =&gt; length); // [8, 6, 7, 9]
+</pre>
+
+<h3 id="this_不分家"><code>this</code> 不分家</h3>
+
+<p>在有箭頭函數之前,每個新函式是依據如何被呼叫來定義自己的 <code><a href="/zh-TW/docs/Web/JavaScript/Reference/Operators/this">this</a></code> 變數<br>
+ 例如:</p>
+
+<ul>
+ <li>在建構子時是一個新物件</li>
+ <li>在呼叫<a href="/zh-TW/docs/Web/JavaScript/Reference/Strict_mode">嚴格模式</a>函數時是 undefined</li>
+ <li>以物件方法呼叫時則為基礎物件</li>
+ <li>等等....</li>
+</ul>
+
+<p>事實證明這對物件導向程式設計來說並不理想。</p>
+
+<pre class="brush: js notranslate">function Person() {
+ // Person() 建構式將 this 定義為它自己的一個實體
+ this.age = 0;
+
+ setInterval(function growUp() {
+ // 在非嚴格模式下, growUp() 函式把 this 定義為全域物件
+  // (因為那是 growUp()執行的所在),
+ // 與 Person() 建構式所定義的 this 有所不同
+ this.age++;
+ }, 1000);
+}
+
+var p = new Person();</pre>
+
+<p>在 ECMAScript 3/5 裡面,有關 <code>this</code> 的問題,可以透過指派 <code>this</code> 值給可以關閉的變數解決。</p>
+
+<pre class="brush: js notranslate">function Person() {
+ var self = this; // 有些人喜歡 `that` 而不是 `self`.
+ // 選好一種取法後始終如一
+ self.age = 0;
+
+ setInterval(function growUp() {
+ // 這個 callback 參考 `self` 變數,為預期中的物件。
+ self.age++;
+ }, 1000);
+}</pre>
+
+<p>或者透過 <a href="/zh-TW/docs/Web/JavaScript/Reference/Global_Objects/Function/bind">bind</a> 函式來綁定 <code>this</code> 變數到指定函式(以上面為例,就是 <code>growUp()</code> 函式)。</p>
+
+<p>箭頭函式並不擁有自己的 <code>this 變</code>數<code>;</code>使用的 this <code>值來自</code>封閉的文本上下文,也就是說,箭頭函式遵循常規變量查找規則。因此,如果在當前範圍中搜索不到 this 變量時,他們最終會尋找其封閉範圍。</p>
+
+<p>因此,在以下程式碼內,傳遞給 <code>setInterval</code> 的 箭頭函式中的<code>this</code> ,會與封閉函式的 <code>this</code> 值相同:</p>
+
+<pre class="brush: js notranslate">function Person(){
+ this.age = 0;
+
+ setInterval(() =&gt; {
+ this.age++; // |this| 適切的參考了Person建構式所建立的物件
+ }, 1000);
+}
+
+var p = new Person();</pre>
+
+<h4 id="和嚴格模式的關係">和嚴格模式的關係</h4>
+
+<p>由於 <code>this</code> 變數具有詞彙上綁定意義,所以<a href="/zh-TW/docs/Web/JavaScript/Reference/Strict_mode">嚴格模式</a>的宣告對 <code>this</code> 的作用將被忽略。</p>
+
+<pre class="brush: js notranslate">var f = () =&gt; {'use strict'; return this};
+f() === window; // 或是 global 物件</pre>
+
+<p>但嚴格模式的其他作用依舊存在。</p>
+
+<h4 id="由_call_與_apply_函式呼叫">由 call 與 apply 函式呼叫</h4>
+
+<p>由於箭頭函式並沒有自己的 <code>this</code>,所以透過 <code>call()</code> 或 <code>apply()</code> 呼叫箭頭函式只能傳入參數。<code>thisArg</code> 將會被忽略。</p>
+
+<pre class="brush: js notranslate">var adder = {
+ base : 1,
+ add : function(a) {
+ var f = v =&gt; v + this.base;
+ return f(a);
+ },
+ addThruCall: function(a) {
+ var f = v =&gt; v + this.base;
+ var b = {
+ base : 2
+ };
+ return f.call(b, a);
+ }
+};
+console.log(adder.add(1)); // 顯示 2
+console.log(adder.addThruCall(1)); // 依舊顯示 2
+</pre>
+
+<h3 id="不綁定_arguments">不綁定 <code>arguments</code></h3>
+
+<p>箭頭函式並沒有自己的 <a href="/zh-TW/docs/Web/JavaScript/Reference/Functions/arguments"><code>arguments</code> 物件</a>。所以在此例中,<code>arguments</code> 只是參考到 enclosing 作用域裡面的相同變數:</p>
+
+<pre class="brush: js notranslate">var arguments = [1, 2, 3];
+var arr = () =&gt; arguments[0];
+
+arr(); // 1
+
+function foo(n) {
+ var f = () =&gt; arguments[0] + n; // <em>foo</em>'s implicit arguments binding. arguments[0] is n
+ return f();
+}
+
+foo(1); // 2</pre>
+
+<p>大多時候,使用<a href="/zh-TW/docs/Web/JavaScript/Reference/Functions/rest_parameters">其餘參數</a> 是取代 <code>arguments</code> 物件的較好方式。</p>
+
+<pre class="brush: js notranslate">function foo(n) {
+ var f = (...args) =&gt; args[0] + n;
+ return f(10);
+}
+
+foo(1); // 11</pre>
+
+<h3 id="將箭頭函式撰寫為方法">將箭頭函式撰寫為方法</h3>
+
+<p>如同前述,箭頭函式運算式最適合用在非方法的函式。來看看如果要把它們當成方法來用,會發生什麼事:</p>
+
+<pre class="brush: js notranslate"><code>'use strict';
+var obj = {
+ i: 10,
+ b: () =&gt; console.log(this.i, this),
+ c: function() {
+ console.log(this.i, this);
+ }
+}
+obj.b(); // 印出 undefined, Object {...}
+obj.c(); // 印出 10, Object {...}</code></pre>
+
+<p>箭頭函式並沒有自己的 <code>this</code>。另一個例子與 {{jsxref("Object.defineProperty()")}} 有關:</p>
+
+<pre class="brush: js notranslate">'use strict';
+
+var obj = {
+ a: 10
+};
+
+Object.defineProperty(obj, 'b', {
+ get: () =&gt; {
+ console.log(this.a, typeof this.a, this); // undefined 'undefined' Window {...} (or the global object)
+ return this.a + 10; // represents global object 'Window', therefore 'this.a' returns 'undefined'
+ }
+});
+</pre>
+
+<h3 id="使用_new_運算子">使用 <code>new</code> 運算子</h3>
+
+<p>箭頭函式不可作為建構式使用;若使用於建構式,會在使用 <code>new</code> 時候拋出錯誤。</p>
+
+<pre class="brush: js notranslate">var Foo = () =&gt; {};
+var foo = new Foo(); // TypeError: Foo is not a constructor</pre>
+
+<h3 id="使用_prototype_屬性">使用 <code>prototype</code> 屬性</h3>
+
+<p>箭頭函式並沒有原型(<code>prototype</code>)屬性。</p>
+
+<pre class="brush: js notranslate">var Foo = () =&gt; {};
+console.log(Foo.prototype); // undefined
+</pre>
+
+<h3 id="使用關鍵字_yield">使用關鍵字 <code>yield</code></h3>
+
+<p><code><a href="https://developer.mozilla.org/zh-TW/docs/Web/JavaScript/Reference/Operators/yield">yield</a></code> 關鍵字無法用於箭頭函式的 body(except when permitted within functions further nested within it)。因此,箭頭函式無法使用 generator。</p>
+
+<h2 id="函式主體(Function_body)">函式主體(Function body)</h2>
+
+<p>箭頭函式可以變成 concise body 或者平常使用的 block body。</p>
+
+<p>在 concise body 裡面只需要輸入運算式,就會附上內建的回傳。在 block body 裡面就必須附上明確的 <code>return</code> 宣告。</p>
+
+<pre class="brush: js notranslate"><code>var func = x =&gt; x * x; // concise 語法會內建 "return"
+var func = (x, y) =&gt; { return x + y; }; // block body 需要明確的 "return"</code></pre>
+
+<h2 id="回傳物件字面值">回傳物件字面值</h2>
+
+<p>請注意只使用 <code>params =&gt; {object:literal}</code> 並不會按照期望般回傳物件字面值(object literal)。</p>
+
+<pre class="brush: js notranslate"><code>var func = () =&gt; { foo: 1 }; // Calling func() returns undefined!
+var func = () =&gt; { foo: function() {} }; // SyntaxError: Unexpected token (</code></pre>
+
+<p>因為在大括弧(<code>{}</code>)裡面的文字會被解析為有序宣告(例如 <code>foo</code> 會被當作標記(label)、而不是物件的 key )</p>
+
+<p>要記得把物件字面值包在圓括弧內。</p>
+
+<pre class="brush: js notranslate"><code>var func = () =&gt; ({foo: 1});
+var func = () =&gt; ({ foo: function() {} }); </code>
+</pre>
+
+<h2 id="換行">換行</h2>
+
+<p>箭頭函式不可以在參數及箭頭間包含換行。</p>
+
+<pre class="brush: js notranslate"><code>var func = ()
+ =&gt; 1; // SyntaxError: expected expression, got '=&gt;'</code></pre>
+
+<h2 id="Parsing_order">Parsing order</h2>
+
+<p>箭頭函式的箭頭儘管不是操作符,但藉著<a href="https://developer.mozilla.org/zh-TW/docs/Web/JavaScript/Reference/Operators/Operator_Precedence">運算子優先等級</a>,箭頭函式有著和普通函式不相同的特殊解析規則。</p>
+
+<pre class="brush: js notranslate"><code>let callback;
+
+callback = callback || function() {}; // ok
+callback = callback || () =&gt; {}; // SyntaxError: invalid arrow-function arguments
+callback = callback || (() =&gt; {}); // ok</code></pre>
+
+<h2 id="更多範例">更多範例</h2>
+
+<pre class="brush: js notranslate">// 回傳 undefined 的箭頭函式
+let empty = () =&gt; {};
+
+(() =&gt; "foobar")() // 回傳 "foobar"
+
+var simple = a =&gt; a &gt; 15 ? 15 : a;
+simple(16); // 15
+simple(10); // 10
+
+let max = (a, b) =&gt; a &gt; b ? a : b;
+
+// Easy array filtering, mapping, ...
+
+var arr = [5, 6, 13, 0, 1, 18, 23];
+var sum = arr.reduce((a, b) =&gt; a + b); // 66
+var even = arr.filter(v =&gt; v % 2 == 0); // [6, 0, 18]
+var double = arr.map(v =&gt; v * 2); // [10, 12, 26, 0, 2, 36, 46]
+
+</pre>
+
+<h2 id="規範">規範</h2>
+
+<table class="standard-table">
+ <tbody>
+ <tr>
+ <th scope="col">規範</th>
+ <th scope="col">狀態</th>
+ <th scope="col">註解</th>
+ </tr>
+ <tr>
+ <td>{{SpecName('ES6', '#sec-arrow-function-definitions', 'Arrow Function Definitions')}}</td>
+ <td>{{Spec2('ES6')}}</td>
+ <td>Initial definition.</td>
+ </tr>
+ </tbody>
+</table>
+
+<h2 id="瀏覽器相容性">瀏覽器相容性</h2>
+
+<div>
+
+
+<p>{{Compat("javascript.functions.arrow_functions")}}</p>
+</div>
+
+<h2 id="參閱">參閱</h2>
+
+<ul>
+ <li><a href="https://hacks.mozilla.org/2015/06/es6-in-depth-arrow-functions/">"ES6 In Depth: Arrow functions" on hacks.mozilla.org</a></li>
+</ul>