diff options
Diffstat (limited to 'files/zh-tw/web/javascript/reference/operators')
17 files changed, 4552 insertions, 0 deletions
diff --git a/files/zh-tw/web/javascript/reference/operators/arithmetic_operators/index.html b/files/zh-tw/web/javascript/reference/operators/arithmetic_operators/index.html new file mode 100644 index 0000000000..a91f586c80 --- /dev/null +++ b/files/zh-tw/web/javascript/reference/operators/arithmetic_operators/index.html @@ -0,0 +1,308 @@ +--- +title: 算術運算子 +slug: Web/JavaScript/Reference/Operators/Arithmetic_Operators +translation_of: Web/JavaScript/Reference/Operators +--- +<div>{{jsSidebar("Operators")}}</div> + +<p><strong>算術運算子接受數值(資料型態為字串或變數都可)作為其運算子並回傳單個數值。 標準算術運算符號有加號(+),減號( - ),乘(*)和除(/)。</strong></p> + +<div>{{EmbedInteractiveExample("pages/js/expressions-arithmetic.html")}}</div> + + + +<h2 id="Addition_()"><a id="加法" name="加法">Addition (+)</a></h2> + +<p>加法運算子生成數字(運算元)的總和或字串串接。</p> + +<h3 id="Syntax">Syntax</h3> + +<pre class="syntaxbox"><strong>Operator:</strong> x + y +</pre> + +<h3 id="Examples">Examples</h3> + +<pre class="brush: js">// Number + Number -> addition +1 + 2 // 3 + +// Boolean + Number -> addition +true + 1 // 2 + +// Boolean + Boolean -> addition +false + false // 0 + +// Number + String -> concatenation +5 + 'foo' // "5foo" + +// String + Boolean -> concatenation +'foo' + false // "foofalse" + +// String + String -> concatenation +'foo' + 'bar' // "foobar" +</pre> + +<h2 id="Subtraction_(-)"><a id="減法" name="減法">Subtraction (-)</a></h2> + +<p>減法運算子能算出兩個運算元間的差異。</p> + +<h3 id="Syntax_2">Syntax</h3> + +<pre class="syntaxbox"><strong>Operator:</strong> x - y +</pre> + +<h3 id="Examples_2">Examples</h3> + +<pre class="brush: js">5 - 3 // 2 +3 - 5 // -2 +'foo' - 3 // NaN</pre> + +<h2 id="Division_()"><a id="除法" name="除法">Division (/)</a></h2> + +<p>The division operator produces the quotient of its operands where the left operand is the dividend and the right operand is the divisor.</p> + +<h3 id="Syntax_3">Syntax</h3> + +<pre class="syntaxbox"><strong>Operator:</strong> x / y +</pre> + +<h3 id="Examples_3">Examples</h3> + +<pre class="brush: js">1 / 2 // returns 0.5 in JavaScript +1 / 2 // returns 0 in Java +// (neither number is explicitly a floating point number) + +1.0 / 2.0 // returns 0.5 in both JavaScript and Java + +2.0 / 0 // returns Infinity in JavaScript +2.0 / 0.0 // returns Infinity too +2.0 / -0.0 // returns -Infinity in JavaScript</pre> + +<h2 id="Multiplication_(*)"><a id="乘法" name="乘法">Multiplication (*)</a></h2> + +<p>The multiplication operator produces the product of the operands.</p> + +<h3 id="Syntax_4">Syntax</h3> + +<pre class="syntaxbox"><strong>Operator:</strong> x * y +</pre> + +<h3 id="Examples_4">Examples</h3> + +<pre class="brush: js">2 * 2 // 4 +-2 * 2 // -4 +Infinity * 0 // NaN +Infinity * Infinity // Infinity +'foo' * 2 // NaN +</pre> + +<h2 id="Remainder_()"><a id="餘數運算" name="餘數運算">Remainder (%)</a></h2> + +<p>The remainder operator returns the remainder left over when one operand is divided by a second operand. It always takes the sign of the dividend.</p> + +<h3 id="Syntax_5">Syntax</h3> + +<pre class="syntaxbox"><strong>Operator:</strong> var1 % var2 +</pre> + +<h3 id="Examples_5">Examples</h3> + +<pre class="brush: js">12 % 5 // 2 +-1 % 2 // -1 +1 % -2 // 1 +NaN % 2 // NaN +1 % 2 // 1 +2 % 3 // 2 +-4 % 2 // -0 +5.5 % 2 // 1.5 +</pre> + +<h2 id="Exponentiation_(**)"><a id="指數運算" name="指數運算">Exponentiation (**)</a></h2> + +<p>The exponentiation operator returns the result of raising first operand to the power second operand. that is, <code>var1</code><sup><code>var2</code></sup>, in the preceding statement, where <code>var1</code> and <code>var2</code> are variables. Exponentiation operator is right associative. <code>a ** b ** c</code> is equal to <code>a ** (b ** c)</code>.</p> + +<h3 id="Syntax_6">Syntax</h3> + +<pre class="syntaxbox"><strong>Operator:</strong> var1 ** var2 +</pre> + +<h3 id="Notes">Notes</h3> + +<p>In most languages like PHP and Python and others that have an exponentiation operator (**), the exponentiation operator is defined to have a higher precedence than unary operators such as unary + and unary -, but there are a few exceptions. For example, in Bash the ** operator is defined to have a lower precedence than unary operators. In JavaScript, it is impossible to write an ambiguous exponentiation expression, i.e. you cannot put a unary operator (<code>+/-/~/!/delete/void/typeof</code>) immediately before the base number.</p> + +<pre class="brush: js">-2 ** 2; +// 4 in Bash, -4 in other languages. +// This is invalid in JavaScript, as the operation is ambiguous. + + +-(2 ** 2); +// -4 in JavaScript and the author's intention is unambiguous. +</pre> + +<h3 id="Examples_6">Examples</h3> + +<pre class="brush: js">2 ** 3 // 8 +3 ** 2 // 9 +3 ** 2.5 // 15.588457268119896 +10 ** -1 // 0.1 +NaN ** 2 // NaN + +2 ** 3 ** 2 // 512 +2 ** (3 ** 2) // 512 +(2 ** 3) ** 2 // 64 +</pre> + +<p>To invert the sign of the result of an exponentiation expression:</p> + +<pre class="brush: js">-(2 ** 2) // -4 +</pre> + +<p>To force the base of an exponentiation expression to be a negative number:</p> + +<pre class="brush: js">(-2) ** 2 // 4 +</pre> + +<div class="note"> +<p><strong>Note:</strong> JavaScript also has <a href="/en-US/docs/Web/JavaScript/Reference/Operators/Bitwise_Operators#Bitwise_XOR">a bitwise operator ^ (logical XOR)</a>. <code>**</code> and <code>^</code> are different (for example : <code>2 ** 3 === 8</code> when <code>2 ^ 3 === 1</code>.)</p> +</div> + +<h2 id="Increment_()"><a id="遞增運算" name="遞增運算">Increment (++)</a></h2> + +<p>The increment operator increments (adds one to) its operand and returns a value.</p> + +<ul> + <li>If used postfix, with operator after operand (for example, x++), then it returns the value before incrementing.</li> + <li>If used prefix with operator before operand (for example, ++x), then it returns the value after incrementing.</li> +</ul> + +<h3 id="Syntax_7">Syntax</h3> + +<pre class="syntaxbox"><strong>Operator:</strong> x++ or ++x +</pre> + +<h3 id="Examples_7">Examples</h3> + +<pre class="brush: js">// Postfix +var x = 3; +y = x++; // y = 3, x = 4 + +// Prefix +var a = 2; +b = ++a; // a = 3, b = 3 +</pre> + +<h2 id="Decrement_(--)"><a id="遞減運算" name="遞減運算">Decrement (--)</a></h2> + +<p>The decrement operator decrements (subtracts one from) its operand and returns a value.</p> + +<ul> + <li>If used postfix (for example, x--), then it returns the value before decrementing.</li> + <li>If used prefix (for example, --x), then it returns the value after decrementing.</li> +</ul> + +<h3 id="Syntax_8">Syntax</h3> + +<pre class="syntaxbox"><strong>Operator:</strong> x-- or --x +</pre> + +<h3 id="Examples_8">Examples</h3> + +<pre class="brush: js">// Postfix +var x = 3; +y = x--; // y = 3, x = 2 + +// Prefix +var a = 2; +b = --a; // a = 1, b = 1 +</pre> + +<h2 id="Unary_negation_(-)"><a name="Unary_negation">Unary negation (-)</a></h2> + +<p>The unary negation operator precedes its operand and negates it.</p> + +<h3 id="Syntax_9">Syntax</h3> + +<pre class="syntaxbox"><strong>Operator:</strong> -x +</pre> + +<h3 id="Examples_9">Examples</h3> + +<pre class="brush: js">var x = 3; +y = -x; // y = -3, x = 3 + +// Unary negation operator can convert non-numbers into a number +var x = "4"; +y = -x; // y = -4 +</pre> + +<h2 id="Unary_plus_()"><a name="Unary_plus">Unary plus</a> (+)</h2> + +<p>The unary plus operator precedes its operand and evaluates to its operand but attempts to convert it into a number, if it isn't already. Although unary negation (-) also can convert non-numbers, unary plus is the fastest and preferred way of converting something into a number, because it does not perform any other operations on the number. It can convert string representations of integers and floats, as well as the non-string values <code>true</code>, <code>false</code>, and <code>null</code>. Integers in both decimal and hexadecimal ("0x"-prefixed) formats are supported. Negative numbers are supported (though not for hex). If it cannot parse a particular value, it will evaluate to {{jsxref("NaN")}}.</p> + +<h3 id="Syntax_10">Syntax</h3> + +<pre class="syntaxbox"><strong>Operator:</strong> +x +</pre> + +<h3 id="Examples_10">Examples</h3> + +<pre class="brush: js">+3 // 3 ++'3' // 3 ++true // 1 ++false // 0 ++null // 0 ++function(val){ return val } // NaN +</pre> + +<h2 id="Specifications">Specifications</h2> + +<table class="standard-table"> + <tbody> + <tr> + <th scope="col">Specification</th> + <th scope="col">Status</th> + <th scope="col">Comment</th> + </tr> + <tr> + <td>{{SpecName('ES1')}}</td> + <td>{{Spec2('ES1')}}</td> + <td>Initial definition.</td> + </tr> + <tr> + <td>{{SpecName('ES5.1', '#sec-11.3')}}</td> + <td>{{Spec2('ES5.1')}}</td> + <td>Defined in several sections of the specification: <a href="http://www.ecma-international.org/ecma-262/5.1/#sec-11.6">Additive operators</a>, <a href="http://www.ecma-international.org/ecma-262/5.1/#sec-11.5">Multiplicative operators</a>, <a href="http://www.ecma-international.org/ecma-262/5.1/#sec-11.3">Postfix expressions</a>, <a href="http://www.ecma-international.org/ecma-262/5.1/#sec-11.4">Unary operators</a>.</td> + </tr> + <tr> + <td>{{SpecName('ES2015', '#sec-postfix-expressions')}}</td> + <td>{{Spec2('ES2015')}}</td> + <td>Defined in several sections of the specification: <a href="http://www.ecma-international.org/ecma-262/6.0/#sec-additive-operators">Additive operators</a>, <a href="http://www.ecma-international.org/ecma-262/6.0/#sec-multiplicative-operators">Multiplicative operators</a>, <a href="http://www.ecma-international.org/ecma-262/6.0/#sec-postfix-expressions">Postfix expressions</a>, <a href="http://www.ecma-international.org/ecma-262/6.0/#sec-unary-operators">Unary operators</a>.</td> + </tr> + <tr> + <td>{{SpecName('ES2016', '#sec-postfix-expressions')}}</td> + <td>{{Spec2('ES2016')}}</td> + <td>Added <a href="https://github.com/rwaldron/exponentiation-operator">Exponentiation operator</a>.</td> + </tr> + <tr> + <td>{{SpecName('ES2017', '#sec-postfix-expressions')}}</td> + <td>{{Spec2('ES2017')}}</td> + <td> </td> + </tr> + <tr> + <td>{{SpecName('ESDraft', '#sec-additive-operators')}}</td> + <td>{{Spec2('ESDraft')}}</td> + <td> </td> + </tr> + </tbody> +</table> + +<h2 id="Browser_compatibility">Browser compatibility</h2> + + + +<p>{{Compat("javascript.operators.arithmetic")}}</p> + +<h2 id="See_also">See also</h2> + +<ul> + <li><a href="/en-US/docs/Web/JavaScript/Reference/Operators/Assignment_Operators">Assignment operators</a></li> +</ul> diff --git a/files/zh-tw/web/javascript/reference/operators/async_function/index.html b/files/zh-tw/web/javascript/reference/operators/async_function/index.html new file mode 100644 index 0000000000..b0a761e890 --- /dev/null +++ b/files/zh-tw/web/javascript/reference/operators/async_function/index.html @@ -0,0 +1,111 @@ +--- +title: async function expression +slug: Web/JavaScript/Reference/Operators/async_function +translation_of: Web/JavaScript/Reference/Operators/async_function +--- +<div>{{jsSidebar("Operators")}}</div> + +<p>關鍵字 <strong><code>async function</code></strong> 可以用來定義陳述式中的 <code>async</code> 函式。</p> + +<p>你也可以使用 <a href="https://developer.mozilla.org/zh-TW/docs/Web/JavaScript/Reference/Statements/async_function" title="The async function keyword can be used to define async functions inside expressions.">async function statement</a> 來定義一個非同步函式</p> + +<h2 id="Syntax">Syntax</h2> + +<pre class="syntaxbox">async function [<em>name</em>]([<em>param1</em>[, <em>param2[</em>, ..., <em>paramN</em>]]]) { + <em>statements</em> +}</pre> + +<p>As of ES2015, you can also use <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions">arrow functions</a>.</p> + +<h3 id="Parameters">Parameters</h3> + +<dl> + <dt><code>name</code></dt> + <dd>The function name. Can be omitted, in which case the function is <em>anonymous</em>. The name is only local to the function body.</dd> + <dt><code>paramN</code></dt> + <dd>The name of an argument to be passed to the function.</dd> + <dt><code>statements</code></dt> + <dd>The statements which comprise the body of the function.</dd> +</dl> + +<h2 id="Description">Description</h2> + +<p>An <code>async function</code> expression is very similar to, and has almost the same syntax as, an {{jsxref('Statements/async_function', 'async function statement')}}. The main difference between an async <code>function</code> expression and an async <code>function</code> statement is the <em>function name,</em> which can be omitted in <code>async function</code> expressions to create <em>anonymous</em> functions. An <code>async function</code> expression can be used as an {{Glossary("IIFE")}} (Immediately Invoked Function Expression) which runs as soon as it is defined. See also the chapter about <a href="/en-US/docs/Web/JavaScript/Reference/Functions">functions</a> for more information.</p> + +<h2 id="Examples">Examples</h2> + +<h3 id="Simple_example">Simple example</h3> + +<pre class="brush: js">function resolveAfter2Seconds(x) { + return new Promise(resolve => { + setTimeout(() => { + resolve(x); + }, 2000); + }); +}; + + +var add = async function(x) { // async function expression assigned to a variable + var a = await resolveAfter2Seconds(20); + var b = await resolveAfter2Seconds(30); + return x + a + b; +}; + +add(10).then(v => { + console.log(v); // prints 60 after 4 seconds. +}); + + +(async function(x) { // async function expression used as an IIFE + var p_a = resolveAfter2Seconds(20); + var p_b = resolveAfter2Seconds(30); + return x + await p_a + await p_b; +})(10).then(v => { + console.log(v); // prints 60 after 2 seconds. +}); +</pre> + +<h2 id="Specifications">Specifications</h2> + +<table class="standard-table"> + <thead> + <tr> + <th scope="col">Specification</th> + <th scope="col">Status</th> + <th scope="col">Comment</th> + </tr> + </thead> + <tbody> + <tr> + <td>{{SpecName('ESDraft', '#sec-async-function-definitions', 'async function')}}</td> + <td>{{Spec2('ESDraft')}}</td> + <td> </td> + </tr> + <tr> + <td>{{SpecName('ES2018', '#sec-async-function-definitions', 'async function')}}</td> + <td>{{Spec2('ES2018')}}</td> + <td> </td> + </tr> + <tr> + <td>{{SpecName('ES2017', '#sec-async-function-definitions', 'async function')}}</td> + <td>{{Spec2('ES2017')}}</td> + <td>Initial definition.</td> + </tr> + </tbody> +</table> + +<h2 id="Browser_compatibility">Browser compatibility</h2> + +<div> + + +<p>{{Compat("javascript.operators.async_function_expression")}}</p> +</div> + +<h2 id="See_also">See also</h2> + +<ul> + <li>{{jsxref("Statements/async_function", "async function")}}</li> + <li>{{jsxref("AsyncFunction")}} object</li> + <li>{{jsxref("Operators/await", "await")}}</li> +</ul> diff --git a/files/zh-tw/web/javascript/reference/operators/await/index.html b/files/zh-tw/web/javascript/reference/operators/await/index.html new file mode 100644 index 0000000000..a8bda40412 --- /dev/null +++ b/files/zh-tw/web/javascript/reference/operators/await/index.html @@ -0,0 +1,152 @@ +--- +title: await +slug: Web/JavaScript/Reference/Operators/await +tags: + - Experimental + - JavaScript + - 運算子 +translation_of: Web/JavaScript/Reference/Operators/await +--- +<div>{{jsSidebar("Operators")}}</div> + +<div>await運算子可被用來等待 {{jsxref("Promise")}},只能在 {{jsxref("Statements/async_function", "async function")}}內使用。</div> + +<h2 id="語法">語法</h2> + +<pre class="syntaxbox">[<em>rv</em>] = await <em>expression</em>;</pre> + +<dl> + <dt><code>expression</code></dt> + <dd>等待解析的 {{jsxref("Promise")}} 物件或任何值。</dd> + <dt><font face="Consolas, Liberation Mono, Courier, monospace">rv = 回傳值</font></dt> + <dd> + <p>回傳 Promise 物件的 resolved 值,或當該值不是 Promise 物件時,回傳該值本身。</p> + </dd> +</dl> + +<h2 id="描述">描述</h2> + +<p>此 await 表示法會暫停 async 函式執行,等待 Promise 物件的解析,並在 promise 物件的值被 resolve 時回復 async 函式的執行。await 接著回傳這個被 resolve 的值。如果回傳值不是一個 Promise 物件,則會被轉換為 resolved 狀態的 Promise 物件。</p> + +<p>如果 Promise 物件被 rejected,則 await 會丟出 rejected 的值。</p> + +<h2 id="範例">範例</h2> + +<p>若將 Promise 物件傳給 await 運算式,它會等待 Promise 解析並回傳 resolve 後的值。</p> + +<pre class="brush: js">function resolveAfter2Seconds(x) { + return new Promise(resolve => { + setTimeout(() => { + resolve(x); + }, 2000); + }); +} + +async function f1() { + var x = await resolveAfter2Seconds(10); + console.log(x); // 10 +} +f1(); +</pre> + +<p>若傳給 await 的值並非一個 Promise 物件,它會將該值轉換為 resolved Promise,並等待之。</p> + +<pre class="brush: js">async function f2() { + var y = await 20; + console.log(y); // 20 +} +f2();</pre> + +<p>若 Promise 被 reject,則丟出 reject 後的異常值。</p> + +<pre class="brush: js">async function f3() { + try { + var z = await Promise.reject(30); + } catch(e) { + console.log(e); // 30 + } +} +f3();</pre> + +<h2 id="規範">規範</h2> + +<table class="standard-table"> + <thead> + <tr> + <th scope="col">規範</th> + <th scope="col">狀態</th> + <th scope="col">註解</th> + </tr> + </thead> + <tbody> + <tr> + <td>{{SpecName('ESDraft', '#sec-async-function-definitions', 'async functions')}}</td> + <td>{{Spec2('ESDraft')}}</td> + <td>ES2017中初始定義</td> + </tr> + </tbody> +</table> + +<h2 id="瀏覽器相容性">瀏覽器相容性</h2> + +<div>{{CompatibilityTable}}</div> + +<div id="compat-desktop"> +<table class="compat-table"> + <tbody> + <tr> + <th>Feature</th> + <th>Chrome</th> + <th>Firefox (Gecko)</th> + <th>Internet Explorer</th> + <th>Edge</th> + <th>Opera</th> + <th>Safari (WebKit)</th> + </tr> + <tr> + <td>基本支援</td> + <td>{{CompatChrome(55)}}</td> + <td>{{CompatGeckoDesktop("52.0")}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatOpera(42)}}</td> + <td>10.1</td> + </tr> + </tbody> +</table> +</div> + +<div id="compat-mobile"> +<table class="compat-table"> + <tbody> + <tr> + <th>Feature</th> + <th>Android</th> + <th>Android Webview</th> + <th>Firefox Mobile (Gecko)</th> + <th>IE Mobile</th> + <th>Opera Mobile</th> + <th>Safari Mobile</th> + <th>Chrome for Android</th> + </tr> + <tr> + <td>基本支援</td> + <td>{{CompatNo}}</td> + <td>{{CompatNo}}</td> + <td>{{CompatGeckoMobile("52.0")}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatOpera(42)}}</td> + <td>10.1</td> + <td>{{CompatChrome(55)}}</td> + </tr> + </tbody> +</table> +</div> + +<h2 id="See_also">See also</h2> + +<ul> + <li>{{jsxref("Statements/async_function", "async function")}}</li> + <li>{{jsxref("Operators/async_function", "async function expression")}}</li> + <li>{{jsxref("AsyncFunction")}} object</li> +</ul> diff --git a/files/zh-tw/web/javascript/reference/operators/bitwise_operators/index.html b/files/zh-tw/web/javascript/reference/operators/bitwise_operators/index.html new file mode 100644 index 0000000000..ed5df1092b --- /dev/null +++ b/files/zh-tw/web/javascript/reference/operators/bitwise_operators/index.html @@ -0,0 +1,554 @@ +--- +title: 位元運算子 +slug: Web/JavaScript/Reference/Operators/Bitwise_Operators +translation_of: Web/JavaScript/Reference/Operators +--- +<div>{{jsSidebar("Operators")}}</div> + +<p><strong>位元運算子</strong>將運算元視為一段 32 位元長的 0 和 1 序列,而不是十進位、十六進位或八進位的 <code><a href="/zh-TW/docs/Web/JavaScript/Reference/Global_Objects/Number" title="/en-US/docs/JavaScript/Reference/Global_Objects/Number">Numbers</a></code>。 舉例來說,十進位的 9 可以用二進位表示為 1001。位元運算子對這樣的二進位表示法進行運算,然後回傳標準 JavaScript 數值。</p> + +<div>{{EmbedInteractiveExample("pages/js/expressions-bitwiseoperators.html")}}</div> + + + +<p>下表總結了 JavaScript 的位元運算子:</p> + +<table class="standard-table"> + <tbody> + <tr> + <th>Operator</th> + <th>Usage</th> + <th>Description</th> + </tr> + <tr> + <td><a href="https://developer.mozilla.org/zh-TW/docs/Web/JavaScript/Reference/Operators/Bitwise_Operators#(位元_AND)">位元 AND</a></td> + <td><code>a & b</code></td> + <td>當兩運算元的該位置皆為 <code>1</code> 時,回傳值的該位置為 <code>1</code>。</td> + </tr> + <tr> + <td><a href="https://developer.mozilla.org/zh-TW/docs/Web/JavaScript/Reference/Operators/Bitwise_Operators#(位元_OR)">位元 OR</a></td> + <td><code>a | b</code></td> + <td>當兩運算元的該位置有一者為 <code>1</code> 時,回傳值的該位置為 <code>1</code>。</td> + </tr> + <tr> + <td><a href="https://developer.mozilla.org/zh-TW/docs/Web/JavaScript/Reference/Operators/Bitwise_Operators#(位元_XOR)">位元 XOR</a></td> + <td><code>a ^ b</code></td> + <td>當兩運算元的該位置恰好一者為 <code>1</code> 時,回傳值的該位置為 <code>1</code>。</td> + </tr> + <tr> + <td><a href="https://developer.mozilla.org/zh-TW/docs/Web/JavaScript/Reference/Operators/Bitwise_Operators#(位元_NOT)">位元 NOT</a></td> + <td><code>~ a</code></td> + <td>將運算元的所有位元反轉。</td> + </tr> + <tr> + <td><a href="https://developer.mozilla.org/zh-TW/docs/Web/JavaScript/Reference/Operators/Bitwise_Operators#%3C%3C_(左移)">左移</a></td> + <td><code>a << b</code></td> + <td>將 <code>a</code> 的二進位表示法左移 <code>b</code> (< 32) 位元,右側補 <code>0</code>。</td> + </tr> + <tr> + <td><a href="https://developer.mozilla.org/zh-TW/docs/Web/JavaScript/Reference/Operators/Bitwise_Operators#%3E%3E_(保持符號右移)">保持符號右移</a></td> + <td><code>a >> b</code></td> + <td>將 <code>a</code> 的二進位表示法右移 <code>b</code> (< 32) 位元,拋棄被移出的位元。</td> + </tr> + <tr> + <td><a href="https://developer.mozilla.org/zh-TW/docs/Web/JavaScript/Reference/Operators/Bitwise_Operators#%3E%3E%3E_(填零右移)">填零右移</a></td> + <td><code>a >>> b</code> </td> + <td>將 <code>a</code> 的二進位表示法右移 <code>b</code> (< 32) 位元,拋棄被移出的位元,並於右側補 <code>0</code>。</td> + </tr> + </tbody> +</table> + +<h2 id="帶號的_32位元整數">帶號的 32位元整數</h2> + +<p>所有位元運算子的運算元皆會被轉換成二<a href="https://en.wikipedia.org/wiki/Method_of_complements">補數系統</a>下的帶號32位元整數。二補數系統意味著一個整數的加法反元素(例如 5和 -5)是該整數的所有位元反轉(位元 NOT,也就是該數的一補數) 再加一。舉例來說,下面的序列代表著整數 314:</p> + +<pre class="brush: js">00000000000000000000000100111010 +</pre> + +<p>下面的序列代表 <code>~314</code>,也就是 <code>314</code> 的一補數:</p> + +<pre class="brush: js">11111111111111111111111011000101 +</pre> + +<p>接著,下面代表著 <code>-314</code>,也就是 <code>314</code> 的二補數:</p> + +<pre class="brush: js">11111111111111111111111011000110 +</pre> + +<p>二補數系統確保了正值時最左邊的位元為 0,反之則為 1。因此,最左邊的位元被稱作符號位。</p> + +<p>整數 <code>0</code> 全由位元 0組成。</p> + +<pre class="brush: js">0 (base 10) = 00000000000000000000000000000000 (base 2) +</pre> + +<p>整數 <code>-1</code> 全由位元 1組成。</p> + +<pre class="brush: js">-1 (base 10) = 11111111111111111111111111111111 (base 2) +</pre> + +<p>整數 <code>-2147483648</code> (十六進位: <code>-0x80000000</code>) 除了第一位為 1,其餘皆由位元 0組成。</p> + +<pre class="brush: js">-2147483648 (base 10) = 10000000000000000000000000000000 (base 2) +</pre> + +<p>整數 <code>-2147483648</code> (十六進位: <code>-0x7fffffff</code>) 除了第一位為 0,其餘皆由位元 1組成。</p> + +<pre class="brush: js">2147483647 (base 10) = 01111111111111111111111111111111 (base 2) +</pre> + +<p>整數 <code>-2147483648</code> 和 <code>2147483647</code> 分別為帶號32位元整數所能表示的最小值和最大值。</p> + +<h2 id="位元邏輯運算子">位元邏輯運算子</h2> + +<p>大致上,位元邏輯運算子的運作如下︰</p> + +<ul> + <li>運算元會被轉換成 32位元的整數,並被表達為一系列的位元 (0 和 1)。多於 32位元的數值在轉換中其超出第32位元的部分會被捨棄。下面的多於32位元整數在被轉換時: + <pre class="brush: js">Before: 11100110111110100000000000000110000000000001 +After: 10100000000000000110000000000001</pre> + </li> + <li>兩個運算元中的位元會根據其位置兩兩一組:第一個跟第一個、第二個跟第二個 ...</li> + <li>運算子會作用在每一組位元上,運算完成後再重新組合起來得到回傳值。</li> +</ul> + +<h3 id="(位元_AND)"><a id="Bitwise_AND" name="Bitwise_AND">& (位元 AND)</a></h3> + +<p>對每一組位元執行 AND 運算。<code>a</code> AND <code>b</code> 只在 <code>a</code> 和 <code>b</code> 同時為 <code>1</code> 時得到 1。AND運算的真值表如下:</p> + +<table class="standard-table"> + <tbody> + <tr> + <td class="header">a</td> + <td class="header">b</td> + <td class="header">a AND b</td> + </tr> + <tr> + <td>0</td> + <td>0</td> + <td>0</td> + </tr> + <tr> + <td>0</td> + <td>1</td> + <td>0</td> + </tr> + <tr> + <td>1</td> + <td>0</td> + <td>0</td> + </tr> + <tr> + <td>1</td> + <td>1</td> + <td>1</td> + </tr> + </tbody> +</table> + +<pre class="brush: js">. 9 (base 10) = 00000000000000000000000000001001 (base 2) + 14 (base 10) = 00000000000000000000000000001110 (base 2) + -------------------------------- +14 & 9 (base 10) = 00000000000000000000000000001000 (base 2) = 8 (base 10) +</pre> + +<p>將任何數 <code>x</code> 和 <code>0</code> 做位元 AND 皆會得到 <code>0</code>。將任何數 <code>x</code> 和 <font face="consolas, Liberation Mono, courier, monospace"><span style="background-color: rgba(220, 220, 220, 0.5);">-1</span></font> 做位元 AND 皆會得到 <font face="consolas, Liberation Mono, courier, monospace"><span style="background-color: rgba(220, 220, 220, 0.5);">x</span></font>。</p> + +<h3 id="(位元_OR)"><a name="Bitwise_OR">| (位元 OR)</a></h3> + +<p>對每一組位元執行 OR 運算。<code>a</code> OR <code>b</code> 在 <code>a</code> 和 <code>b</code> 有一者為 <code>1</code> 時得到 1。OR運算的真值表如下:</p> + +<table class="standard-table"> + <tbody> + <tr> + <td class="header">a</td> + <td class="header">b</td> + <td class="header">a OR b</td> + </tr> + <tr> + <td>0</td> + <td>0</td> + <td>0</td> + </tr> + <tr> + <td>0</td> + <td>1</td> + <td>1</td> + </tr> + <tr> + <td>1</td> + <td>0</td> + <td>1</td> + </tr> + <tr> + <td>1</td> + <td>1</td> + <td>1</td> + </tr> + </tbody> +</table> + +<pre class="brush: js">. 9 (base 10) = 00000000000000000000000000001001 (base 2) + 14 (base 10) = 00000000000000000000000000001110 (base 2) + -------------------------------- +14 | 9 (base 10) = 00000000000000000000000000001111 (base 2) = 15 (base 10) +</pre> + +<p>將任何數 <code>x</code> 和 <code>0</code> 做位元 OR 皆會得到 <font face="consolas, Liberation Mono, courier, monospace"><span style="background-color: rgba(220, 220, 220, 0.5);">x</span></font>。將任何數 <code>x</code> 和 <font face="consolas, Liberation Mono, courier, monospace"><span style="background-color: rgba(220, 220, 220, 0.5);">-1</span></font> 做位元 OR 皆會得到 <font face="consolas, Liberation Mono, courier, monospace"><span style="background-color: rgba(220, 220, 220, 0.5);">-1</span></font>。</p> + +<h3 id="(位元_XOR)"><a name="Bitwise_XOR">^ (位元 XOR)</a></h3> + +<p>對每一組位元執行 XOR 運算。<code>a</code> XOR <code>b</code> 只在 <code>a</code> 和 <code>b</code> 恰一者為 <code>1</code> 時得到 1。XOR運算的真值表如下:</p> + +<table class="standard-table"> + <tbody> + <tr> + <td class="header">a</td> + <td class="header">b</td> + <td class="header">a XOR b</td> + </tr> + <tr> + <td>0</td> + <td>0</td> + <td>0</td> + </tr> + <tr> + <td>0</td> + <td>1</td> + <td>1</td> + </tr> + <tr> + <td>1</td> + <td>0</td> + <td>1</td> + </tr> + <tr> + <td>1</td> + <td>1</td> + <td>0</td> + </tr> + </tbody> +</table> + +<pre class="brush: js">. 9 (base 10) = 00000000000000000000000000001001 (base 2) + 14 (base 10) = 00000000000000000000000000001110 (base 2) + -------------------------------- +14 ^ 9 (base 10) = 00000000000000000000000000000111 (base 2) = 7 (base 10) +</pre> + +<p>將任何數 <code>x</code> 和 <code>0</code> 做位元 AND 皆會得到 <font face="consolas, Liberation Mono, courier, monospace"><span style="background-color: rgba(220, 220, 220, 0.5);">x</span></font>。將任何數 <code>x</code> 和 <font face="consolas, Liberation Mono, courier, monospace">-1</font> 做位元 AND 皆會得到 <code>~x</code>。</p> + +<h3 id="(位元_NOT)"><a name="Bitwise_NOT">~ (位元 NOT)</a></h3> + +<p>對每一個位元執行 NOT 運算。NOT <code>a</code> 會得到 <code>a</code> 的反轉值(也就是一補數)。NOT運算的真值表如下:</p> + +<table class="standard-table"> + <tbody> + <tr> + <td class="header">a</td> + <td class="header">NOT a</td> + </tr> + <tr> + <td>0</td> + <td>1</td> + </tr> + <tr> + <td>1</td> + <td>0</td> + </tr> + </tbody> +</table> + +<pre class="brush: js"> 9 (base 10) = 00000000000000000000000000001001 (base 2) + -------------------------------- +~9 (base 10) = 11111111111111111111111111110110 (base 2) = -10 (base 10) +</pre> + +<p>將任何數 <code>x</code> 做位元 NOT 皆會得到 <code>-(x + 1)</code>。舉例來說,<code>~-5</code> 會得到 <code>4</code>。</p> + +<p>值得注意的是,因為使用 32位元表示法表示數值 <code>~-1</code> 和 <code>~4294967295</code> (2<sup>32</sup>-1) 皆會得到 <code>0</code>。</p> + +<h2 id="位元位移運算子">位元位移運算子</h2> + +<p>位移運算子需要兩個運算元:第一個是要被位移的值,第二個是位元位移量。位移的方向取決於使用的運算子。</p> + +<p>位移運算子將運算元轉換成 32位元的大端序整數並回傳一個與左運算元相同類別的值。右運算元應不大於32,如果超過的話,將只會使用後 5個位元。</p> + +<h3 id="<<_(左移)"><a name="Left_shift"><< (左移)</a></h3> + +<p>將第一個運算元向左位移指定的量。被移出的位元會被拋棄,並從右側補零。</p> + +<p>例如,<code>9 << 2</code> 會得到 36:</p> + +<pre class="brush: js">. 9 (base 10): 00000000000000000000000000001001 (base 2) + -------------------------------- +9 << 2 (base 10): 00000000000000000000000000100100 (base 2) = 36 (base 10) +</pre> + +<p>將任意值 <code>x</code> 左移 <code>y</code> 位元會得到 <code>x * 2 ** y</code>。</p> + +<h3 id=">>_(保持符號右移)"><a name="Right_shift">>> (保持符號右移)</a></h3> + +<p>將第一個運算元向右位移指定的量。被移出的位元會被拋棄,並從左側補進和原本最左端相同的位元值。因為新的最左端位元和原本的最左端位元是一樣的,符號位(最左端位元)並不會改變。「保持符號」之名便是因此。</p> + +<p>例如,<code>9 >> 2</code> 會得到 2:</p> + +<pre class="brush: js">. 9 (base 10): 00000000000000000000000000001001 (base 2) + -------------------------------- +9 >> 2 (base 10): 00000000000000000000000000000010 (base 2) = 2 (base 10) +</pre> + +<p>同樣地,<code>-9 >> 2</code> 會得到 <code>-3</code>,因為符號會保持不變。</p> + +<pre class="brush: js">. -9 (base 10): 11111111111111111111111111110111 (base 2) + -------------------------------- +-9 >> 2 (base 10): 11111111111111111111111111111101 (base 2) = -3 (base 10) +</pre> + +<h3 id=">>>_(填零右移)"><a name="Unsigned_right_shift">>>> (填零右移)</a></h3> + +<p>將第一個運算元向右位移指定的量。被移出的位元會被拋棄,並從左側補零。因為符號位變成 0,所以結果永遠都是正值。</p> + +<p>對非負的數來說,填零右移會得到和保持符號右移一樣的結果。例如,<code>9 >>> 2</code> 和 <code>9 >> 2</code> 一樣,皆會得到 2:</p> + +<pre class="brush: js">. 9 (base 10): 00000000000000000000000000001001 (base 2) + -------------------------------- +9 >>> 2 (base 10): 00000000000000000000000000000010 (base 2) = 2 (base 10) +</pre> + +<p>然而對負值來說並不是這麼一回事。例如,<code>-9 >>> 2</code> 會得到 1073741821,跟 <code>-9 >> 2</code> (得到 <code>-3</code>)的結果是不一樣的:</p> + +<pre class="brush: js">. -9 (base 10): 11111111111111111111111111110111 (base 2) + -------------------------------- +-9 >>> 2 (base 10): 00111111111111111111111111111101 (base 2) = 1073741821 (base 10) +</pre> + +<h2 id="範例">範例</h2> + +<h3 id="旗標(flags)_和遮罩_(bitmasks)">旗標(flags) 和遮罩 (bitmasks)</h3> + +<p>位元運算子常被用於生成、修改、和讀取旗標序列,就像是二進制的變數一般。雖然也可以使用普通變數,但使用二進制的旗標序列大大的減少了所需空間 (32 倍)。</p> + +<p>假設有 4個旗標:</p> + +<ul> + <li>旗標 A:我們有螞蟻問題</li> + <li>旗標 B:我們擁有一隻蝙蝠</li> + <li>旗標 C:我們擁有一隻貓</li> + <li>旗標 D:我們擁有一隻鴨子</li> +</ul> + +<p>這些旗標倍表達成一個位元序列:DCBA。當一個旗標被立起 (set)時,其值為1。當一個旗標被放下 (clear),其值為0。假設有一變數 <code>flags</code> 的二進位值為 0101:</p> + +<pre class="brush: js">var flags = 5; // 二進位 0101 +</pre> + +<p>這個值表示:</p> + +<ul> + <li>旗標 A為真 (我們有螞蟻問題);</li> + <li>旗標 B為假 (我們並未擁有一隻蝙蝠);</li> + <li>旗標 C為真 (我們擁有一隻貓);</li> + <li>旗標 D為假 (我們並未擁有一隻鴨子);</li> +</ul> + +<p>因為位元運算子進行的是 32位元操作,0101 實際上是 00000000000000000000000000000101,但前導的 0可被忽略因為他們沒有實際上的意義。</p> + +<p>位元遮罩則為一個可以修改且(或)讀取旗標序列的位元序列。通常為每個單獨旗標為真的「初始」值:</p> + +<pre class="brush: js">var FLAG_A = 1; // 0001 +var FLAG_B = 2; // 0010 +var FLAG_C = 4; // 0100 +var FLAG_D = 8; // 1000 +</pre> + +<p>新的位元遮罩可以透過對初始遮罩進行位元運算獲得。例如,遮罩 1011 可以透過對 FLAG_A、FLAG_B、和 FLAG_D進行 OR運算獲得:</p> + +<pre class="brush: js">var mask = FLAG_A | FLAG_B | FLAG_D; // 0001 | 0010 | 1000 => 1011 +</pre> + +<p>Individual flag values can be extracted by ANDing them with a bitmask, where each bit with the value of one will "extract" the corresponding flag. The bitmask <em>masks</em> out the non-relevant flags by ANDing with zeroes (hence the term "bitmask"). For example, the bitmask 0100 can be used to see if flag C is set:</p> + +<pre class="brush: js">// if we own a cat +if (flags & FLAG_C) { // 0101 & 0100 => 0100 => true + // do stuff +} +</pre> + +<p>A bitmask with multiple set flags acts like an "either/or". For example, the following two are equivalent:</p> + +<pre class="brush: js">// if we own a bat or we own a cat +// (0101 & 0010) || (0101 & 0100) => 0000 || 0100 => true +if ((flags & FLAG_B) || (flags & FLAG_C)) { + // do stuff +} +</pre> + +<pre class="brush: js">// if we own a bat or cat +var mask = FLAG_B | FLAG_C; // 0010 | 0100 => 0110 +if (flags & mask) { // 0101 & 0110 => 0100 => true + // do stuff +} +</pre> + +<p>Flags can be set by ORing them with a bitmask, where each bit with the value one will set the corresponding flag, if that flag isn't already set. For example, the bitmask 1100 can be used to set flags C and D:</p> + +<pre class="brush: js">// yes, we own a cat and a duck +var mask = FLAG_C | FLAG_D; // 0100 | 1000 => 1100 +flags |= mask; // 0101 | 1100 => 1101 +</pre> + +<p>Flags can be cleared by ANDing them with a bitmask, where each bit with the value zero will clear the corresponding flag, if it isn't already cleared. This bitmask can be created by NOTing primitive bitmasks. For example, the bitmask 1010 can be used to clear flags A and C:</p> + +<pre class="brush: js">// no, we don't have an ant problem or own a cat +var mask = ~(FLAG_A | FLAG_C); // ~0101 => 1010 +flags &= mask; // 1101 & 1010 => 1000 +</pre> + +<p>The mask could also have been created with <code>~FLAG_A & ~FLAG_C</code> (De Morgan's law):</p> + +<pre class="brush: js">// no, we don't have an ant problem, and we don't own a cat +var mask = ~FLAG_A & ~FLAG_C; +flags &= mask; // 1101 & 1010 => 1000 +</pre> + +<p>Flags can be toggled by XORing them with a bitmask, where each bit with the value one will toggle the corresponding flag. For example, the bitmask 0110 can be used to toggle flags B and C:</p> + +<pre class="brush: js">// if we didn't have a bat, we have one now, +// and if we did have one, bye-bye bat +// same thing for cats +var mask = FLAG_B | FLAG_C; +flags = flags ^ mask; // 1100 ^ 0110 => 1010 +</pre> + +<p>Finally, the flags can all be flipped with the NOT operator:</p> + +<pre class="brush: js">// entering parallel universe... +flags = ~flags; // ~1010 => 0101 +</pre> + +<h3 id="Conversion_snippets">Conversion snippets</h3> + +<p>Convert a binary <code><a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/String" title="/en-US/docs/JavaScript/Reference/Global_Objects/String">String</a></code> to a decimal <code><a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number" title="/en-US/docs/JavaScript/Reference/Global_Objects/Number">Number</a></code>:</p> + +<pre class="brush: js">var sBinString = '1011'; +var nMyNumber = parseInt(sBinString, 2); +alert(nMyNumber); // prints 11, i.e. 1011 +</pre> + +<p>Convert a decimal <code><a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number" title="/en-US/docs/JavaScript/Reference/Global_Objects/Number">Number</a></code> to a binary <code><a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/String" title="/en-US/docs/JavaScript/Reference/Global_Objects/String">String</a></code>:</p> + +<pre class="brush: js">var nMyNumber = 11; +var sBinString = nMyNumber.toString(2); +alert(sBinString); // prints 1011, i.e. 11 +</pre> + +<h3 id="Automate_Mask_Creation">Automate Mask Creation</h3> + +<p>You can create multiple masks from a set of <code><a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean" title="/en-US/docs/JavaScript/Reference/Global_Objects/Boolean">Boolean</a></code> values, like this:</p> + +<pre class="brush: js">function createMask() { + var nMask = 0, nFlag = 0, nLen = arguments.length > 32 ? 32 : arguments.length; + for (nFlag; nFlag < nLen; nMask |= arguments[nFlag] << nFlag++); + return nMask; +} +var mask1 = createMask(true, true, false, true); // 11, i.e.: 1011 +var mask2 = createMask(false, false, true); // 4, i.e.: 0100 +var mask3 = createMask(true); // 1, i.e.: 0001 +// etc. + +alert(mask1); // prints 11, i.e.: 1011 +</pre> + +<h3 id="Reverse_algorithm_an_array_of_booleans_from_a_mask">Reverse algorithm: an array of booleans from a mask</h3> + +<p>If you want to create an <code><a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array" title="/en-US/docs/JavaScript/Reference/Global_Objects/Array">Array</a></code> of <code><a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean" title="/en-US/docs/JavaScript/Reference/Global_Objects/Boolean">Booleans</a></code> from a mask you can use this code:</p> + +<pre class="brush: js">function arrayFromMask(nMask) { + // nMask must be between -2147483648 and 2147483647 + if (nMask > 0x7fffffff || nMask < -0x80000000) { + throw new TypeError('arrayFromMask - out of range'); + } + for (var nShifted = nMask, aFromMask = []; nShifted; + aFromMask.push(Boolean(nShifted & 1)), nShifted >>>= 1); + return aFromMask; +} + +var array1 = arrayFromMask(11); +var array2 = arrayFromMask(4); +var array3 = arrayFromMask(1); + +alert('[' + array1.join(', ') + ']'); +// prints "[true, true, false, true]", i.e.: 11, i.e.: 1011 +</pre> + +<p>You can test both algorithms at the same time…</p> + +<pre class="brush: js">var nTest = 19; // our custom mask +var nResult = createMask.apply(this, arrayFromMask(nTest)); + +alert(nResult); // 19 +</pre> + +<p>For the didactic purpose only (since there is the <code><a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/toString" title="/en-US/docs/JavaScript/Reference/Global_Objects/Number/toString">Number.toString(2)</a></code> method), we show how it is possible to modify the <code>arrayFromMask</code> algorithm in order to create a <code><a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/String" title="/en-US/docs/JavaScript/Reference/Global_Objects/String">String</a></code> containing the binary representation of a <code><a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number" title="/en-US/docs/JavaScript/Reference/Global_Objects/Number">Number</a></code>, rather than an <code><a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array" title="/en-US/docs/JavaScript/Reference/Global_Objects/Array">Array</a></code> of <code><a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean" title="/en-US/docs/JavaScript/Reference/Global_Objects/Boolean">Booleans</a></code>:</p> + +<pre class="brush: js">function createBinaryString(nMask) { + // nMask must be between -2147483648 and 2147483647 + for (var nFlag = 0, nShifted = nMask, sMask = ''; nFlag < 32; + nFlag++, sMask += String(nShifted >>> 31), nShifted <<= 1); + return sMask; +} + +var string1 = createBinaryString(11); +var string2 = createBinaryString(4); +var string3 = createBinaryString(1); + +alert(string1); +// prints 00000000000000000000000000001011, i.e. 11 +</pre> + +<h2 id="規範">規範</h2> + +<table class="standard-table"> + <tbody> + <tr> + <th scope="col">Specification</th> + <th scope="col">Status</th> + <th scope="col">Comment</th> + </tr> + <tr> + <td>{{SpecName('ES1')}}</td> + <td>{{Spec2('ES1')}}</td> + <td>Initial definition.</td> + </tr> + <tr> + <td>{{SpecName('ES5.1', '#sec-11.7')}}</td> + <td>{{Spec2('ES5.1')}}</td> + <td>Defined in several sections of the specification: <a href="http://www.ecma-international.org/ecma-262/5.1/#sec-11.4.8">Bitwise NOT operator</a>, <a href="http://www.ecma-international.org/ecma-262/5.1/#sec-11.7">Bitwise shift operators</a>, <a href="http://www.ecma-international.org/ecma-262/5.1/#sec-11.10">Binary bitwise operators</a></td> + </tr> + <tr> + <td>{{SpecName('ES6', '#sec-bitwise-shift-operators')}}</td> + <td>{{Spec2('ES6')}}</td> + <td>Defined in several sections of the specification: <a href="http://www.ecma-international.org/ecma-262/6.0/#sec-bitwise-not-operator">Bitwise NOT operator</a>, <a href="http://www.ecma-international.org/ecma-262/6.0/#sec-bitwise-shift-operators">Bitwise shift operators</a>, <a href="http://www.ecma-international.org/ecma-262/6.0/#sec-binary-bitwise-operators">Binary bitwise operators</a></td> + </tr> + <tr> + <td>{{SpecName('ESDraft', '#sec-bitwise-shift-operators')}}</td> + <td>{{Spec2('ESDraft')}}</td> + <td>Defined in several sections of the specification: <a href="http://tc39.github.io/ecma262/#sec-bitwise-not-operator">Bitwise NOT operator</a>, <a href="http://tc39.github.io/ecma262/#sec-bitwise-shift-operators">Bitwise shift operators</a>, <a href="http://tc39.github.io/ecma262/#sec-binary-bitwise-operators">Binary bitwise operators</a></td> + </tr> + </tbody> +</table> + +<h2 id="瀏覽器相容性">瀏覽器相容性</h2> + +<div class="hidden"> +<p>The compatibility table on this page is generated from structured data. If you'd like to contribute to the data, please check out <a href="https://github.com/mdn/browser-compat-data">https://github.com/mdn/browser-compat-data</a> and send us a pull request.</p> +</div> + +<p>{{Compat("javascript.operators.bitwise")}}</p> + +<h2 id="另見">另見</h2> + +<ul> + <li><a href="/en-US/docs/Web/JavaScript/Reference/Operators/Logical_Operators">Logical operators</a></li> +</ul> diff --git a/files/zh-tw/web/javascript/reference/operators/comma_operator/index.html b/files/zh-tw/web/javascript/reference/operators/comma_operator/index.html new file mode 100644 index 0000000000..3324cb156b --- /dev/null +++ b/files/zh-tw/web/javascript/reference/operators/comma_operator/index.html @@ -0,0 +1,145 @@ +--- +title: 逗號運算子 +slug: Web/JavaScript/Reference/Operators/Comma_Operator +translation_of: Web/JavaScript/Reference/Operators/Comma_Operator +--- +<div>{{jsSidebar("Operators")}}</div> + +<p>The<strong> comma operator</strong> evaluates each of its operands (from left to right) and returns the value of the last operand.</p> + +<h2 id="語法">語法</h2> + +<pre class="syntaxbox"><em>expr1</em>, <em>expr2, expr3...</em></pre> + +<h2 id="參數">參數</h2> + +<dl> + <dt><code>expr1</code>, <code>expr2, expr3...</code></dt> + <dd>Any expressions.</dd> +</dl> + +<h2 id="描述">描述</h2> + +<p>You can use the comma operator when you want to include multiple expressions in a location that requires a single expression. The most common usage of this operator is to supply multiple parameters in a <code>for</code> loop.</p> + +<h2 id="範例">範例</h2> + +<p>If <code>a</code> is a 2-dimensional array with 10 elements on each side, the following code uses the comma operator to increment two variables at once.</p> + +<p>The following code prints the values of the diagonal elements in the array:</p> + +<pre class="brush:js;highlight:[1]">for (var i = 0, j = 9; i <= 9; i++, j--) + console.log("a[" + i + "][" + j + "] = " + a[i][j]);</pre> + +<p>Note that the comma in assignments such as the <code>var</code> statement may appear not to have the normal effect of comma operators because they don't exist within an expression. In the following example, <code>a</code> is set to the value of <code>b = 3</code> (which is 3), but the <code>c = 4</code> expression still evaluates and its result returned to console (i.e., 4). This is due to <a href="/en-US/docs/Web/JavaScript/Reference/Operators/Operator_Precedence">operator precedence and associativity</a>.</p> + +<pre class="brush: js">// Note that the following creates globals and is disallowed in strict mode. + +a = b = 3, c = 4; // Returns 4 in console +console.log(a); // 3 (left-most) + +x = (y = 5, z = 6); // Returns 6 in console +console.log(x); // 6 (right-most) +</pre> + +<p>The comma operator is fully different from the comma within arrays, objects, and function arguments and parameters.</p> + +<h3 id="Processing_and_then_returning">Processing and then returning</h3> + +<p>Another example that one could make with comma operator is processing before returning. As stated, only the last element will be returned but all others are going to be evaluated as well. So, one could do:</p> + +<pre class="brush: js">function myFunc () { + var x = 0; + + return (x += 1, x); // the same as return ++x; +}</pre> + +<h2 id="規範">規範</h2> + +<table class="standard-table"> + <tbody> + <tr> + <th scope="col">Specification</th> + <th scope="col">Status</th> + <th scope="col">Comment</th> + </tr> + <tr> + <td>{{SpecName('ESDraft', '#sec-comma-operator', 'Comma operator')}}</td> + <td>{{Spec2('ESDraft')}}</td> + <td> </td> + </tr> + <tr> + <td>{{SpecName('ES6', '#sec-comma-operator', 'Comma operator')}}</td> + <td>{{Spec2('ES6')}}</td> + <td> </td> + </tr> + <tr> + <td>{{SpecName('ES5.1', '#sec-11.14', 'Comma operator')}}</td> + <td>{{Spec2('ES5.1')}}</td> + <td> </td> + </tr> + <tr> + <td>{{SpecName('ES1', '#sec-11.14', 'Comma operator')}}</td> + <td>{{Spec2('ES1')}}</td> + <td>Initial definition</td> + </tr> + </tbody> +</table> + +<h2 id="瀏覽器相容性">瀏覽器相容性</h2> + +<p>{{CompatibilityTable}}</p> + +<div id="compat-desktop"> +<table class="compat-table"> + <tbody> + <tr> + <th>Feature</th> + <th>Chrome</th> + <th>Firefox (Gecko)</th> + <th>Internet Explorer</th> + <th>Opera</th> + <th>Safari</th> + </tr> + <tr> + <td>Basic support</td> + <td>{{CompatVersionUnknown}}</td> + <td>{{CompatVersionUnknown}}</td> + <td>3.0</td> + <td>{{CompatVersionUnknown}}</td> + <td>{{CompatVersionUnknown}}</td> + </tr> + </tbody> +</table> +</div> + +<div id="compat-mobile"> +<table class="compat-table"> + <tbody> + <tr> + <th>Feature</th> + <th>Android</th> + <th>Chrome for Android</th> + <th>Firefox Mobile (Gecko)</th> + <th>IE Mobile</th> + <th>Opera Mobile</th> + <th>Safari Mobile</th> + </tr> + <tr> + <td>Basic support</td> + <td>{{CompatVersionUnknown}}</td> + <td>{{CompatVersionUnknown}}</td> + <td>{{CompatVersionUnknown}}</td> + <td>{{CompatVersionUnknown}}</td> + <td>{{CompatVersionUnknown}}</td> + <td>{{CompatVersionUnknown}}</td> + </tr> + </tbody> +</table> +</div> + +<h2 id="參見">參見</h2> + +<ul> + <li><a href="/en-US/docs/Web/JavaScript/Reference/Statements/for">for loop</a></li> +</ul> diff --git a/files/zh-tw/web/javascript/reference/operators/comparison_operators/index.html b/files/zh-tw/web/javascript/reference/operators/comparison_operators/index.html new file mode 100644 index 0000000000..70345e158c --- /dev/null +++ b/files/zh-tw/web/javascript/reference/operators/comparison_operators/index.html @@ -0,0 +1,283 @@ +--- +title: 比較運算子 +slug: Web/JavaScript/Reference/Operators/Comparison_Operators +translation_of: Web/JavaScript/Reference/Operators +--- +<div>{{jsSidebar("Operators")}}</div> + +<p>JavaScript has both strict and type–converting comparisons. A strict comparison (e.g., <code>===</code>) is only true if the operands are of the same type and the contents match. The more commonly-used abstract comparison (e.g. <code>==</code>) converts the operands to the same type before making the comparison. For relational abstract comparisons (e.g., <code><=</code>), the operands are first converted to primitives, then to the same type, before comparison.</p> + +<p>Strings are compared based on standard lexicographical ordering, using Unicode values.</p> + +<p>Features of comparisons:</p> + +<ul> + <li>Two strings are strictly equal when they have the same sequence of characters, same length, and same characters in corresponding positions.</li> + <li>Two numbers are strictly equal when they are numerically equal (have the same number value). <a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/NaN" title="NaN">NaN</a> is not equal to anything, including NaN. Positive and negative zeros are equal to one another.</li> + <li>Two Boolean operands are strictly equal if both are <code>true</code> or both are <code>false</code>.</li> + <li>Two distinct objects are never equal for either strict or abstract comparisons.</li> + <li>An expression comparing Objects is only true if the operands reference the same Object.</li> + <li>Null and Undefined Types are strictly equal to themselves and abstractly equal to each other.</li> +</ul> + +<h2 id="Equality_operators">Equality operators</h2> + +<h3 id="Equality_()"><a name="Equality">Equality (==)</a></h3> + +<p>The equality operator converts the operands if they are <strong>not of the same type</strong>, then applies strict comparison. If <strong>both operands are objects</strong>, then JavaScript compares internal references which are equal when operands refer to the same object in memory.</p> + +<h4 id="Syntax">Syntax</h4> + +<pre class="syntaxbox">x == y +</pre> + +<h4 id="Examples">Examples</h4> + +<pre class="brush: js"> 1 == 1 // true + "1" == 1 // true + 1 == '1' // true + 0 == false // true + 0 == null // false +var object1 = {"value":"key"}, object2={"value":"key"}; +object1 == object2 //false + + 0 == undefined // false +null == undefined // true +</pre> + +<h3 id="Inequality_(!)"><a name="Inequality">Inequality (!=)</a></h3> + +<p>The inequality operator returns true if the operands are not equal. If the two operands are <strong>not of the same type</strong>, JavaScript attempts to convert the operands to an appropriate type for the comparison. If <strong>both operands are objects</strong>, then JavaScript compares internal references which are not equal when operands refer to different objects in memory.</p> + +<h4 id="Syntax_2">Syntax</h4> + +<pre class="syntaxbox">x != y</pre> + +<h4 id="Examples_2">Examples</h4> + +<pre class="brush: js">1 != 2 // true +1 != "1" // false +1 != '1' // false +1 != true // false +0 != false // false +</pre> + +<h3 id="Identity_strict_equality_()"><a name="Identity">Identity / strict equality (===)</a></h3> + +<p>The identity operator returns true if the operands are strictly equal (see above) <strong>with no type conversion</strong>. </p> + +<h4 id="Syntax_3">Syntax</h4> + +<pre class="syntaxbox">x === y</pre> + +<h4 id="Examples_3">Examples</h4> + +<pre class="brush: js ">3 === 3 // true +3 === '3' // false +var object1 = {"value":"key"}, object2={"value":"key"}; +object1 === object2 //false</pre> + +<p> </p> + +<h3 id="Non-identity_strict_inequality_(!)"><a name="Nonidentity">Non-identity / strict inequality (!==)</a></h3> + +<p>The non-identity operator returns true if the operands <strong>are not equal and/or not of the same type</strong>.</p> + +<h4 id="Syntax_4">Syntax</h4> + +<pre class="syntaxbox">x !== y</pre> + +<h4 id="Examples_4">Examples</h4> + +<pre class="brush: js">3 !== '3' // true +4 !== 3 // true +</pre> + +<h2 id="Relational_operators">Relational operators</h2> + +<p>Each of these operators will call the <code>valueOf()</code> function on each operand before a comparison is made.</p> + +<h3 id="Greater_than_operator_(>)"><a name="Greater_than_operator">Greater than operator (>)</a></h3> + +<p>The greater than operator returns true if the left operand is greater than the right operand.</p> + +<h4 id="Syntax_5">Syntax</h4> + +<pre class="syntaxbox">x > y</pre> + +<h4 id="Examples_5">Examples</h4> + +<pre class="brush: js">4 > 3 // true +</pre> + +<h3 id="Greater_than_or_equal_operator_(>)"><a name="Greater_than_or_equal_operator">Greater than or equal operator (>=)</a></h3> + +<p>The greater than or equal operator returns true if the left operand is greater than or equal to the right operand.</p> + +<h4 id="Syntax_6">Syntax</h4> + +<pre class="syntaxbox"> x >= y</pre> + +<h4 id="Examples_6">Examples</h4> + +<pre class="brush: js">4 >= 3 // true +3 >= 3 // true +</pre> + +<h3 id="Less_than_operator_(<)"><a name="Less_than_operator">Less than operator (<)</a></h3> + +<p>The less than operator returns true if the left operand is less than the right operand.</p> + +<h4 id="Syntax_7">Syntax</h4> + +<pre class="syntaxbox"> x < y</pre> + +<h4 id="Examples_7">Examples</h4> + +<pre class="brush: js">3 < 4 // true +</pre> + +<h3 id="Less_than_or_equal_operator_(<)"><a id="Less_than_or_equal_operator" name="Less_than_or_equal_operator">Less than or equal operator (<=)</a></h3> + +<p>The less than or equal operator returns true if the left operand is less than or equal to the right operand.</p> + +<h4 id="Syntax_8">Syntax</h4> + +<pre class="syntaxbox"> x <= y</pre> + +<h4 id="Examples_8">Examples</h4> + +<pre class="brush: js">3 <= 4 // true +</pre> + +<h2 id="Using_the_Equality_Operators">Using the Equality Operators</h2> + +<p>The standard equality operators (<code>==</code> and <code>!=</code>) use the <a href="http://www.ecma-international.org/ecma-262/5.1/#sec-11.9.3">Abstract Equality Comparison Algorithm</a> to compare two operands. If the operands are of different types, it will attempt to convert them to the same type before making the comparison, e.g., in the expression <code>5 == '5'</code>, the string on the right is converted to {{jsxref("Number")}} before the comparison is made.</p> + +<p>The strict equality operators (<code>===</code> and <code>!==</code>) use the <a href="http://www.ecma-international.org/ecma-262/5.1/#sec-11.9.6">Strict Equality Comparison Algorithm</a> and are intended for performing equality comparisons on operands of the same type. If the operands are of different types, the result is always <code>false</code> so <code>5 !== '5'</code>.</p> + +<p>Use strict equality operators if the operands must be of a specific type as well as value or if the exact type of the operands is important. Otherwise, use the standard equality operators, which allow you to compare the identity of two operands even if they are not of the same type.</p> + +<p>When type conversion is involved in the comparison (i.e., non–strict comparison), JavaScript converts the types {{jsxref("String")}}, {{jsxref("Number")}}, {{jsxref("Boolean")}}, or {{jsxref("Object")}} operands as follows:</p> + +<ul> + <li>When comparing a number and a string, the string is converted to a number value. JavaScript attempts to convert the string numeric literal to a <code>Number</code> type value. First, a mathematical value is derived from the string numeric literal. Next, this value is rounded to nearest <code>Number</code> type value.</li> + <li>If one of the operands is <code>Boolean</code>, the Boolean operand is converted to 1 if it is <code>true</code> and +0 if it is <code>false</code>.</li> + <li>If an object is compared with a number or string, JavaScript attempts to return the default value for the object. Operators attempt to convert the object to a primitive value, a <code>String</code> or <code>Number</code> value, using the <code>valueOf</code> and <code>toString</code> methods of the objects. If this attempt to convert the object fails, a runtime error is generated.</li> + <li>Note that an object is converted into a primitive if, and only if, its comparand is a primitive. If both operands are objects, they're compared as objects, and the equality test is true only if both refer the same object.</li> +</ul> + +<div class="note"><strong>Note:</strong> String objects are Type Object, not String! String objects are rarely used, so the following results might be surprising:</div> + +<pre class="brush:js">// true as both operands are type String (i.e. string primitives): +'foo' === 'foo' + +var a = new String('foo'); +var b = new String('foo'); + +// false as a and b are type Object and reference different objects +a == b + +// false as a and b are type Object and reference different objects +a === b + +// true as a and 'foo' are of different type and, the Object (a) +// is converted to String 'foo' before comparison +a == 'foo'</pre> + +<h2 id="規範">規範</h2> + +<table class="standard-table"> + <tbody> + <tr> + <th scope="col">Specification</th> + <th scope="col">Status</th> + <th scope="col">Comment</th> + </tr> + <tr> + <td>{{SpecName('ES1')}}</td> + <td>{{Spec2('ES1')}}</td> + <td>Initial definition. Implemented in JavaScript 1.0</td> + </tr> + <tr> + <td>{{SpecName('ES3')}}</td> + <td>{{Spec2('ES3')}}</td> + <td>Adds <code>===</code> and <code>!==</code> operators. Implemented in JavaScript 1.3</td> + </tr> + <tr> + <td>{{SpecName('ES5.1', '#sec-11.8')}}</td> + <td>{{Spec2('ES5.1')}}</td> + <td>Defined in several sections of the specification: <a href="http://www.ecma-international.org/ecma-262/5.1/#sec-11.8">Relational Operators</a>, <a href="http://www.ecma-international.org/ecma-262/5.1/#sec-11.9">Equality Operators</a></td> + </tr> + <tr> + <td>{{SpecName('ES6', '#sec-relational-operators')}}</td> + <td>{{Spec2('ES6')}}</td> + <td>Defined in several sections of the specification: <a href="http://www.ecma-international.org/ecma-262/6.0/#sec-relational-operators">Relational Operators</a>, <a href="http://www.ecma-international.org/ecma-262/6.0/#sec-equality-operators">Equality Operators</a></td> + </tr> + <tr> + <td>{{SpecName('ESDraft', '#sec-relational-operators')}}</td> + <td>{{Spec2('ESDraft')}}</td> + <td>Defined in several sections of the specification: <a href="http://tc39.github.io/ecma262/#sec-relational-operators">Relational Operators</a>, <a href="http://tc39.github.io/ecma262/#sec-equality-operators">Equality Operators</a></td> + </tr> + </tbody> +</table> + +<h2 id="瀏覽器相容性">瀏覽器相容性</h2> + +<p>{{CompatibilityTable}}</p> + +<div id="compat-desktop"> +<table class="compat-table"> + <tbody> + <tr> + <th>Feature</th> + <th>Chrome</th> + <th>Firefox (Gecko)</th> + <th>Internet Explorer</th> + <th>Opera</th> + <th>Safari</th> + </tr> + <tr> + <td>Basic support</td> + <td>{{CompatVersionUnknown}}</td> + <td>{{CompatVersionUnknown}}</td> + <td>{{CompatVersionUnknown}}</td> + <td>{{CompatVersionUnknown}}</td> + <td>{{CompatVersionUnknown}}</td> + </tr> + </tbody> +</table> +</div> + +<div id="compat-mobile"> +<table class="compat-table"> + <tbody> + <tr> + <th>Feature</th> + <th>Android</th> + <th>Chrome for Android</th> + <th>Firefox Mobile (Gecko)</th> + <th>IE Mobile</th> + <th>Opera Mobile</th> + <th>Safari Mobile</th> + </tr> + <tr> + <td>Basic support</td> + <td>{{CompatVersionUnknown}}</td> + <td>{{CompatVersionUnknown}}</td> + <td>{{CompatVersionUnknown}}</td> + <td>{{CompatVersionUnknown}}</td> + <td>{{CompatVersionUnknown}}</td> + <td>{{CompatVersionUnknown}}</td> + </tr> + </tbody> +</table> +</div> + +<h2 id="參見">參見</h2> + +<ul> + <li>{{jsxref("Object.is()")}}</li> + <li>{{jsxref("Math.sign()")}}</li> + <li><a href="/en-US/docs/Web/JavaScript/Equality_comparisons_and_sameness">Equality comparisons and sameness</a></li> +</ul> diff --git a/files/zh-tw/web/javascript/reference/operators/conditional_operator/index.html b/files/zh-tw/web/javascript/reference/operators/conditional_operator/index.html new file mode 100644 index 0000000000..78fb9a4a55 --- /dev/null +++ b/files/zh-tw/web/javascript/reference/operators/conditional_operator/index.html @@ -0,0 +1,101 @@ +--- +title: 條件運算子 +slug: Web/JavaScript/Reference/Operators/Conditional_Operator +translation_of: Web/JavaScript/Reference/Operators/Conditional_Operator +--- +<div>{{jsSidebar("Operators")}}</div> + +<p><span class="seoSummary"><strong>條件 (三元) 運算子</strong> 是 JavaScript 唯一用到三個運算元的運算子:在一個條件後面會跟著一個問號 (<code>?</code>),如果條件是 <a href="/en-US/docs/Glossary/truthy">truthy</a>,在冒號(<code>:</code>)前的表達式會被執行,如果條件是 <a href="/en-US/docs/Glossary/falsy">falsy</a>,在冒號後面的表達式會被執行,</span>這個運算子常常被用來當作 <a href="/en-US/docs/Web/JavaScript/Reference/Statements/if...else"><code>if</code></a> 的簡潔寫法.</p> + +<div>{{EmbedInteractiveExample("pages/js/expressions-conditionaloperators.html")}}</div> + +<div class="hidden">The source for this interactive example is stored in a GitHub repository. If you'd like to contribute to the interactive examples project, please clone <a href="https://github.com/mdn/interactive-examples">https://github.com/mdn/interactive-examples</a> and send us a pull request.</div> + +<h2 id="語法">語法</h2> + +<pre class="syntaxbox notranslate"><var>condition</var> ? <var>exprIfTrue</var> : <var>exprIfFalse</var></pre> + +<h3 id="參數">參數</h3> + +<dl> + <dt><code><var>condition</var></code></dt> + <dd>值用來做為條件的表達式</dd> + <dt><code><var>exprIfTrue</var></code></dt> + <dd>如果 <code><var>condition</var></code> 的值是 <a href="/en-US/docs/Glossary/truthy">truthy</a> (等於或是可轉換為 <code>true</code>) , <code><var>exprIfTrue</var></code> 會被執行</dd> + <dt><code><var>exprIfFalse</var></code></dt> + <dd>如果 <code><var>condition</var></code> 的值是 <a href="/en-US/docs/Glossary/falsy">falsy</a> (等於或是可轉換為 <font face="consolas, Liberation Mono, courier, monospace"><span style="background-color: rgba(220, 220, 220, 0.5);">false</span></font>) , <code><var>exprIfFalse</var></code> 會被執行</dd> +</dl> + +<h2 id="描述">描述</h2> + +<p>除了 <code>false</code>, 可能是 falsy 的表達式有 <code>null</code>, <code>NaN</code>, <code>0</code>, 空字串 (<code>""</code>) 和 <code>undefined</code>. 如果<code><var>condition</var></code> 是他們其中之一 , 那麼條件表達式的結果會是 <code>exprIfFalse</code> 的執行結果. </p> + +<p>一個簡單的範例:</p> + +<pre class="brush: js notranslate">var age = 26; +var beverage = (age >= 21) ? "Beer" : "Juice"; +console.log(beverage); // "Beer" +</pre> + +<p>一個常用來處理 <code>null</code> 的用法 : </p> + +<pre class="brush: js notranslate">function greeting(person) { + var name = person ? person.name : "stranger"; + return "Howdy, " + name; +} + +console.log(greeting({name: 'Alice'})); // "Howdy, Alice" +console.log(greeting(null)); // "Howdy, stranger" +</pre> + +<h3 id="條件鏈">條件鏈</h3> + +<p>條件 (三元) 運算子是右相依性的 (right-associative), 代表他可以以下面的方式鏈結 , 類似於 <code>if … else if … else if … else</code> 的鏈結方法 :</p> + +<pre class="brush: js notranslate">function example(…) { + return condition1 ? value1 + : condition2 ? value2 + : condition3 ? value3 + : value4; +} + +// Equivalent to: + +function example(…) { + if (condition1) { return value1; } + else if (condition2) { return value2; } + else if (condition3) { return value3; } + else { return value4; } +} +</pre> + +<h2 id="規範">規範</h2> + +<table class="standard-table"> + <thead> + <tr> + <th scope="col">Specification</th> + </tr> + </thead> + <tbody> + <tr> + <td>{{SpecName('ESDraft', '#sec-conditional-operator', 'Conditional Operator')}}</td> + </tr> + </tbody> +</table> + +<h2 id="瀏覽器相容性">瀏覽器相容性</h2> + +<div class="hidden">The compatibility table on this page is generated from structured data. If you'd like to contribute to the data, please check out <a class="external" href="https://github.com/mdn/browser-compat-data">https://github.com/mdn/browser-compat-data</a> and send us a pull request.</div> + +<p>{{Compat("javascript.operators.conditional")}}</p> + +<h2 id="參見">參見</h2> + +<ul> + <li><a href="/en-US/docs/Web/JavaScript/Reference/Statements/if...else">if statement</a></li> + <li><a href="/en-US/docs/Web/JavaScript/Reference/Operators/Nullish_coalescing_operator">Nullish coalescing operator</a></li> + <li><a href="/en-US/docs/Web/JavaScript/Reference/Operators/Optional_chaining">Optional chaining</a></li> + <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/Web/JavaScript/Guide/Expressions_and_Operators">Expressions and operators</a></li> +</ul> diff --git a/files/zh-tw/web/javascript/reference/operators/destructuring_assignment/index.html b/files/zh-tw/web/javascript/reference/operators/destructuring_assignment/index.html new file mode 100644 index 0000000000..0cae43e2b5 --- /dev/null +++ b/files/zh-tw/web/javascript/reference/operators/destructuring_assignment/index.html @@ -0,0 +1,423 @@ +--- +title: 解構賦值 +slug: Web/JavaScript/Reference/Operators/Destructuring_assignment +tags: + - Destructuring + - Destructuring_assignment + - ECMAScript 2015 + - ES6 + - JavaScript + - Language feature + - Operator + - 解構 +translation_of: Web/JavaScript/Reference/Operators/Destructuring_assignment +--- +<div>{{jsSidebar("Operators")}}</div> + +<p><strong>解構賦值</strong> (Destructuring assignment) 語法是一種 JavaScript 運算式,可以把陣列或物件中的資料解開擷取成為獨立變數。</p> + +<div>{{EmbedInteractiveExample("pages/js/expressions-destructuringassignment.html", "taller")}}</div> + + + +<h2 id="語法">語法</h2> + +<pre class="brush:js">let a, b, rest; +[a, b] = [10, 20]; +console.log(a); // 10 +console.log(b); // 20 + +[a, b, ...rest] = [10, 20, 30, 40, 50]; +console.log(a); // 10 +console.log(b); // 20 +console.log(rest); // [30, 40, 50] + +({ a, b } = { a: 10, b: 20 }); +console.log(a); // 10 +console.log(b); // 20 + + +// Stage 4(finished) proposal +({a, b, ...rest} = {a: 10, b: 20, c: 30, d: 40}); +console.log(a); // 10 +console.log(b); // 20 +console.log(rest); // {c: 30, d: 40} +</pre> + +<h2 id="描述">描述</h2> + +<p>物件與陣列運算式提供了簡單的方式,建立特定的資料組。</p> + +<pre class="brush: js">const x = [1, 2, 3, 4, 5];</pre> + +<p>解構賦值使用類似語法;不過在指定敘述式的左側,要宣告從來源變數接收解開值之變數。</p> + +<pre class="brush: js">const x = [1, 2, 3, 4, 5]; +const [y, z] = x; +console.log(y); // 1 +console.log(z); // 2 +</pre> + +<p>Perl 和 Python 也有類似的語法和功能。</p> + +<h2 id="陣列解構">陣列解構</h2> + +<h3 id="基本變數指定敘述">基本變數指定敘述</h3> + +<pre class="brush: js">const foo = ['one', 'two', 'three']; + +const [red, yellow, green] = foo; +console.log(red); // "one" +console.log(yellow); // "two" +console.log(green); // "three" +</pre> + +<h3 id="宣告指派分開敍述">宣告指派分開敍述</h3> + +<p>變數可以在宣告式後,再透過解構賦值。</p> + +<pre class="brush:js">let a, b; + +[a, b] = [1, 2]; +console.log(a); // 1 +console.log(b); // 2 +</pre> + +<h3 id="預設值">預設值</h3> + +<p>當解構來源陣列對應的元素是 undefined 時,變數可以被設定預設值。</p> + +<pre class="brush: js">let a, b; + +[a=5, b=7] = [1]; +console.log(a); // 1 +console.log(b); // 7 +</pre> + +<h3 id="變數交換">變數交換</h3> + +<p>兩個變數可以透過一個解構指派式交換。</p> + +<p>沒有解構指派式時,這需要一個暫存變數來達成(或者像某些低階語言的 <a class="external" href="https://en.wikipedia.org/wiki/XOR_swap_algorithm">XOR-swap trick</a>)。</p> + +<pre class="brush:js">let a = 1; +let b = 3; + +[a, b] = [b, a]; +console.log(a); // 3 +console.log(b); // 1 + +const arr = [1,2,3]; +[arr[2], arr[1]] = [arr[1], arr[2]]; +console.log(arr); // [1,3,2] + +</pre> + +<h3 id="解析自函式回傳的陣列">解析自函式回傳的陣列</h3> + +<p>一直以來函式都可以回傳陣列,而解構指派式可以讓回傳的值更加簡潔。</p> + +<p>在這個例子, <code>f()</code> 回傳 <code>[1, 2]</code> ,接著透過一個解構指派式解析。</p> + +<pre class="brush:js">function f() { + return [1, 2]; +} + +let a, b; +[a, b] = f(); +console.log(a); // 1 +console.log(b); // 2 +</pre> + +<h3 id="忽略某些回傳值">忽略某些回傳值</h3> + +<p>你可以忽略某些回傳值:</p> + +<pre class="brush:js">function f() { + return [1, 2, 3]; +} + +const [a, , b] = f(); +console.log(a); // 1 +console.log(b); // 3 +</pre> + +<p>當然你也可以忽略全部回傳值:</p> + +<pre class="brush:js">[,,] = f(); +</pre> + +<h3 id="把矩陣剩餘部分解構到一個變數">把矩陣剩餘部分解構到一個變數</h3> + +<p>解構一個陣列時,你可以透過其餘元素(rest pattern)將來源剩下之元素指派到一個變數:</p> + +<pre class="brush: js">const [a, ...b] = [1, 2, 3]; +console.log(a); // 1 +console.log(b); // [2, 3]</pre> + +<p>要注意的是,當左邊函式裡使用其餘解構,同時使用結尾逗號,這樣會拋出例外 {{jsxref("SyntaxError")}} :</p> + +<pre class="brush: js example-bad">const [a, ...b,] = [1, 2, 3]; + +// SyntaxError 語法錯誤: 其餘元素不可以跟隨結尾逗號 +// 需要把其餘運算子放在最後的元素 +</pre> + +<h3 id="從正則運算式的比對結果取值">從正則運算式的比對結果取值</h3> + +<p>當正則運算式的方法 <code><a href="/zh-TW/docs/Web/JavaScript/Reference/Global_Objects/RegExp/exec">exec()</a></code> 比對到一個值,其回傳陣列中的第一個值是相符的完整字串,後績的則是比對到正則運算式每組括號內的部分。當你沒需要利用第一個完整比對結果時,解構指派式讓你更簡單的取出後績元素。</p> + +<pre class="brush:js">function parseProtocol(url) { + const parsedURL = /^(\w+)\:\/\/([^\/]+)\/(.*)$/.exec(url); + if (!parsedURL) { + return false; + } + console.log(parsedURL); // ["https://developer.mozilla.org/en-US/Web/JavaScript", "https", "developer.mozilla.org", "en-US/Web/JavaScript"] + + const [, protocol, fullhost, fullpath] = parsedURL; + return protocol; +} + +console.log(parseProtocol('https://developer.mozilla.org/en-US/Web/JavaScript')); // "https" +</pre> + +<h2 id="物件解構">物件解構</h2> + +<h3 id="基本指派式">基本指派式</h3> + +<pre class="brush: js">const o = {p: 42, q: true}; +const {p, q} = o; + +console.log(p); // 42 +console.log(q); // true +</pre> + +<h3 id="無宣告指派">無宣告指派</h3> + +<p>變數可以在宣告式後,再透過解構進行指派。</p> + +<pre class="brush:js">let a, b; + +({a, b} = {a:1, b:2});</pre> + +<div class="note"> +<p><strong>注意</strong>:當針對物件進行解構,而該句式沒有進行宣告時,指派式外必須加上括號 <code>( ... )</code> 。</p> + +<p><code>{a, b} = {a: 1, b: 2}</code> 不是有效的獨立語法,因為左邊的 <code>{a, b}</code> 被視為程式碼區塊而非物件。</p> + +<p>然而,<code>({a, b} = {a: 1, b: 2})</code> 是有效的,如同 <code>const {a, b} = {a: 1, b: 2}</code></p> + +<p><code>( ... )</code> 表達式前句需要以分號結束,否則可能把上一句視為函式隨即執行。</p> +</div> + +<h3 id="指派到新的變數名稱">指派到新的變數名稱</h3> + +<p>物件中的屬性可以解構並擷取到名稱跟該屬性不一樣的變數。</p> + +<pre class="brush: js">const o = {p: 42, q: true}; +const {p: foo, q: bar} = o; + +console.log(foo); // 42 +console.log(bar); // true</pre> + +<p>舉例來說, <code>const {p: foo} = o</code> 把物件 <code>o</code> 裡名為 <code>p</code> 的屬性解出並指派到一個名為 <code>foo</code> 的本地變數。</p> + +<h3 id="預設值_2">預設值</h3> + +<p>當解構物件中對應的值是 <code>undefined</code> 時,變數可以設定預設值。</p> + +<pre class="brush: js">const {a = 10, b = 5} = {a: 3}; + +console.log(a); // 3 +console.log(b); // 5</pre> + +<h3 id="指定新的變數名稱及預設值">指定新的變數名稱及預設值</h3> + +<p>屬性 1) 可以從物件中被解開,且被指定一個不同名稱的變數及 2) 同時指定一個預設值,在解開的值為 <code>undefined</code> 時使用。</p> + +<pre class="brush: js">const {a:aa = 10, b:bb = 5} = {a: 3}; + +console.log(aa); // 3 +console.log(bb); // 5 +</pre> + +<h3 id="從作為函式參數的物件中提出某屬性的值">從作為函式參數的物件中提出某屬性的值</h3> + +<pre class="brush:js">const user = { + id: 42, + displayName: 'jdoe', + fullName: { + firstName: 'John', + lastName: 'Doe' + } +}; + +function userId({id}) { + return id; +} + +function whois({displayName, fullName: {firstName: name}}) { + return `${displayName} is ${name}`; +} + +console.log(userId(user)); // 42 +console.log(whois(user)); // "jdoe is John"</pre> + +<p>這樣從 user 物件中提出了 <code>id</code>, <code>displayName</code> 和 <code>firstName</code> 並且印出。</p> + +<h3 id="設定函式參數的預設值">設定函式參數的預設值</h3> + +<pre class="brush: js">function drawChart({size = 'big', coords = {x: 0, y: 0}, radius = 25} = {}) { + console.log(size, coords, radius); + // do some chart drawing +} + +drawChart({ + coords: {x: 18, y: 30}, + radius: 30 +});</pre> + +<div class="note"> +<p>在上述函式 <strong><code>drawChart</code></strong> 中,左方之解構式被指派到一個空物件: <code>{size = 'big', coords = {x: 0, y: 0}, radius = 25} = {}</code> 。你也可以略過填寫右方的指派式。不過,當你沒有使用右方指派式時,函式在呼叫時會找出最少一個參數。透過上述形式,你可以直接不使用參數的呼叫 <code><strong>drawChart()</strong></code> 。當你希望在呼叫這個函式時不傳送參數,這個設計會帶來方便。而另一個設計則能讓你確保函式必須傳上一個物件作為參數。</p> +</div> + +<h3 id="巢狀物件或陣列的解構">巢狀物件或陣列的解構</h3> + +<pre class="brush:js">const metadata = { + title: 'Scratchpad', + translations: [ + { + locale: 'de', + localization_tags: [], + last_edit: '2014-04-14T08:43:37', + url: '/de/docs/Tools/Scratchpad', + title: 'JavaScript-Umgebung' + } + ], + url: '/en-US/docs/Tools/Scratchpad' +}; + +let { + title: englishTitle, // rename + translations: [ + { + title: localeTitle, // rename + }, + ], +} = metadata; + +console.log(englishTitle); // "Scratchpad" +console.log(localeTitle); // "JavaScript-Umgebung"</pre> + +<h3 id="循環取出的解構">循環取出的解構</h3> + +<pre class="brush: js">const people = [ + { + name: 'Mike Smith', + family: { + mother: 'Jane Smith', + father: 'Harry Smith', + sister: 'Samantha Smith' + }, + age: 35 + }, + { + name: 'Tom Jones', + family: { + mother: 'Norah Jones', + father: 'Richard Jones', + brother: 'Howard Jones' + }, + age: 25 + } +]; + +for (const {name: n, family: {father: f}} of people) { + console.log('Name: ' + n + ', Father: ' + f); +} + +// "Name: Mike Smith, Father: Harry Smith" +// "Name: Tom Jones, Father: Richard Jones" +</pre> + +<h3 id="以物件演算屬性名稱解構">以物件演算屬性名稱解構</h3> + +<p>物件演算屬性名稱(像是在 <a href="/zh-TW/docs/Web/JavaScript/Reference/Operators/Object_initializer#Computed_property_names">object literals</a>)可以在解構指派式使用。</p> + +<pre class="brush: js">let key = 'z'; +let {[key]: foo} = {z: 'bar'}; + +console.log(foo); // "bar" +</pre> + +<h3 id="在物件解構時使用其餘變數">在物件解構時使用其餘變數</h3> + +<p><a class="external external-icon" href="https://github.com/tc39/proposal-object-rest-spread">ECMAScript 中的其餘/展開屬性</a>在 proposal (stage 4) 新增了在解構式內使用<a href="/zh-TW/docs/Web/JavaScript/Reference/Functions/rest_parameters">其餘 (rest)</a> 語法的定義。其餘屬性可以收集解構式中沒有指定的屬性值。</p> + +<pre class="brush: js">let {a, b, ...rest} = {a: 10, b: 20, c: 30, d: 40} +a; // 10 +b; // 20 +rest; // { c: 30, d: 40 }</pre> + +<h3 id="不符合_JavaScript_識別字的屬性名稱">不符合 JavaScript 識別字的屬性名稱</h3> + +<p>解構賦值可以透過另一個符合 JavaScript <a href="/zh-TW/docs/Glossary/Identifier">識別字</a>的變數名稱來解出不符合識別字的屬性。</p> + +<pre class="brush: js">const foo = { 'fizz-buzz': true }; +const { 'fizz-buzz': fizzBuzz } = foo; + +console.log(fizzBuzz); // "true" +</pre> + +<h3 id="混合使用矩陣及物件解構">混合使用矩陣及物件解構</h3> + +<p>矩陣及物件解構可以混合進行。與例來說,你只需要使用下列 <code>props</code> 矩陣中第三個元素之物件中的 <code>name</code> 屬性,你可以如下面的例子進行解構:</p> + +<pre class="brush: js">const props = [ + { id: 1, name: 'Fizz'}, + { id: 2, name: 'Buzz'}, + { id: 3, name: 'FizzBuzz'} +]; + +const [,, { name }] = props; + +console.log(name); // "FizzBuzz" +</pre> + +<h3 id="物件解構時的原型鏈追溯">物件解構時的原型鏈追溯</h3> + +<p>在進行物件解構時,如果一個屬性不在其當下存取,將會透過原型鏈 (prototype chain) 來進行追溯。</p> + +<pre>let obj = {self: '123'}; +obj.__proto__.prot = '456'; +const {self, prot} = obj; +// self "123" +// prot "456"(Access to the prototype chain)</pre> + +<h2 id="規範">規範</h2> + +<table class="standard-table"> + <tbody> + <tr> + <th scope="col">規範</th> + </tr> + <tr> + <td>{{SpecName('ESDraft', '#sec-destructuring-assignment', 'Destructuring assignment')}}</td> + </tr> + </tbody> +</table> + +<h2 id="瀏覽器相容性">瀏覽器相容性</h2> + +<div> + + +<p>{{Compat("javascript.operators.destructuring")}}</p> +</div> + +<h2 id="參見">參見</h2> + +<ul> + <li><a href="/zh-TW/docs/Web/JavaScript/Reference/Operators/Assignment_Operators">Assignment operators</a></li> + <li><a href="https://hacks.mozilla.org/2015/05/es6-in-depth-destructuring/">"ES6 in Depth: Destructuring" on hacks.mozilla.org</a></li> +</ul> diff --git a/files/zh-tw/web/javascript/reference/operators/index.html b/files/zh-tw/web/javascript/reference/operators/index.html new file mode 100644 index 0000000000..e6efa9a181 --- /dev/null +++ b/files/zh-tw/web/javascript/reference/operators/index.html @@ -0,0 +1,301 @@ +--- +title: 運算式與運算子 +slug: Web/JavaScript/Reference/Operators +tags: + - NeedsTranslation + - TopicStub + - 運算子 +translation_of: Web/JavaScript/Reference/Operators +--- +<div>{{jsSidebar("Operators")}}</div> + +<p>本章節記錄了所有 JavaScript 運算式、運算子以及關鍵字。</p> + +<h2 id="運算式與運算子分類">運算式與運算子分類</h2> + +<p>以字母排列的清單請參考左側的側邊欄。</p> + +<h3 id="主要運算式">主要運算式</h3> + +<p>在 JavaScript 中基本的關鍵字與一般的運算式。</p> + +<dl> + <dt>{{jsxref("Operators/this", "this")}}</dt> + <dd><code>this</code> 關鍵字可以參考執行函數的所在位置。</dd> + <dt>{{jsxref("Operators/function", "function")}}</dt> + <dd><code>function</code> 關鍵字可以定義一個函數運算式。</dd> + <dt>{{jsxref("Operators/class", "class")}}</dt> + <dd><code>class</code> 關鍵字可以定義一個類別運算式。</dd> + <dt>{{jsxref("Operators/function*", "function*")}}</dt> + <dd><code>function*</code> 關鍵字可以定義一個 Generator 函數運算式</dd> + <dt>{{jsxref("Operators/yield", "yield")}}</dt> + <dd>暫停與繼續一個產生器 (Generator) 函數。</dd> + <dt>{{jsxref("Operators/yield*", "yield*")}}</dt> + <dd>轉交另一個產生器 (Generator) 函數或可迭代 (Iterable) 的物件。</dd> + <dt>{{experimental_inline}} {{jsxref("Operators/async_function", "async function*")}}</dt> + <dd><code>async</code> 函數可以定義一個非同步函數運算式。</dd> + <dt>{{experimental_inline}} {{jsxref("Operators/await", "await")}}</dt> + <dd>暫停與繼續一個非同步函數並等候承諾的結果/拒絕。</dd> + <dt>{{jsxref("Global_Objects/Array", "[]")}}</dt> + <dd>陣列初始化/書寫格式。</dd> + <dt>{{jsxref("Operators/Object_initializer", "{}")}}</dt> + <dd>物件初始化/書寫格式。</dd> + <dt>{{jsxref("Global_Objects/RegExp", "/ab+c/i")}}</dt> + <dd>正規表示法書寫格式。</dd> + <dt>{{jsxref("Operators/Grouping", "( )")}}</dt> + <dd>分組運算子。</dd> +</dl> + +<h3 id="左手邊運算式">左手邊運算式</h3> + +<p>左側值為賦值的目標。</p> + +<dl> + <dt>{{jsxref("Operators/Property_accessors", "Property accessors", "", 1)}}</dt> + <dd>成員運算子可存取物件的屬性或方法<br> + (<code>object.property</code> and <code>object["property"]</code>)。</dd> + <dt>{{jsxref("Operators/new", "new")}}</dt> + <dd><code>new</code> 運算子可以建立一個建構子 (Constructor) 的實例。</dd> + <dt><a href="/zh-TW/docs/Web/JavaScript/Reference/Operators/new.target">new.target</a></dt> + <dd>在建構子中 <code>new.target</code> 可以參考被 {{jsxref("Operators/new", "new")}} 呼叫的建構子 (Constructor) 。</dd> + <dt>{{jsxref("Operators/super", "super")}}</dt> + <dd><code>super</code> 關鍵字可以呼叫父建構子 (Constructor) 。</dd> + <dt>{{jsxref("Operators/Spread_operator", "...obj")}}</dt> + <dd>The spread operator allows an expression to be expanded in places where multiple arguments (for function calls) or multiple elements (for array literals) are expected.</dd> +</dl> + +<h3 id="遞增與遞減">遞增與遞減</h3> + +<p>字尾/字首遞增與字尾/字首遞減運算子。</p> + +<dl> + <dt>{{jsxref("Operators/Arithmetic_Operators", "A++", "#Increment")}}</dt> + <dd>字尾遞增運算子。</dd> + <dt>{{jsxref("Operators/Arithmetic_Operators", "A--", "#Decrement")}}</dt> + <dd>字尾遞減運算子。</dd> + <dt>{{jsxref("Operators/Arithmetic_Operators", "++A", "#Increment")}}</dt> + <dd>字首遞增運算子。</dd> + <dt>{{jsxref("Operators/Arithmetic_Operators", "--A", "#Decrement")}}</dt> + <dd>字首遞減運算子。</dd> +</dl> + +<h3 id="一元運算子">一元運算子</h3> + +<p>一元運算是指只需要使用一個運算元的運算。</p> + +<dl> + <dt>{{jsxref("Operators/delete", "delete")}}</dt> + <dd><code>delete</code> 運算子可刪除物件中的屬性。</dd> + <dt>{{jsxref("Operators/void", "void")}}</dt> + <dd><code>void</code> 運算子可放棄一個運算式的回傳值。</dd> + <dt>{{jsxref("Operators/typeof", "typeof")}}</dt> + <dd><code>typeof</code> 運算子可以判斷一個指定物件的型態。</dd> + <dt>{{jsxref("Operators/Arithmetic_Operators", "+", "#Unary_plus")}}</dt> + <dd>一元正運算子可以轉換其運算元成為數值 (Number) 型態。</dd> + <dt>{{jsxref("Operators/Arithmetic_Operators", "-", "#Unary_negation")}}</dt> + <dd>一元負運算子可以轉換其運算元成為數值 (Number) 型態並轉為負值。</dd> + <dt>{{jsxref("Operators/Bitwise_Operators", "~", "#Bitwise_NOT")}}</dt> + <dd>元位 NOT 運算子。</dd> + <dt>{{jsxref("Operators/Logical_Operators", "!", "#Logical_NOT")}}</dt> + <dd>邏輯 NOT 運算子。</dd> +</dl> + +<h3 id="算術運算子">算術運算子</h3> + +<p>算術運算子會要用到數值 (不論是字面值或者變數) 做為運算元,並且會回傳單一數值結果。</p> + +<dl> + <dt>{{jsxref("Operators/Arithmetic_Operators", "+", "#Addition")}}</dt> + <dd>加法運算子。</dd> + <dt>{{jsxref("Operators/Arithmetic_Operators", "-", "#Subtraction")}}</dt> + <dd>減法運算子。</dd> + <dt>{{jsxref("Operators/Arithmetic_Operators", "/", "#Division")}}</dt> + <dd>除法運算子。</dd> + <dt>{{jsxref("Operators/Arithmetic_Operators", "*", "#Multiplication")}}</dt> + <dd>乘法運算子。</dd> + <dt>{{jsxref("Operators/Arithmetic_Operators", "%", "#Remainder")}}</dt> + <dd>餘數運算子。</dd> +</dl> + +<dl> + <dt>{{jsxref("Operators/Arithmetic_Operators", "**", "#Exponentiation")}}</dt> + <dd>指數運算子。</dd> +</dl> + +<h3 id="關係運算子">關係運算子</h3> + +<p>比較運算子會比較其運算元並根據比較的結果是否成立回傳一個 <code>Boolean</code> 值的結果。</p> + +<dl> + <dt>{{jsxref("Operators/in", "in")}}</dt> + <dd><code>in</code> 運算子會判斷一個物件是否有指定的屬性。</dd> + <dt>{{jsxref("Operators/instanceof", "instanceof")}}</dt> + <dd><code>instanceof</code> 運算子會判斷一個物件是否為另一個物件的實例。</dd> + <dt>{{jsxref("Operators/Comparison_Operators", "<", "#Less_than_operator")}}</dt> + <dd>小於運算子。</dd> + <dt>{{jsxref("Operators/Comparison_Operators", ">", "#Greater_than_operator")}}</dt> + <dd>大於運算子。</dd> + <dt>{{jsxref("Operators/Comparison_Operators", "<=", "#Less_than_or_equal_operator")}}</dt> + <dd>小於等於運算子。</dd> + <dt>{{jsxref("Operators/Comparison_Operators", ">=", "#Greater_than_or_equal_operator")}}</dt> + <dd>大於等於運算子。</dd> +</dl> + +<div class="note"> +<p><strong>Note: =></strong> is not an operator, but the notation for <a href="/zh-TW/docs/Web/JavaScript/Reference/Functions/Arrow_functions">Arrow functions</a>.</p> +</div> + +<h3 id="相等運算子">相等運算子</h3> + +<p>執行相對運算子後的結果為比較結果是否成立的 <code>Boolean</code> 值。</p> + +<dl> + <dt>{{jsxref("Operators/Comparison_Operators", "==", "#Equality")}}</dt> + <dd>相等運算子。</dd> + <dt>{{jsxref("Operators/Comparison_Operators", "!=", "#Inequality")}}</dt> + <dd>不相等運算子。</dd> + <dt>{{jsxref("Operators/Comparison_Operators", "===", "#Identity")}}</dt> + <dd>恆等運算子。</dd> + <dt>{{jsxref("Operators/Comparison_Operators", "!==", "#Nonidentity")}}</dt> + <dd>不恆等運算子。</dd> +</dl> + +<h3 id="位元移位運算子">位元移位運算子</h3> + +<p>用來位移運算元所有位元的運算。</p> + +<dl> + <dt>{{jsxref("Operators/Bitwise_Operators", "<<", "#Left_shift")}}</dt> + <dd>左移位元運算子。</dd> + <dt>{{jsxref("Operators/Bitwise_Operators", ">>", "#Right_shift")}}</dt> + <dd>右移位元運算子。</dd> + <dt>{{jsxref("Operators/Bitwise_Operators", ">>>", "#Unsigned_right_shift")}}</dt> + <dd>右移無號位元運算子。</dd> +</dl> + +<h3 id="二元位元運算子">二元位元運算子</h3> + +<p>位元運算子將其運算元當做是 32 位元 (32 個零與一) 的數值處理並回傳標準 JavaScript 數值。</p> + +<dl> + <dt>{{jsxref("Operators/Bitwise_Operators", "&", "#Bitwise_AND")}}</dt> + <dd>位元 AND。</dd> + <dt>{{jsxref("Operators/Bitwise_Operators", "|", "#Bitwise_OR")}}</dt> + <dd>位元 OR。</dd> + <dt>{{jsxref("Operators/Bitwise_Operators", "^", "#Bitwise_XOR")}}</dt> + <dd>位元 XOR。</dd> +</dl> + +<h3 id="二元邏輯運算子">二元邏輯運算子</h3> + +<p>邏輯運算子一般用在處理布林 (邏輯) 值,它們存在的地方會回傳一個布林 (Boolean) 值。</p> + +<dl> + <dt>{{jsxref("Operators/Logical_Operators", "&&", "#Logical_AND")}}</dt> + <dd>邏輯 AND。</dd> + <dt>{{jsxref("Operators/Logical_Operators", "||", "#Logical_OR")}}</dt> + <dd>邏輯 OR。</dd> +</dl> + +<h3 id="條件_(三元)_運算子">條件 (三元) 運算子</h3> + +<dl> + <dt>{{jsxref("Operators/Conditional_Operator", "(condition ? ifTrue : ifFalse)")}}</dt> + <dd> + <p>條件運算子會根據條件的邏輯值判斷並回傳其中一個值。</p> + </dd> +</dl> + +<h3 id="賦值運算子">賦值運算子</h3> + +<p>賦值運算子會根據其右側運算元的數值處理後賦值給其左側的運算元。</p> + +<dl> + <dt>{{jsxref("Operators/Assignment_Operators", "=", "#Assignment")}}</dt> + <dd>賦值運算子。</dd> + <dt>{{jsxref("Operators/Assignment_Operators", "*=", "#Multiplication_assignment")}}</dt> + <dd>乘法賦值。</dd> + <dt>{{jsxref("Operators/Assignment_Operators", "/=", "#Division_assignment")}}</dt> + <dd>除法賦值。</dd> + <dt>{{jsxref("Operators/Assignment_Operators", "%=", "#Remainder_assignment")}}</dt> + <dd>餘數賦值。</dd> + <dt>{{jsxref("Operators/Assignment_Operators", "+=", "#Addition_assignment")}}</dt> + <dd>加法賦值。</dd> + <dt>{{jsxref("Operators/Assignment_Operators", "-=", "#Subtraction_assignment")}}</dt> + <dd>減法賦值。</dd> + <dt>{{jsxref("Operators/Assignment_Operators", "<<=", "#Left_shift_assignment")}}</dt> + <dd>左移賦值。</dd> + <dt>{{jsxref("Operators/Assignment_Operators", ">>=", "#Right_shift_assignment")}}</dt> + <dd>右移賦值。</dd> + <dt>{{jsxref("Operators/Assignment_Operators", ">>>=", "#Unsigned_right_shift_assignment")}}</dt> + <dd>無號右移賦值。</dd> + <dt>{{jsxref("Operators/Assignment_Operators", "&=", "#Bitwise_AND_assignment")}}</dt> + <dd>位元 AND 賦值。</dd> + <dt>{{jsxref("Operators/Assignment_Operators", "^=", "#Bitwise_XOR_assignment")}}</dt> + <dd>位元 XOR 賦值。</dd> + <dt>{{jsxref("Operators/Assignment_Operators", "|=", "#Bitwise_OR_assignment")}}</dt> + <dd>位元 OR 賦值。</dd> + <dt>{{jsxref("Operators/Destructuring_assignment", "[a, b] = [1, 2]")}}<br> + {{jsxref("Operators/Destructuring_assignment", "{a, b} = {a:1, b:2}")}}</dt> + <dd> + <p>解構賦值讓您可使用如陣列或物件書寫格式來賦值給陣列或物件的屬性。</p> + </dd> +</dl> + +<h3 id="逗號運算子">逗號運算子</h3> + +<dl> + <dt>{{jsxref("Operators/Comma_Operator", ",")}}</dt> + <dd>逗號運算子允許在一個敘述句中執行多個運算式並回傳最後一個運算式的結果。</dd> +</dl> + +<h3 id="非標準功能">非標準功能</h3> + +<dl> + <dt>{{non-standard_inline}} {{jsxref("Operators/Legacy_generator_function", "Legacy generator function", "", 1)}}</dt> + <dd>The <code>function</code> keyword can be used to define a legacy generator function inside an expression. To make the function a legacy generator, the function body should contains at least one {{jsxref("Operators/yield", "yield")}} expression.</dd> + <dt>{{non-standard_inline}} {{jsxref("Operators/Expression_closures", "Expression closures", "", 1)}}</dt> + <dd>The expression closure syntax is a shorthand for writing simple function.</dd> + <dt>{{non-standard_inline}} {{jsxref("Operators/Array_comprehensions", "[for (x of y) x]")}}</dt> + <dd>Array comprehensions.</dd> + <dt>{{non-standard_inline}} {{jsxref("Operators/Generator_comprehensions", "(for (x of y) y)")}}</dt> + <dd>Generator comprehensions.</dd> +</dl> + +<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('ES1', '#sec-11', 'Expressions')}}</td> + <td>{{Spec2('ES1')}}</td> + <td>Initial definition</td> + </tr> + <tr> + <td>{{SpecName('ES5.1', '#sec-11', 'Expressions')}}</td> + <td>{{Spec2('ES5.1')}}</td> + <td> </td> + </tr> + <tr> + <td>{{SpecName('ES6', '#sec-ecmascript-language-expressions', 'ECMAScript Language: Expressions')}}</td> + <td>{{Spec2('ES6')}}</td> + <td>New: Spread operator, destructuring assignment, <code>super</code> keyword.</td> + </tr> + <tr> + <td>{{SpecName('ESDraft', '#sec-ecmascript-language-expressions', 'ECMAScript Language: Expressions')}}</td> + <td>{{Spec2('ESDraft')}}</td> + <td> </td> + </tr> + </tbody> +</table> + +<h2 id="相關文獻">相關文獻</h2> + +<ul> + <li><a href="/zh-TW/docs/Web/JavaScript/Reference/Operators/Operator_Precedence">Operator precedence</a></li> +</ul> diff --git a/files/zh-tw/web/javascript/reference/operators/logical_operators/index.html b/files/zh-tw/web/javascript/reference/operators/logical_operators/index.html new file mode 100644 index 0000000000..9a7138244c --- /dev/null +++ b/files/zh-tw/web/javascript/reference/operators/logical_operators/index.html @@ -0,0 +1,243 @@ +--- +title: Logical operators +slug: Web/JavaScript/Reference/Operators/Logical_Operators +translation_of: Web/JavaScript/Reference/Operators +--- +<div>{{jsSidebar("Operators")}}</div> + +<p>邏輯運算子通常會搭配 {{jsxref("Boolean")}} (logical) 值。若是,則回傳布林值。然而, <code>&&</code> 和 <code>||</code> 運算子通常回傳其中一運算元的值, 因此若這些運算子搭配非布林值使用,他們會回傳非布林值。</p> + +<div>{{EmbedInteractiveExample("pages/js/expressions-logicaloperator.html")}}</div> + + + +<h2 id="說明">說明</h2> + +<p>邏輯運算子的使用方式如下(<code><em>expr</em></code> 可能會是 <a href="/en-US/docs/Glossary/Data_structure">type</a>,不只是布林值):</p> + +<table class="fullwidth-table"> + <tbody> + <tr> + <th>Operator</th> + <th>Syntax</th> + <th>Description</th> + </tr> + <tr> + <td>邏輯 AND (<code>&&</code>)</td> + <td><code><em>expr1</em> && <em>expr2</em></code></td> + <td>若 <code>expr<strong>1</strong></code> 可被轉換成 <code>true</code>, 回傳 <code>expr<strong>2</strong></code>; 否則 回傳 <code>expr<strong>1</strong></code>.</td> + </tr> + <tr> + <td>邏輯 OR (<code>||</code>)</td> + <td><code><em>expr1</em> || <em>expr2</em></code></td> + <td>若 <code>expr<strong>1</strong></code> 可被轉換成 <code>true</code>, 回傳 <code>expr<strong>1</strong></code>; 否則 回傳 <code>expr<strong>2</strong></code>.</td> + </tr> + <tr> + <td>邏輯 NOT (<code>!</code>)</td> + <td><code>!<em>expr</em></code></td> + <td>回傳 <code>false</code> 若它的單一運算元可被轉換成 <code>true</code>; 否則回傳 <code>true</code>.</td> + </tr> + </tbody> +</table> + +<p>If a value can be converted to <code>true</code>, the value is so-called {{Glossary("truthy")}}. If a value can be converted to <code>false</code>, the value is so-called {{Glossary("falsy")}}.</p> + +<p>Examples of expressions that can be converted to false are:</p> + +<ul> + <li><code>null</code>;</li> + <li><code>NaN</code>;</li> + <li><code>0</code>;</li> + <li>empty string (<code>""</code> or <code>''</code> or <code>``</code>);</li> + <li><code>undefined</code>.</li> +</ul> + +<p>Even though the <code>&&</code> and <code>||</code> operators can be used with operands that are not Boolean values, they can still be considered boolean operators since their return values can always be converted to <a href="/en-US/docs/Web/JavaScript/Data_structures#Boolean_type">boolean primitives</a>. To explicitly convert their return value (or any expression in general) to the corresponding boolean value, use a double <a href="/en-US/docs/Web/JavaScript/Reference/Operators/Logical_Operators#Logical_NOT">NOT operator</a> or the <a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean">Boolean</a> constructor.</p> + +<h3 id="Short-circuit_evaluation">Short-circuit evaluation</h3> + +<p>As logical expressions are evaluated left to right, they are tested for possible "short-circuit" evaluation using the following rules:</p> + +<ul> + <li><code>(some falsy expression) && <em>expr</em></code> is short-circuit evaluated to the falsy expression;</li> + <li><code>(some truthy expression) || <em>expr</em></code> is short-circuit evaluated to the truthy expression.</li> +</ul> + +<p>Short circuit means that the <em>expr</em> parts above are <strong>not evaluated</strong>, hence any side effects of doing so do not take effect (e.g., if <em>expr</em> is a function call, the calling never takes place). This happens because the value of the operator is already determined after the evaluation of the first operand. See example:</p> + +<pre class="brush: js">function A(){ console.log('called A'); return false; } +function B(){ console.log('called B'); return true; } + +console.log( A() && B() ); +// logs "called A" due to the function call, +// then logs false (which is the resulting value of the operator) + +console.log( B() || A() ); +// logs "called B" due to the function call, +// then logs true (which is the resulting value of the operator) +</pre> + +<h3 id="Operator_precedence">Operator precedence</h3> + +<p>The following expressions might seem equivalent, but they are not, because the <code>&&</code> operator is executed before the <code>||</code> operator (see <a href="/en-US/docs/Web/JavaScript/Reference/Operators/Operator_Precedence">operator precedence</a>).</p> + +<pre class="brush: js">true || false && false // returns true, because && is executed first +(true || false) && false // returns false, because operator precedence cannot apply</pre> + +<h3 id="Logical_AND_()"><a name="Logical_AND">Logical AND (<code>&&</code>)</a></h3> + +<p>The following code shows examples of the <code>&&</code> (logical AND) operator.</p> + +<pre class="brush: js">a1 = true && true // t && t returns true +a2 = true && false // t && f returns false +a3 = false && true // f && t returns false +a4 = false && (3 == 4) // f && f returns false +a5 = 'Cat' && 'Dog' // t && t returns "Dog" +a6 = false && 'Cat' // f && t returns false +a7 = 'Cat' && false // t && f returns false +a8 = '' && false // f && f returns "" +a9 = false && '' // f && f returns false +</pre> + +<h3 id="Logical_OR_()"><a name="Logical_OR">Logical OR (<code>||</code>)</a></h3> + +<p>The following code shows examples of the <code>||</code> (logical OR) operator.</p> + +<pre class="brush: js">o1 = true || true // t || t returns true +o2 = false || true // f || t returns true +o3 = true || false // t || f returns true +o4 = false || (3 == 4) // f || f returns false +o5 = 'Cat' || 'Dog' // t || t returns "Cat" +o6 = false || 'Cat' // f || t returns "Cat" +o7 = 'Cat' || false // t || f returns "Cat" +o8 = '' || false // f || f returns false +o9 = false || '' // f || f returns "" +o10 = false || varObject // f || object returns varObject +</pre> + +<h3 id="Logical_NOT_(!)"><a name="Logical_NOT">Logical NOT (<code>!</code>)</a></h3> + +<p>The following code shows examples of the <code>!</code> (logical NOT) operator.</p> + +<pre class="brush: js">n1 = !true // !t returns false +n2 = !false // !f returns true +n3 = !'' // !f returns true +n4 = !'Cat' // !t returns false +</pre> + +<h4 id="Double_NOT_(!!)">Double NOT (<code>!!</code>)</h4> + +<p>It is possible to use a couple of NOT operators in series to explicitly force the conversion of any value to the corresponding <a href="/en-US/docs/Web/JavaScript/Data_structures#Boolean_type">boolean primitive</a>. The conversion is based on the "truthyness" or "falsyness" of the value (see {{Glossary("truthy")}} and {{Glossary("falsy")}}).</p> + +<p>The same conversion can be done through the {{jsxref("Boolean")}} function.</p> + +<pre class="brush: js">n1 = !!true // !!truthy returns true +n2 = !!{} // !!truthy returns true: <strong>any</strong> object is truthy... +n3 = !!(new Boolean(false)) // ...even Boolean objects with a false <em>.valueOf()</em>! +n4 = !!false // !!falsy returns false +n5 = !!"" // !!falsy returns false +n6 = !!Boolean(false) // !!falsy returns false +</pre> + +<h3 id="Conversion_rules_for_booleans">Conversion rules for booleans</h3> + +<h4 id="Converting_AND_to_OR">Converting AND to OR</h4> + +<p>The following operation involving <strong>booleans</strong>:</p> + +<pre class="brush: js">bCondition1 && bCondition2</pre> + +<p>is always equal to:</p> + +<pre class="brush: js">!(!bCondition1 || !bCondition2)</pre> + +<h4 id="Converting_OR_to_AND">Converting OR to AND</h4> + +<p>The following operation involving <strong>booleans</strong>:</p> + +<pre class="brush: js">bCondition1 || bCondition2</pre> + +<p>is always equal to:</p> + +<pre class="brush: js">!(!bCondition1 && !bCondition2)</pre> + +<h4 id="Converting_between_NOTs">Converting between NOTs</h4> + +<p>The following operation involving <strong>booleans</strong>:</p> + +<pre class="brush: js">!!bCondition</pre> + +<p>is always equal to:</p> + +<pre class="brush: js">bCondition</pre> + +<h3 id="Removing_nested_parentheses">Removing nested parentheses</h3> + +<p>As logical expressions are evaluated left to right, it is always possible to remove parentheses from a complex expression following some rules.</p> + +<h4 id="Removing_nested_AND">Removing nested AND</h4> + +<p>The following composite operation involving <strong>booleans</strong>:</p> + +<pre class="brush: js">bCondition1 || (bCondition2 && bCondition3)</pre> + +<p>is always equal to:</p> + +<pre class="brush: js">bCondition1 || bCondition2 && bCondition3</pre> + +<h4 id="Removing_nested_OR">Removing nested OR</h4> + +<p>The following composite operation involving <strong>booleans</strong>:</p> + +<pre class="brush: js">bCondition1 && (bCondition2 || bCondition3)</pre> + +<p>is always equal to:</p> + +<pre class="brush: js">!(!bCondition1 || !bCondition2 && !bCondition3)</pre> + +<h2 id="Specifications">Specifications</h2> + +<table class="standard-table"> + <tbody> + <tr> + <th scope="col">Specification</th> + <th scope="col">Status</th> + <th scope="col">Comment</th> + </tr> + <tr> + <td>{{SpecName('ES1')}}</td> + <td>{{Spec2('ES1')}}</td> + <td>Initial definition.</td> + </tr> + <tr> + <td>{{SpecName('ES5.1', '#sec-11.11')}}</td> + <td>{{Spec2('ES5.1')}}</td> + <td>Defined in several sections of the specification: <a href="http://www.ecma-international.org/ecma-262/5.1/#sec-11.4.9">Logical NOT Operator</a>, <a href="http://www.ecma-international.org/ecma-262/5.1/#sec-11.11">Binary Logical Operators</a></td> + </tr> + <tr> + <td>{{SpecName('ES6', '#sec-binary-logical-operators')}}</td> + <td>{{Spec2('ES6')}}</td> + <td>Defined in several sections of the specification: <a href="http://www.ecma-international.org/ecma-262/6.0/#sec-logical-not-operator">Logical NOT Operator</a>, <a href="http://www.ecma-international.org/ecma-262/6.0/#sec-binary-logical-operators">Binary Logical Operators</a></td> + </tr> + <tr> + <td>{{SpecName('ESDraft', '#sec-binary-logical-operators')}}</td> + <td>{{Spec2('ESDraft')}}</td> + <td>Defined in several sections of the specification: <a href="http://tc39.github.io/ecma262/#sec-logical-not-operator">Logical NOT Operator</a>, <a href="http://tc39.github.io/ecma262/#sec-binary-logical-operators">Binary Logical Operators</a></td> + </tr> + </tbody> +</table> + +<h2 id="Browser_compatibility">Browser compatibility</h2> + + + +<p>{{Compat("javascript.operators.logical")}}</p> + +<h2 id="See_also">See also</h2> + +<ul> + <li><a href="/en-US/docs/Web/JavaScript/Reference/Operators/Bitwise_Operators">Bitwise operators</a></li> + <li>{{jsxref("Boolean")}}</li> + <li><a href="/en-US/docs/Glossary/Truthy">Truthy</a></li> + <li><a href="/en-US/docs/Glossary/Falsy">Falsy</a></li> +</ul> diff --git a/files/zh-tw/web/javascript/reference/operators/object_initializer/index.html b/files/zh-tw/web/javascript/reference/operators/object_initializer/index.html new file mode 100644 index 0000000000..c8e4308f32 --- /dev/null +++ b/files/zh-tw/web/javascript/reference/operators/object_initializer/index.html @@ -0,0 +1,431 @@ +--- +title: Object initializer +slug: Web/JavaScript/Reference/Operators/Object_initializer +translation_of: Web/JavaScript/Reference/Operators/Object_initializer +--- +<div>{{JsSidebar("Operators")}}</div> + +<p>Objects can be initialized using <a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object"><code>new Object()</code></a>,<code> <a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/create">Object.create()</a></code>, or using the <em>literal</em> notation (<em>initializer</em> notation). An object initializer is a comma-delimited list of zero or more pairs of property names and associated values of an object, enclosed in curly braces (<code>{}</code>).</p> + +<h2 id="語法">語法</h2> + +<pre class="brush: js">var o = {}; +var o = {a: 'foo', b: 42, c: {}}; + +var a = 'foo', b = 42, c = {}; +var o = {a: a, b: b, c: c}; + +var o = { + <var>property: function </var>([<var>parameters</var>]) {}, + get <var>property</var>() {}, + set <var>property</var>(<var>value</var>) {} +}; +</pre> + +<h3 id="New_notations_in_ECMAScript_2015">New notations in ECMAScript 2015</h3> + +<p>Please see the compatibility table for support for these notations. In non-supporting environments, these notations will lead to syntax errors.</p> + +<pre class="brush: js">// Shorthand property names (ES2015) +var a = 'foo', b = 42, c = {}; +var o = {a, b, c}; + +// Shorthand method names (ES2015) +var o = { + <var>property</var>([<var>parameters</var>]) {} +}; + +// Computed property names (ES2015) +var prop = 'foo'; +var o = { + [prop]: 'hey', + ['b' + 'ar']: 'there' +};</pre> + +<h2 id="說明">說明</h2> + +<p>An object initializer is an expression that describes the initialization of an {{jsxref("Object")}}. Objects consist of <em>properties</em>, which are used to describe an object. Values of object properties can either contain {{Glossary("primitive")}} data types or other objects.</p> + +<h3 id="建立物件">建立物件</h3> + +<p>An empty object with no properties can be created like this:</p> + +<pre class="brush: js">var object = {};</pre> + +<p>However, the advantage of the <em>literal</em> or <em>initializer</em> notation is, that you are able to quickly create objects with properties inside the curly braces. You simply notate a list of <code>key: value</code> pairs delimited by comma. The following code creates an object with three properties and the keys are <code>"foo"</code>, <code>"age"</code> and <code>"baz"</code>. The values of these keys are a string <code>"bar"</code>, a number <code>42</code> and the third property has another object as its value.</p> + +<pre class="brush: js">var object = { + foo: 'bar', + age: 42, + baz: {myProp: 12} +}</pre> + +<h3 id="存取屬性">存取屬性</h3> + +<p>Once you have created an object, you might want to read or change them. Object properties can be accessed by using the dot notation or the bracket notation. See <a href="/en-US/docs/Web/JavaScript/Reference/Operators/Property_Accessors">property accessors</a> for detailed information.</p> + +<pre class="brush: js">object.foo; // "bar" +object['age']; // 42 + +object.foo = 'baz'; +</pre> + +<h3 id="屬性定義">屬性定義</h3> + +<p>We have already learned how to notate properties using the initializer syntax. Oftentimes, there are variables in your code that you would like to put into an object. You will see code like this:</p> + +<pre class="brush: js">var a = 'foo', + b = 42, + c = {}; + +var o = { + a: a, + b: b, + c: c +};</pre> + +<p>With ECMAScript 2015, there is a shorter notation available to achieve the same:</p> + +<pre class="brush: js">var a = 'foo', + b = 42, + c = {}; + +// Shorthand property names (ES2015) +var o = {a, b, c}; + +// In other words, +console.log((o.a === {a}.a)); // true +</pre> + +<h4 id="Duplicate_property_names">Duplicate property names</h4> + +<p>When using the same name for your properties, the second property will overwrite the first.</p> + +<pre class="brush: js">var a = {x: 1, x: 2}; +console.log(a); // {x: 2} +</pre> + +<p>In ECMAScript 5 strict mode code, duplicate property names were considered a {{jsxref("SyntaxError")}}. With the introduction of computed property names making duplication possible at runtime, ECMAScript 2015 has removed this restriction.</p> + +<pre class="brush: js">function haveES2015DuplicatePropertySemantics() { + 'use strict'; + try { + ({prop: 1, prop: 2}); + + // No error thrown, duplicate property names allowed in strict mode + return true; + } catch(e) { + // Error thrown, duplicates prohibited in strict mode + return false; + } +}</pre> + +<h3 id="方法定義">方法定義</h3> + +<p>A property of an object can also refer to a <a href="/en-US/docs/Web/JavaScript/Reference/Functions">function</a> or a <a href="/en-US/docs/Web/JavaScript/Reference/Functions/get">getter</a> or <a href="/en-US/docs/Web/JavaScript/Reference/Functions/set">setter</a> method.</p> + +<pre class="brush: js">var o = { + <var>property: function </var>([<var>parameters</var>]) {}, + get <var>property</var>() {}, + set <var>property</var>(<var>value</var>) {} +};</pre> + +<p>In ECMAScript 2015, a shorthand notation is available, so that the keyword "function" is no longer necessary.</p> + +<pre class="brush: js">// Shorthand method names (ES2015) +var o = { + <var>property</var>([<var>parameters</var>]) {}, + *<var>generator</var>() {} +};</pre> + +<p>In ECMAScript 2015 There is a way to concisely define properties whose values are generator functions:</p> + +<pre class="brush: js">var o = { + *<var>generator</var>() { + ........... + } +};</pre> + +<p>Which is equivalent to this ES5-like notation (but note that ECMAScript 5 has no generators):</p> + +<pre class="brush: js">var o = { + generator<var>: function* </var>() { + ........... + } +};</pre> + +<p>For more information and examples about methods, see <a href="/en-US/docs/Web/JavaScript/Reference/Functions/Method_definitions">method definitions</a>.</p> + +<h3 id="Computed_property_names">Computed property names</h3> + +<p>Starting with ECMAScript 2015, the object initializer syntax also supports computed property names. That allows you to put an expression in brackets <code>[]</code>, that will be computed as the property name. This is symmetrical to the bracket notation of the <a href="/en-US/docs/Web/JavaScript/Reference/Operators/Property_Accessors">property accessor</a> syntax, which you might have used to read and set properties already. Now you can use the same syntax in object literals, too:</p> + +<pre class="brush: js">// Computed property names (ES2015) +var i = 0; +var a = { + ['foo' + ++i]: i, + ['foo' + ++i]: i, + ['foo' + ++i]: i +}; + +console.log(a.foo1); // 1 +console.log(a.foo2); // 2 +console.log(a.foo3); // 3 + +var param = 'size'; +var config = { + [param]: 12, + ['mobile' + param.charAt(0).toUpperCase() + param.slice(1)]: 4 +}; + +console.log(config); // {size: 12, mobileSize: 4}</pre> + +<h3 id="Spread_properties">Spread properties</h3> + +<p>The <a href="https://github.com/tc39/proposal-object-rest-spread">Rest/Spread Properties for ECMAScript</a> proposal (stage 3) adds <a href="/en-US/docs/Web/JavaScript/Reference/Operators/Spread_operator">spread</a> properties to object literals. It copies own enumerable properties from a provided object onto a new object.</p> + +<p>Shallow-cloning (excluding prototype) or merging objects is now possible using a shorter syntax than {{jsxref("Object.assign()")}}.</p> + +<pre class="brush: js">var obj1 = { foo: 'bar', x: 42 }; +var obj2 = { foo: 'baz', y: 13 }; + +var clonedObj = { ...obj1 }; +// Object { foo: "bar", x: 42 } + +var mergedObj = { ...obj1, ...obj2 }; +// Object { foo: "baz", x: 42, y: 13 }</pre> + +<p>Note that {{jsxref("Object.assign()")}} triggers <a href="/en-US/docs/Web/JavaScript/Reference/Functions/set">setters</a> whereas the spread operator doesn't.</p> + +<h3 id="Prototype_mutation">Prototype mutation</h3> + +<p>A property definition of the form <code>__proto__: value</code> or <code>"__proto__": value</code> does not create a property with the name <code>__proto__</code>. Instead, if the provided value is an object or <a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/null"><code>null</code></a>, it changes the <code>[[Prototype]]</code> of the created object to that value. (If the value is not an object or null, the object is not changed.)</p> + +<pre class="brush: js">var obj1 = {}; +assert(Object.getPrototypeOf(obj1) === Object.prototype); + +var obj2 = {__proto__: null}; +assert(Object.getPrototypeOf(obj2) === null); + +var protoObj = {}; +var obj3 = {'__proto__': protoObj}; +assert(Object.getPrototypeOf(obj3) === protoObj); + +var obj4 = {__proto__: 'not an object or null'}; +assert(Object.getPrototypeOf(obj4) === Object.prototype); +assert(!obj4.hasOwnProperty('__proto__')); +</pre> + +<p>Only a single prototype mutation is permitted in an object literal: multiple prototype mutations are a syntax error.</p> + +<p>Property definitions that do not use "colon" notation are not prototype mutations: they are property definitions that behave identically to similar definitions using any other name.</p> + +<pre class="brush: js">var __proto__ = 'variable'; + +var obj1 = {__proto__}; +assert(Object.getPrototypeOf(obj1) === Object.prototype); +assert(obj1.hasOwnProperty('__proto__')); +assert(obj1.__proto__ === 'variable'); + +var obj2 = {__proto__() { return 'hello'; }}; +assert(obj2.__proto__() === 'hello'); + +var obj3 = {['__prot' + 'o__']: 17}; +assert(obj3.__proto__ === 17); +</pre> + +<h2 id="Object_literal_notation_vs_JSON">Object literal notation vs JSON</h2> + +<p>Object literal notation與<strong>J</strong>ava<strong>S</strong>cript <strong>O</strong>bject <strong>N</strong>otation (<a href="/en-US/docs/Glossary/JSON">JSON</a>)是不一樣的東西. 儘管它們看起來很相似,但還是有以下的不同:</p> + +<ul> + <li>JSON只允許屬性透過<code>"property": value</code>格式定義. 屬性名稱必須使用雙引號包起來,且不能是速記。</li> + <li>JSON的數值僅能為string, numbers, arrays, <code>true</code>, <code>false</code>, <code>null</code>, 或另一個JSON物件.</li> + <li>A function value (see "Methods" above) can not be assigned to a value in JSON.</li> + <li>Objects like {{jsxref("Date")}} will be a string after {{jsxref("JSON.parse()")}}.</li> + <li>{{jsxref("JSON.parse()")}} will reject computed property names and an error will be thrown.</li> +</ul> + +<h2 id="規範">規範</h2> + +<table class="standard-table"> + <tbody> + <tr> + <th scope="col">Specification</th> + <th scope="col">Status</th> + <th scope="col">Comment</th> + </tr> + <tr> + <td>{{SpecName('ES1')}}</td> + <td>{{Spec2('ES1')}}</td> + <td>initial definition.</td> + </tr> + <tr> + <td>{{SpecName('ES5.1', '#sec-11.1.5', 'Object Initializer')}}</td> + <td>{{Spec2('ES5.1')}}</td> + <td><a href="/en-US/docs/Web/JavaScript/Reference/Functions/get">getter</a> and <a href="/en-US/docs/Web/JavaScript/Reference/Functions/set">setter</a> added.</td> + </tr> + <tr> + <td>{{SpecName('ES2015', '#sec-object-initializer', 'Object Initializer')}}</td> + <td>{{Spec2('ES2015')}}</td> + <td>Shorthand method/property names and computed property names added.</td> + </tr> + <tr> + <td>{{SpecName('ESDraft', '#sec-object-initializer', 'Object Initializer')}}</td> + <td>{{Spec2('ESDraft')}}</td> + <td> </td> + </tr> + <tr> + <td><a href="https://github.com/tc39/proposal-object-rest-spread">Rest/Spread Properties for ECMAScript </a></td> + <td>Draft</td> + <td>Stage 3 draft.</td> + </tr> + </tbody> +</table> + +<h2 id="瀏覽器相容性">瀏覽器相容性</h2> + +<div>{{CompatibilityTable}}</div> + +<div id="compat-desktop"> +<table class="compat-table"> + <tbody> + <tr> + <th>Feature</th> + <th>Chrome</th> + <th>Edge</th> + <th>Firefox (Gecko)</th> + <th>Internet Explorer</th> + <th>Opera</th> + <th>Safari</th> + </tr> + <tr> + <td>Basic support</td> + <td>{{CompatChrome(1.0)}}</td> + <td>{{CompatVersionUnknown}}</td> + <td>{{CompatGeckoDesktop("1.0")}}</td> + <td>1</td> + <td>1</td> + <td>1</td> + </tr> + <tr> + <td>Computed property names</td> + <td>{{CompatVersionUnknown}}</td> + <td>{{CompatVersionUnknown}}</td> + <td>{{CompatGeckoDesktop("34")}}</td> + <td>{{CompatNo}}</td> + <td>34</td> + <td>7.1</td> + </tr> + <tr> + <td>Shorthand property names</td> + <td>{{CompatVersionUnknown}}</td> + <td>{{CompatVersionUnknown}}</td> + <td>{{CompatGeckoDesktop("33")}}</td> + <td>{{CompatNo}}</td> + <td>34</td> + <td>9</td> + </tr> + <tr> + <td>Shorthand method names</td> + <td>{{CompatChrome(42.0)}}</td> + <td>{{CompatVersionUnknown}}</td> + <td>{{CompatGeckoDesktop("34")}}</td> + <td>{{CompatNo}}</td> + <td>34</td> + <td>9</td> + </tr> + <tr> + <td>Spread properties</td> + <td>{{CompatChrome(60)}}</td> + <td>{{CompatNo}}</td> + <td>{{CompatGeckoDesktop("55")}}</td> + <td>{{CompatNo}}</td> + <td>{{CompatNo}}</td> + <td>{{CompatNo}}</td> + </tr> + </tbody> +</table> +</div> + +<div id="compat-mobile"> +<table class="compat-table"> + <tbody> + <tr> + <th>Feature</th> + <th>Android</th> + <th>Android Webview</th> + <th>Edge</th> + <th>Firefox Mobile (Gecko)</th> + <th>IE Mobile</th> + <th>Opera Mobile</th> + <th>Safari Mobile</th> + <th>Chrome for Android</th> + </tr> + <tr> + <td>Basic support</td> + <td>{{CompatVersionUnknown}}</td> + <td>{{CompatVersionUnknown}}</td> + <td>{{CompatVersionUnknown}}</td> + <td>{{CompatGeckoMobile("1.0")}}</td> + <td>1</td> + <td>1</td> + <td>1</td> + <td>{{CompatChrome(1.0)}}</td> + </tr> + <tr> + <td>Computed property names</td> + <td>{{CompatNo}}</td> + <td>{{CompatVersionUnknown}}</td> + <td>{{CompatVersionUnknown}}</td> + <td>{{CompatGeckoMobile("34")}}</td> + <td>{{CompatNo}}</td> + <td>34</td> + <td>7.1</td> + <td>{{CompatNo}}</td> + </tr> + <tr> + <td>Shorthand property names</td> + <td>{{CompatNo}}</td> + <td>{{CompatVersionUnknown}}</td> + <td>{{CompatVersionUnknown}}</td> + <td>{{CompatGeckoMobile("33")}}</td> + <td>{{CompatNo}}</td> + <td>34</td> + <td>9</td> + <td>{{CompatNo}}</td> + </tr> + <tr> + <td>Shorthand method names</td> + <td>{{CompatNo}}</td> + <td>{{CompatChrome(42.0)}}</td> + <td>{{CompatVersionUnknown}}</td> + <td>{{CompatGeckoMobile("34")}}</td> + <td>{{CompatNo}}</td> + <td>34</td> + <td>9</td> + <td>{{CompatChrome(42.0)}}</td> + </tr> + <tr> + <td>Spread properties</td> + <td>{{CompatNo}}</td> + <td>{{CompatNo}}</td> + <td>{{CompatNo}}</td> + <td>{{CompatGeckoMobile("55")}}</td> + <td>{{CompatNo}}</td> + <td>{{CompatNo}}</td> + <td>{{CompatNo}}</td> + <td>{{CompatNo}}</td> + </tr> + </tbody> +</table> +</div> + +<h2 id="參見">參見</h2> + +<ul> + <li><a href="/en-US/docs/Web/JavaScript/Reference/Operators/Property_Accessors">Property accessors</a></li> + <li><code><a href="/en-US/docs/Web/JavaScript/Reference/Functions/get">get</a></code> / <code><a href="/en-US/docs/Web/JavaScript/Reference/Functions/set">set</a></code></li> + <li><a href="/en-US/docs/Web/JavaScript/Reference/Functions/Method_definitions">Method definitions</a></li> + <li><a href="/en-US/docs/Web/JavaScript/Reference/Lexical_grammar">Lexical grammar</a></li> +</ul> diff --git a/files/zh-tw/web/javascript/reference/operators/operator_precedence/index.html b/files/zh-tw/web/javascript/reference/operators/operator_precedence/index.html new file mode 100644 index 0000000000..0395059d09 --- /dev/null +++ b/files/zh-tw/web/javascript/reference/operators/operator_precedence/index.html @@ -0,0 +1,316 @@ +--- +title: 運算子優先序 +slug: Web/JavaScript/Reference/Operators/Operator_Precedence +tags: + - JavaScript + - Operator + - precedence +translation_of: Web/JavaScript/Reference/Operators/Operator_Precedence +--- +<div>{{jsSidebar("Operators")}}</div> + +<p>運算子優先序(Operator precedence)決定了運算子彼此之間被語法解析的方式,優先序較高的運算子會成為優先序較低運算子的運算元(operands)。</p> + +<div>{{EmbedInteractiveExample("pages/js/expressions-operatorprecedence.html")}}</div> + + + +<h2 id="相依性(Associativity)">相依性(Associativity)</h2> + +<p>當優先序相同時,使用相依性決定運算方向。範例如下:</p> + +<pre class="syntaxbox">a OP b OP c +</pre> + +<p>左相依性 (Left-associativity) ,表示處理順序為從左至右 <code>(a OP b) OP c</code>,反之,右相依性(right-associativity) 表示處理順序為從右至左 <code>a OP (b OP c)</code>。賦值運算符 (Assignment operators) 為右相依性,範例如下:</p> + +<pre class="brush: js">a = b = 5; +</pre> + +<p><code>a</code> 和 <code>b</code> 的預期結果為 5,因為賦值運算符 (Assignment operator) 為右相依性,因此從右至左返回值。一開始 <code>b</code> 被設定為 5,接著 <code>a</code> 也被設定為 5。</p> + +<h2 id="表格(Table)">表格(Table)</h2> + +<p>下方表格列出運算子的相依性,從高 (20) 到低 (1)。</p> + +<table class="fullwidth-table"> + <tbody> + <tr> + <th>優先性<br> + Precedence</th> + <th>運算子名稱<br> + Operator type</th> + <th>相依性<br> + Associativity</th> + <th>運算子<br> + Individual operators</th> + </tr> + <tr> + <td>20</td> + <td>{{jsxref("Operators/Grouping", "Grouping")}}</td> + <td>無</td> + <td><code>( … )</code></td> + </tr> + <tr> + <td colspan="1" rowspan="4">19</td> + <td>{{jsxref("Operators/Property_Accessors", "Member Access", "#Dot_notation")}}</td> + <td>從左至右</td> + <td><code>… . …</code></td> + </tr> + <tr> + <td>{{jsxref("Operators/Property_Accessors", "Computed Member Access","#Bracket_notation")}}</td> + <td>從左至右</td> + <td><code>… [ … ]</code></td> + </tr> + <tr> + <td>{{jsxref("Operators/new","new")}} (with argument list)</td> + <td>無</td> + <td><code>new … ( … )</code></td> + </tr> + <tr> + <td><a href="/en-US/docs/Web/JavaScript/Guide/Functions">Function Call</a></td> + <td>從左至右</td> + <td><code>… ( <var>… </var>)</code></td> + </tr> + <tr> + <td rowspan="1">18</td> + <td>{{jsxref("Operators/new","new")}} (without argument list)</td> + <td>從右至左</td> + <td><code>new …</code></td> + </tr> + <tr> + <td rowspan="2">17</td> + <td>{{jsxref("Operators/Arithmetic_Operators","Postfix Increment","#Increment")}}</td> + <td colspan="1" rowspan="2">無</td> + <td><code>… ++</code></td> + </tr> + <tr> + <td>{{jsxref("Operators/Arithmetic_Operators","Postfix Decrement","#Decrement")}}</td> + <td><code>… --</code></td> + </tr> + <tr> + <td colspan="1" rowspan="10">16</td> + <td><a href="/en-US/docs/Web/JavaScript/Reference/Operators/Logical_Operators#Logical_NOT">Logical NOT</a></td> + <td colspan="1" rowspan="10">從右至左</td> + <td><code>! …</code></td> + </tr> + <tr> + <td><a href="/en-US/docs/Web/JavaScript/Reference/Operators/Bitwise_Operators#Bitwise_NOT">Bitwise NOT</a></td> + <td><code>~ …</code></td> + </tr> + <tr> + <td><a href="/en-US/docs/Web/JavaScript/Reference/Operators/Arithmetic_Operators#Unary_plus">Unary Plus</a></td> + <td><code>+ …</code></td> + </tr> + <tr> + <td><a href="/en-US/docs/Web/JavaScript/Reference/Operators/Arithmetic_Operators#Unary_negation">Unary Negation</a></td> + <td><code>- …</code></td> + </tr> + <tr> + <td><a href="/en-US/docs/Web/JavaScript/Reference/Operators/Arithmetic_Operators#Increment">Prefix Increment</a></td> + <td><code>++ …</code></td> + </tr> + <tr> + <td><a href="/en-US/docs/Web/JavaScript/Reference/Operators/Arithmetic_Operators#Decrement">Prefix Decrement</a></td> + <td><code>-- …</code></td> + </tr> + <tr> + <td><a href="/en-US/docs/Web/JavaScript/Reference/Operators/typeof">typeof</a></td> + <td><code>typeof …</code></td> + </tr> + <tr> + <td><a href="/en-US/docs/Web/JavaScript/Reference/Operators/void">void</a></td> + <td><code>void …</code></td> + </tr> + <tr> + <td><a href="/en-US/docs/Web/JavaScript/Reference/Operators/delete">delete</a></td> + <td><code>delete …</code></td> + </tr> + <tr> + <td><a href="/en-US/docs/Web/JavaScript/Reference/Operators/await">await</a></td> + <td><code>await …</code></td> + </tr> + <tr> + <td>15</td> + <td><a href="/en-US/docs/Web/JavaScript/Reference/Operators/Arithmetic_Operators#Exponentiation">Exponentiation</a></td> + <td>從右至左</td> + <td><code>… ** …</code></td> + </tr> + <tr> + <td rowspan="3">14</td> + <td><a href="/en-US/docs/Web/JavaScript/Reference/Operators/Arithmetic_Operators#Multiplication">Multiplication</a></td> + <td colspan="1" rowspan="3">從左至右</td> + <td><code>… * …</code></td> + </tr> + <tr> + <td><a href="/en-US/docs/Web/JavaScript/Reference/Operators/Arithmetic_Operators#Division">Division</a></td> + <td><code>… / …</code></td> + </tr> + <tr> + <td><a href="/en-US/docs/Web/JavaScript/Reference/Operators/Arithmetic_Operators#Remainder">Remainder</a></td> + <td><code>… % …</code></td> + </tr> + <tr> + <td rowspan="2">13</td> + <td><a href="/en-US/docs/Web/JavaScript/Reference/Operators/Arithmetic_Operators#Addition">Addition</a></td> + <td colspan="1" rowspan="2">從左至右</td> + <td><code>… + …</code></td> + </tr> + <tr> + <td><a href="/en-US/docs/Web/JavaScript/Reference/Operators/Arithmetic_Operators#Subtraction">Subtraction</a></td> + <td><code>… - …</code></td> + </tr> + <tr> + <td rowspan="3">12</td> + <td><a href="/en-US/docs/Web/JavaScript/Reference/Operators/Bitwise_Operators">Bitwise Left Shift</a></td> + <td colspan="1" rowspan="3">從左至右</td> + <td><code>… << …</code></td> + </tr> + <tr> + <td><a href="/en-US/docs/Web/JavaScript/Reference/Operators/Bitwise_Operators">Bitwise Right Shift</a></td> + <td><code>… >> …</code></td> + </tr> + <tr> + <td><a href="/en-US/docs/Web/JavaScript/Reference/Operators/Bitwise_Operators">Bitwise Unsigned Right Shift</a></td> + <td><code>… >>> …</code></td> + </tr> + <tr> + <td rowspan="6">11</td> + <td><a href="/en-US/docs/Web/JavaScript/Reference/Operators/Comparison_Operators#Less_than_operator">Less Than</a></td> + <td colspan="1" rowspan="6">從左至右</td> + <td><code>… < …</code></td> + </tr> + <tr> + <td><a href="/en-US/docs/Web/JavaScript/Reference/Operators/Comparison_Operators#Less_than__or_equal_operator">Less Than Or Equal</a></td> + <td><code>… <= …</code></td> + </tr> + <tr> + <td><a href="/en-US/docs/Web/JavaScript/Reference/Operators/Comparison_Operators#Greater_than_operator">Greater Than</a></td> + <td><code>… > …</code></td> + </tr> + <tr> + <td><a href="/en-US/docs/Web/JavaScript/Reference/Operators/Comparison_Operators#Greater_than_or_equal_operator">Greater Than Or Equal</a></td> + <td><code>… >= …</code></td> + </tr> + <tr> + <td><a href="/en-US/docs/Web/JavaScript/Reference/Operators/in">in</a></td> + <td><code>… in …</code></td> + </tr> + <tr> + <td><a href="/en-US/docs/Web/JavaScript/Reference/Operators/instanceof">instanceof</a></td> + <td><code>… instanceof …</code></td> + </tr> + <tr> + <td rowspan="4">10</td> + <td><a href="/en-US/docs/Web/JavaScript/Reference/Operators/Comparison_Operators#Equality">Equality</a></td> + <td colspan="1" rowspan="4">從左至右</td> + <td><code>… == …</code></td> + </tr> + <tr> + <td><a href="/en-US/docs/Web/JavaScript/Reference/Operators/Comparison_Operators#Inequality">Inequality</a></td> + <td><code>… != …</code></td> + </tr> + <tr> + <td><a href="/en-US/docs/Web/JavaScript/Reference/Operators/Comparison_Operators#Identity">Strict Equality</a></td> + <td><code>… === …</code></td> + </tr> + <tr> + <td><a href="/en-US/docs/Web/JavaScript/Reference/Operators/Comparison_Operators#Nonidentity">Strict Inequality</a></td> + <td><code>… !== …</code></td> + </tr> + <tr> + <td>9</td> + <td><a href="/en-US/docs/Web/JavaScript/Reference/Operators/Bitwise_Operators#Bitwise_AND">Bitwise AND</a></td> + <td>從左至右</td> + <td><code>… & …</code></td> + </tr> + <tr> + <td>8</td> + <td><a href="/en-US/docs/Web/JavaScript/Reference/Operators/Bitwise_Operators#Bitwise_XOR">Bitwise XOR</a></td> + <td>從左至右</td> + <td><code>… ^ …</code></td> + </tr> + <tr> + <td>7</td> + <td><a href="/en-US/docs/Web/JavaScript/Reference/Operators/Bitwise_Operators#Bitwise_OR">Bitwise OR</a></td> + <td>從左至右</td> + <td><code>… | …</code></td> + </tr> + <tr> + <td>6</td> + <td><a href="/en-US/docs/Web/JavaScript/Reference/Operators/Logical_Operators#Logical_AND">Logical AND</a></td> + <td>從左至右</td> + <td><code>… && …</code></td> + </tr> + <tr> + <td>5</td> + <td><a href="/en-US/docs/Web/JavaScript/Reference/Operators/Logical_Operators#Logical_OR">Logical OR</a></td> + <td>從左至右</td> + <td><code>… || …</code></td> + </tr> + <tr> + <td>4</td> + <td><a href="/en-US/docs/Web/JavaScript/Reference/Operators/Conditional_Operator">Conditional</a></td> + <td>從右至左</td> + <td><code>… ? … : …</code></td> + </tr> + <tr> + <td rowspan="13">3</td> + <td rowspan="13"><a href="/en-US/docs/Web/JavaScript/Reference/Operators/Assignment_Operators">Assignment</a></td> + <td rowspan="13">從右至左</td> + <td><code>… = …</code></td> + </tr> + <tr> + <td><code>… += …</code></td> + </tr> + <tr> + <td><code>… -= …</code></td> + </tr> + <tr> + <td><code>… **= …</code></td> + </tr> + <tr> + <td><code>… *= …</code></td> + </tr> + <tr> + <td><code>… /= …</code></td> + </tr> + <tr> + <td><code>… %= …</code></td> + </tr> + <tr> + <td><code>… <<= …</code></td> + </tr> + <tr> + <td><code>… >>= …</code></td> + </tr> + <tr> + <td><code>… >>>= …</code></td> + </tr> + <tr> + <td><code>… &= …</code></td> + </tr> + <tr> + <td><code>… ^= …</code></td> + </tr> + <tr> + <td><code>… |= …</code></td> + </tr> + <tr> + <td rowspan="2">2</td> + <td><a href="/en-US/docs/Web/JavaScript/Reference/Operators/yield">yield</a></td> + <td colspan="1" rowspan="2">從右至左</td> + <td><code>yield …</code></td> + </tr> + <tr> + <td><a href="/en-US/docs/Web/JavaScript/Reference/Operators/yield*">yield*</a></td> + <td><code>yield* …</code></td> + </tr> + <tr> + <td>1</td> + <td><a href="/en-US/docs/Web/JavaScript/Reference/Operators/Comma_Operator">Comma / Sequence</a></td> + <td>從左至右</td> + <td><code>… , …</code></td> + </tr> + </tbody> +</table> diff --git a/files/zh-tw/web/javascript/reference/operators/optional_chaining/index.html b/files/zh-tw/web/javascript/reference/operators/optional_chaining/index.html new file mode 100644 index 0000000000..a0b8edeae6 --- /dev/null +++ b/files/zh-tw/web/javascript/reference/operators/optional_chaining/index.html @@ -0,0 +1,195 @@ +--- +title: 可選串連 +slug: Web/JavaScript/Reference/Operators/Optional_chaining +tags: + - JavaScript + - 串連 + - 可選串連 + - 語言功能 + - 運算子 +translation_of: Web/JavaScript/Reference/Operators/Optional_chaining +--- +<div>{{JSSidebar("Operators")}}</div> + +<div></div> + +<p><strong>可選串連</strong>運算子 <strong><code>?.</code></strong> 允許進行深層次的物件值存取,而無需透過明確的物件值串連驗證。<span class="seoSummary"><code>?.</code> 運算子的操作與 <code>.</code> 屬性存取運算子相似,後者會在參照到 <a href="/zh-TW/docs/Glossary/nullish">nullish</a> ({{JSxRef("null")}} or {{JSxRef("undefined")}}) 的值時出現錯誤,而前者可選串連則回傳 <code>undefined</code> 。</span> 當需要存取一個函數,而這函數並不存在時,則會回傳 <code>undefined</code> 。</p> + +<p>當有機會存在參照不存在的時候,可選串連可以提供更簡短的表述式來進行串連性的屬性存取。這有助於在無法保證物件屬性為必要存在的狀況下,進行物件內容的探索。</p> + +<div>{{EmbedInteractiveExample("pages/js/expressions-optionalchainingoperator.html", "taller")}}</div> + +<div></div> + + + +<h2 id="語法">語法</h2> + +<pre class="syntaxbox"><var>obj</var>?.<var>prop</var> +<var>obj</var>?.[<var>expr</var>] +<em>arr</em>?.[<var>index</var>] +<var>func</var>?.(<var>args</var>) +</pre> + +<h2 id="描述">描述</h2> + +<p>當串連物件裡面的參照或方法可能是<code>undefined</code> 或 <code>null</code> 時,可選串連運算子提供簡單的方法去存取這些串連物件下的值。</p> + +<p>舉例來說,當一個物件 <code>obj</code> 是巢狀結構時,在沒有可選串連之下,要去查找一深層的屬性值需要驗證每層間的參照連結:</p> + +<pre class="brush: js">let nestedProp = obj.first && obj.first.second;</pre> + +<p><code>obj.first</code> 的值需要先確定不是 <code>null</code> 值(和並非 <code>undefined</code> ),才能存取 <code>obj.first.second</code> 的值。這才能避免在存取值時,因為直接使用 <code>obj.first.second</code> 而沒有測試 <code>obj.first</code> 之下帶來的錯誤。</p> + +<p>當使用了可選串連運算子(<code>?.</code>),你不再需要明確地進行測測,並能在基於 <code>obj.first</code> 的狀態下直接回傳,忽略存取 <code>obj.first.second</code> 的動作:</p> + +<pre class="brush: js">let nestedProp = obj.first?.second;</pre> + +<p>從只是 <code>.</code> 改用作 <code>?.</code> 運算子,JavaScript 會知道在存取 <code>obj.first.second</code> 之前,需要間接地檢查並確保 <code>obj.first</code> 並不是 <code>null</code> 或 <code>undefined</code> 。當 <code>obj.first</code> 是 <code>null</code> 或 <code>undefined</code> ,運算式會像短路一樣跳過整個串連存取式,而回傳 <code>undefined</code> 。</p> + +<p>這是跟以下是相等同的,但是實際上是不會建立臨時變數:</p> + +<pre class="brush: js">let temp = obj.first; +let nestedProp = ((temp === null || temp === undefined) ? undefined : temp.second); +</pre> + +<h3 id="可選串連呼叫函數">可選串連呼叫函數</h3> + +<p>你可以使用可選串連來嘗試呼叫一個或許沒有存在的方法。這可能有助於,舉例來說,使用一些未能提供服務的 API ,這可能因為過時的應用或是使用者的裝置未能支援某種功能。</p> + +<p>當需要使用的方法並不存在時,透過可選串連去進行呼叫將不會抛出錯誤,取而代之的是回傳 <code>undefined</code> :</p> + +<pre class="brush: js">let result = someInterface.customMethod?.();</pre> + +<div class="blockIndicator note"> +<p><strong>注意:</strong> 假如物件有同樣的屬性名稱,而不是一個方法,使用 <code>?.</code> 將會抛出 {{JSxRef("TypeError")}} 錯誤(<code>x.y</code><code> 不是一個函數</code>.</p> +</div> + +<h4 id="處理回呼函式或事件處理器">處理回呼函式或事件處理器</h4> + +<p>如果你使用回呼函式,或是透過<a href="/zh-TW/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment#Object_destructuring">解構賦值</a>來擷取物件中的方法,你可能會因為這些方法沒有存在,而無法進行呼叫,除非你事先驗證其存在性。所以,你可以利用 <code>?.</code> 來避免這樣的測試:</p> + +<pre class="brush: js">// 在 ES2019 下撰寫 +function doSomething(onContent, onError) { + try { + // ... 對資料進行一些處理 + } + catch (err) { + if (onError) { // 測試 onError 是否真的存在 + onError(err.message); + } + } +} +</pre> + +<pre class="brush: js">// 使用可選串連進行函式呼叫 +function doSomething(onContent, onError) { + try { + // ... 對資料進行一些處理 + } + catch (err) { + onError?.(err.message); // 就算 onError 是 undefined 也不會抛出錯誤 + } +} +</pre> + +<h3 id="可選串連表述式">可選串連表述式</h3> + +<p>你也可以在<a href="/zh-TW/docs/Web/JavaScript/Reference/Operators/Property_Accessors#Bracket_notation">方括號屬性存取</a>表達式中使用可選串連:</p> + +<pre class="brush: js">let nestedProp = obj?.['prop' + 'Name']; +</pre> + +<h3 id="矩陣項目的可選串連">矩陣項目的可選串連</h3> + +<pre class="brush: js">let arrayItem = arr?.[42];</pre> + +<h2 id="範例">範例</h2> + +<h3 id="基本範例">基本範例</h3> + +<p>這個範例會找出 Map 物件中一個鍵為 <code>bar</code> 成員的 <code>name</code> 屬性值,但事實上並沒有相關成員。所以結果為 <code>undefined</code> 。</p> + +<pre class="brush: js">let myMap = new Map(); +myMap.set("foo", {name: "baz", desc: "inga"}); + +let nameBar = myMap.get("bar")?.name;</pre> + +<h3 id="短路式運算">短路式運算</h3> + +<p>當可選串連接上表述式時,如果左邊的運算數值是 <code>null</code> 或 <code>undefined</code> ,表述式則不會被運算。舉例來說:</p> + +<pre class="brush: js">let potentiallyNullObj = null; +let x = 0; +let prop = potentiallyNullObj?.[x++]; + +console.log(x); // 因為 x 沒有遞增,所以為 0 +</pre> + +<h3 id="串接多個可選串連">串接多個可選串連</h3> + +<p>在巢狀結構中可以使用多次的可選串連:</p> + +<pre class="brush: js">let customer = { + name: "Carl", + details: { + age: 82, + location: "Paradise Falls" // 詳細地址 address 並不知道 + } +}; +let customerCity = customer.details?.address?.city; + +// … 同樣地,串接多個可選串連來呼叫函式也是湊效的 +let duration = vacations.trip?.getTime?.(); +</pre> + +<h3 id="使用空值合併運算子">使用空值合併運算子</h3> + +<p>在可選串連後可以使用{{JSxRef("Operators/Nullish_Coalescing_Operator", "空值合併運算子", '', 1)}}來編配預設值,如果無法在屬性串連中取得值:</p> + +<pre class="brush: js">let customer = { + name: "Carl", + details: { age: 82 } +}; +const customerCity = customer?.city ?? "Unknown city"; +console.log(customerCity); // Unknown city</pre> + +<h2 id="規範">規範</h2> + +<table class="standard-table"> + <thead> + <tr> + <th scope="col">規範</th> + <th scope="col">狀態</th> + <th scope="col">註解</th> + </tr> + </thead> + <tbody> + <tr> + <td><a href="https://tc39.es/proposal-optional-chaining/#sec-scope">Proposal for the "optional chaining" operator</a></td> + <td>Stage 4</td> + <td></td> + </tr> + </tbody> +</table> + +<h2 id="瀏覽器相容性">瀏覽器相容性</h2> + +<div> + + +<p>{{Compat("javascript.operators.optional_chaining")}}</p> +</div> + +<h3 id="實施進程">實施進程</h3> + +<p>因為本功能尚未達到跨瀏覽器性穩定,以下表格提供本功能的每天實驗狀態。資料是透過在各瀏覽器 nightly build 或最新版本 JavaScript 引擎中,進行<a href="https://github.com/tc39/test262">Test262</a> (一個 JavaScript 的標準測試包) 中相關測試而生成的。</p> + +<div>{{EmbedTest262ReportResultsTable("optional-chaining")}}</div> + +<h2 id="參見">參見</h2> + +<ul> + <li>{{JSxRef("Operators/Nullish_Coalescing_Operator", "空值合併運算子", '', 1)}}</li> + <li><a href="https://github.com/tc39/proposals">TC39 proposals</a></li> +</ul> diff --git a/files/zh-tw/web/javascript/reference/operators/spread_syntax/index.html b/files/zh-tw/web/javascript/reference/operators/spread_syntax/index.html new file mode 100644 index 0000000000..fe6ea9a383 --- /dev/null +++ b/files/zh-tw/web/javascript/reference/operators/spread_syntax/index.html @@ -0,0 +1,248 @@ +--- +title: Spread syntax (...) +slug: Web/JavaScript/Reference/Operators/Spread_syntax +translation_of: Web/JavaScript/Reference/Operators/Spread_syntax +--- +<div>{{jsSidebar("Operators")}}</div> + +<p><strong>展開運算子</strong>(<code>...</code>) 允許可迭代的陣列或字串展開成0到多個參數(如果是function的話)或是0到多個元素(如果是array或字組的話),或如果是物件的話則展開成0到多個key-value pair。</p> + +<div>{{EmbedInteractiveExample("pages/js/expressions-spreadsyntax.html")}}</div> + +<div class="hidden">The source for this interactive example is stored in a GitHub repository. If you'd like to contribute to the interactive examples project, please clone <a href="https://github.com/mdn/interactive-examples">https://github.com/mdn/interactive-examples</a> and send us a pull request.</div> + +<h2 id="語法">語法</h2> + +<p>用在呼叫函式時:</p> + +<pre class="syntaxbox notranslate"><var>myFunction</var>(...<var>iterableObj</var>); +</pre> + +<p>用在陣列或字串時:</p> + +<pre class="syntaxbox notranslate">[...<var>iterableObj</var>, '4', 'five', 6];</pre> + +<p>用在物件時(new in ECMAScript 2018):</p> + +<pre class="syntaxbox notranslate">let <var>objClone</var> = { ...<var>obj</var> };</pre> + +<h2 id="Rest_syntax_parameters">Rest syntax (parameters)</h2> + +<p>Rest syntax looks exactly like spread syntax. In a way, rest syntax is the opposite of spread syntax. Spread syntax "expands" an array into its elements, while rest syntax collects multiple elements and "condenses" them into a single element. See {{jsxref("Functions/rest_parameters", "rest parameters", "", 1)}}.</p> + +<h2 id="Examples">Examples</h2> + +<h3 id="Spread_in_function_calls">Spread in function calls</h3> + +<h4 id="Replace_apply">Replace apply()</h4> + +<p>It is common to use {{jsxref("Function.prototype.apply()")}} in cases where you want to use the elements of an array as arguments to a function.</p> + +<pre class="brush: js notranslate">function myFunction(x, y, z) { } +const args = [0, 1, 2]; +myFunction.apply(null, args);</pre> + +<p>With spread syntax the above can be written as:</p> + +<pre class="brush: js notranslate">function myFunction(x, y, z) { } +const args = [0, 1, 2]; +myFunction(...args);</pre> + +<p>Any argument in the argument list can use spread syntax, and the spread syntax can be used multiple times.</p> + +<pre class="brush: js notranslate">function myFunction(v, w, x, y, z) { } +const args = [0, 1]; +myFunction(-1, ...args, 2, ...[3]);</pre> + +<h4 id="Apply_for_new_operator">Apply for new operator</h4> + +<p>When calling a constructor with {{jsxref("Operators/new", "new")}} it's not possible to <strong>directly</strong> use an array and <code>apply()</code> (<code>apply()</code> does a <code>[[Call]]</code> and not a <code>[[Construct]]</code>). However, an array can be easily used with <code>new</code> thanks to spread syntax:</p> + +<pre class="brush: js notranslate">const dateFields = [1970, 0, 1]; // 1 Jan 1970 +const d = new Date(...dateFields); +</pre> + +<p>To use <code>new</code> with an array of parameters without spread syntax, you would have to do it <strong>indirectly</strong> through partial application:</p> + +<pre class="brush: js notranslate">function applyAndNew(constructor, args) { + function partial () { + return constructor.apply(this, args); + }; + if (typeof constructor.prototype === "object") { + partial.prototype = Object.create(constructor.prototype); + } + return partial; +} + + +function myConstructor () { + console.log("arguments.length: " + arguments.length); + console.log(arguments); + this.prop1="val1"; + this.prop2="val2"; +}; + +const myArguments = ["hi", "how", "are", "you", "mr", null]; +const myConstructorWithArguments = applyAndNew(myConstructor, myArguments); + +console.log(new myConstructorWithArguments); +// (internal log of myConstructor): arguments.length: 6 +// (internal log of myConstructor): ["hi", "how", "are", "you", "mr", null] +// (log of "new myConstructorWithArguments"): {prop1: "val1", prop2: "val2"}</pre> + +<h3 id="Spread_in_array_literals">Spread in array literals</h3> + +<h4 id="A_more_powerful_array_literal">A more powerful array literal</h4> + +<p>Without spread syntax, to create a new array using an existing array as one part of it, the array literal syntax is no longer sufficient and imperative code must be used instead using a combination of {{jsxref("Array.prototype.push", "push()")}}, {{jsxref("Array.prototype.splice", "splice()")}}, {{jsxref("Array.prototype.concat", "concat()")}}, etc. With spread syntax this becomes much more succinct:</p> + +<pre class="brush: js notranslate">const parts = ['shoulders', 'knees']; +const lyrics = ['head', ...parts, 'and', 'toes']; +// ["head", "shoulders", "knees", "and", "toes"] +</pre> + +<p>Just like spread for argument lists, <code>...</code> can be used anywhere in the array literal, and may be used more than once.</p> + +<h4 id="Copy_an_array">Copy an array</h4> + +<pre class="brush: js notranslate">const arr = [1, 2, 3]; +const arr2 = [...arr]; // like arr.slice() + +arr2.push(4); +// arr2 becomes [1, 2, 3, 4] +// arr remains unaffected +</pre> + +<div class="blockIndicator note"> +<p><strong>Note:</strong> Spread syntax effectively goes one level deep while copying an array. Therefore, it may be unsuitable for copying multidimensional arrays, as the following example shows. (The same is true with {{jsxref("Object.assign()")}} and spread syntax.)</p> + +<pre class="brush: js example-bad notranslate">const a = [[1], [2], [3]]; +const b = [...a]; + +b.shift().shift(); +// 1 + +// Oh no! Now array 'a' is affected as well: +a +// [[], [2], [3]] +</pre> +</div> + +<h4 id="A_better_way_to_concatenate_arrays">A better way to concatenate arrays</h4> + +<p>{{jsxref("Array.prototype.concat()")}} is often used to concatenate an array to the end of an existing array. Without spread syntax, this is done as:</p> + +<pre class="brush: js notranslate">const arr1 = [0, 1, 2]; +const arr2 = [3, 4, 5]; + +// Append all items from arr2 onto arr1 +arr1 = arr1.concat(arr2);</pre> + +<p>With spread syntax this becomes:</p> + +<pre class="brush: js notranslate">let arr1 = [0, 1, 2]; +let arr2 = [3, 4, 5]; + +arr1 = [...arr1, ...arr2]; +// arr1 is now [0, 1, 2, 3, 4, 5] +// Note: Not to use const otherwise, it will give TypeError (invalid assignment) +</pre> + +<p>{{jsxref("Array.prototype.unshift()")}} is often used to insert an array of values at the start of an existing array. Without spread syntax, this is done as:</p> + +<pre class="brush: js notranslate">const arr1 = [0, 1, 2]; +const arr2 = [3, 4, 5]; + +// Prepend all items from arr2 onto arr1 +Array.prototype.unshift.apply(arr1, arr2) + +// arr1 is now [3, 4, 5, 0, 1, 2]</pre> + +<p>With spread syntax, this becomes:</p> + +<pre class="brush: js notranslate">let arr1 = [0, 1, 2]; +let arr2 = [3, 4, 5]; + +arr1 = [...arr2, ...arr1]; +// arr1 is now [3, 4, 5, 0, 1, 2] +</pre> + +<div class="blockIndicator note"> +<p><strong>Note:</strong> Unlike <code>unshift()</code>, this creates a new <code>arr1</code>, and does not modify the original <code>arr1</code> array in-place.</p> +</div> + +<h3 id="Spread_in_object_literals">Spread in object literals</h3> + +<p>The <a href="https://github.com/tc39/proposal-object-rest-spread">Rest/Spread Properties for ECMAScript</a> proposal (ES2018) added spread properties to {{jsxref("Operators/Object_initializer", "object literals", 1)}}. It copies own enumerable properties from a provided object onto a new object.</p> + +<p>Shallow-cloning (excluding prototype) or merging of objects is now possible using a shorter syntax than {{jsxref("Object.assign()")}}.</p> + +<pre class="brush: js notranslate">const obj1 = { foo: 'bar', x: 42 }; +const obj2 = { foo: 'baz', y: 13 }; + +const clonedObj = { ...obj1 }; +// Object { foo: "bar", x: 42 } + +const mergedObj = { ...obj1, ...obj2 }; +// Object { foo: "baz", x: 42, y: 13 }</pre> + +<p>Note that {{jsxref("Object.assign()")}} triggers {{jsxref("Functions/set", "setters")}}, whereas spread syntax doesn't.</p> + +<p>Note that you cannot replace or mimic the {{jsxref("Object.assign()")}} function:</p> + +<pre class="brush: js notranslate">let obj1 = { foo: 'bar', x: 42 }; +let obj2 = { foo: 'baz', y: 13 }; +const merge = ( ...objects ) => ( { ...objects } ); + +let mergedObj1 = merge (obj1, obj2); +// Object { 0: { foo: 'bar', x: 42 }, 1: { foo: 'baz', y: 13 } } + +let mergedObj2 = merge ({}, obj1, obj2); +// Object { 0: {}, 1: { foo: 'bar', x: 42 }, 2: { foo: 'baz', y: 13 } }</pre> + +<p>In the above example, the spread syntax does not work as one might expect: it spreads an <em>array</em> of arguments into the object literal, due to the rest parameter.</p> + +<h3 id="Only_for_iterables">Only for iterables</h3> + +<p>Objects themselves are not iterable, but they become iterable when used in an Array, or with iterating functions such as <code>map()</code>, <code>reduce()</code>, and <code>assign()</code>. When merging 2 objects together with the spread operator, it is assumed another iterating function is used when the merging occurs.</p> + +<p>Spread syntax (other than in the case of spread properties) can be applied only to <a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/iterator">iterable</a> objects:</p> + +<pre class="brush: js notranslate">const obj = {'key1': 'value1'}; +const array = [...obj]; // TypeError: obj is not iterable +</pre> + +<h3 id="Spread_with_many_values">Spread with many values</h3> + +<p>When using spread syntax for function calls, be aware of the possibility of exceeding the JavaScript engine's argument length limit. See {{jsxref("Function.prototype.apply", "apply()")}} for more details.</p> + +<h2 id="Specifications">Specifications</h2> + +<table class="standard-table"> + <thead> + <tr> + <th scope="col">Specification</th> + </tr> + </thead> + <tbody> + <tr> + <td>{{SpecName('ESDraft', '#sec-array-initializer', 'Array initializer')}}</td> + </tr> + <tr> + <td>{{SpecName('ESDraft', '#sec-object-initializer', 'Object initializer')}}</td> + </tr> + </tbody> +</table> + +<h2 id="Browser_compatibility">Browser compatibility</h2> + + + +<p>{{Compat("javascript.operators.spread")}}</p> + +<h2 id="See_also">See also</h2> + +<ul> + <li>{{jsxref("Functions/rest_parameters", "Rest parameters", "", 1)}} (also ‘<code>...</code>’)</li> + <li>{{jsxref("Function.prototype.apply()")}} (also ‘<code>...</code>’)</li> +</ul> diff --git a/files/zh-tw/web/javascript/reference/operators/super/index.html b/files/zh-tw/web/javascript/reference/operators/super/index.html new file mode 100644 index 0000000000..d02c8a0a91 --- /dev/null +++ b/files/zh-tw/web/javascript/reference/operators/super/index.html @@ -0,0 +1,179 @@ +--- +title: super +slug: Web/JavaScript/Reference/Operators/super +translation_of: Web/JavaScript/Reference/Operators/super +--- +<div>{{jsSidebar("Operators")}}</div> + +<p>super 關鍵字被使用於通過函式存取父層</p> + +<p> <code>super.prop</code> 與 <code>super[expr]</code> 表達有效在 <a href="/en-US/docs/Web/JavaScript/Reference/Functions/Method_definitions">method definition</a> 與 <a href="/en-US/docs/Web/JavaScript/Reference/Classes">classes</a> 與 <a href="/en-US/docs/Web/JavaScript/Reference/Operators/Object_initializer">object literals</a>.</p> + +<h2 id="語法">語法</h2> + +<pre class="syntaxbox">super([arguments]); // calls the parent constructor. +super.functionOnParent([arguments]); +</pre> + +<h2 id="描述">描述</h2> + +<p>當使用建構子,<code>super</code> 關鍵字必須出現在<code>this</code> 關鍵字之前使用,<code>super</code> 關鍵字也可以使用在呼叫函式與父對象</p> + +<h2 id="範例">範例</h2> + +<h3 id="在類別中使用_super">在類別中使用 <code>super</code> </h3> + +<p>這個程式碼片段從 <a href="https://github.com/GoogleChrome/samples/blob/gh-pages/classes-es6/index.html">classes sample</a> (<a href="https://googlechrome.github.io/samples/classes-es6/index.html">live demo</a>). 這裏的 <code>super()</code> 被呼叫去避免複製到建構子的 <code>Rectangle</code> 與 <code>Square</code> 的共通部分。</p> + +<pre class="brush: js">class Rectangle { + constructor(height, width) { + this.name = 'Rectangle'; + this.height = height; + this.width = width; + } + sayName() { + console.log('Hi, I am a ', this.name + '.'); + } + get area() { + return this.height * this.width; + } + set area(value) { + this.area = value; + } +} + +class Square extends Rectangle { + constructor(length) { + this.height; // ReferenceError, super needs to be called first! + + // Here, it calls the parent class's constructor with lengths + // provided for the Rectangle's width and height + super(length, length); + + // Note: In derived classes, super() must be called before you + // can use 'this'. Leaving this out will cause a reference error. + this.name = 'Square'; + } +}</pre> + +<h3 id="Super-calling_靜態方法">Super-calling 靜態方法</h3> + +<p>你也可以使用在<a href="/en-US/docs/Web/JavaScript/Reference/Classes/static">靜態</a>方法.</p> + +<pre class="brush: js">class Rectangle { + constructor() {} + static logNbSides() { + return 'I have 4 sides'; + } +} + +class Square extends Rectangle { + constructor() {} + static logDescription() { + return super.logNbSides() + ' which are all equal'; + } +} +Square.logDescription(); // 'I have 4 sides which are all equal' +</pre> + +<h3 id="刪除_super_屬性將拋出錯誤">刪除 super 屬性將拋出錯誤</h3> + +<p>你不能使用 <a href="/en-US/docs/Web/JavaScript/Reference/Operators/delete">delete operator</a> 以及 <code>super.prop</code> 以及 <code>super[expr]</code> 去刪除父層的類別屬性, 不然他會丟出一個錯誤 {{jsxref("ReferenceError")}}.</p> + +<pre class="brush: js">class Base { + constructor() {} + foo() {} +} +class Derived extends Base { + constructor() {} + delete() { + delete super.foo; // this is bad + } +} + +new Derived().delete(); // ReferenceError: invalid delete involving 'super'. </pre> + +<h3 id="super.prop_不能複寫在不能複寫的屬性"><code>super.prop</code> 不能複寫在不能複寫的屬性</h3> + +<p>當定義不可寫屬性,例如 {{jsxref("Object.defineProperty")}}, <code>super</code> 不能複寫這個屬性的值.</p> + +<pre class="brush: js">class X { + constructor() { + Object.defineProperty(this, 'prop', { + configurable: true, + writable: false, + value: 1 + }); + } +} + +class Y extends X { + constructor() { + super(); + } + foo() { + super.prop = 2; // Cannot overwrite the value. + } +} + +var y = new Y(); +y.foo(); // TypeError: "prop" is read-only +console.log(y.prop); // 1 +</pre> + +<h3 id="使用_super.prop_在對象符號">使用 <code>super.prop</code> 在對象符號</h3> + +<p>Super 可以使用在 <a href="/en-US/docs/Web/JavaScript/Reference/Operators/Object_initializer">object initializer / literal</a> 符號. 在這個範例, 有兩個對象定義在一個方法. 在第二個對象裡面, <code>super</code> 呼叫了第一個對象的方法. 這個動作幫助 {{jsxref("Object.setPrototypeOf()")}} 讓我們可以設定原型 <code>obj2</code> to <code>obj1</code>, 所以 <code>super</code> 可以發現 <code>method1</code> 在 <code>obj1</code>裡被找到.</p> + +<pre class="brush: js">var obj1 = { + method1() { + console.log('method 1'); + } +} + +var obj2 = { + method2() { + super.method1(); + } +} + +Object.setPrototypeOf(obj2, obj1); +obj2.method2(); // logs "method 1" +</pre> + +<h2 id="規格">規格</h2> + +<table class="standard-table"> + <thead> + <tr> + <th scope="col">Specification</th> + <th scope="col">Status</th> + <th scope="col">Comment</th> + </tr> + </thead> + <tbody> + <tr> + <td>{{SpecName('ESDraft', '#sec-super-keyword', 'super')}}</td> + <td>{{Spec2('ESDraft')}}</td> + <td></td> + </tr> + <tr> + <td>{{SpecName('ES2015', '#sec-super-keyword', 'super')}}</td> + <td>{{Spec2('ES2015')}}</td> + <td>Initial definition.</td> + </tr> + </tbody> +</table> + +<h2 id="Browser_compatibility">Browser compatibility</h2> + + + +<p>{{Compat("javascript.operators.super")}}</p> + +<h2 id="參考">參考</h2> + +<ul> + <li><a href="/en-US/docs/Web/JavaScript/Reference/Classes">Classes</a></li> + <li><a href="https://medium.com/beginners-guide-to-mobile-web-development/super-and-extends-in-javascript-es6-understanding-the-tough-parts-6120372d3420">Anurag Majumdar - Super & Extends in JavaScript</a></li> +</ul> diff --git a/files/zh-tw/web/javascript/reference/operators/this/index.html b/files/zh-tw/web/javascript/reference/operators/this/index.html new file mode 100644 index 0000000000..e26b592244 --- /dev/null +++ b/files/zh-tw/web/javascript/reference/operators/this/index.html @@ -0,0 +1,385 @@ +--- +title: this +slug: Web/JavaScript/Reference/Operators/this +tags: + - JavaScript + - this +translation_of: Web/JavaScript/Reference/Operators/this +--- +<div>{{jsSidebar("Operators")}}</div> + +<p>JavaScript <strong>函式內的 <code>this</code> 關鍵字</strong>表現,和其他語言相比略有差異。在<a href="/zh-TW/docs/Web/JavaScript/Reference/Functions_and_function_scope/Strict_mode">嚴格模式</a>與非嚴格模式下也有所不同。</p> + +<p>通常,<code>this</code> 值由被呼叫的函式來決定。它不能在執行期間被指派,每次函式呼叫調用的值也可能不同。ES5 引入了 <code><a href="/zh-TW/docs/Web/JavaScript/Reference/Global_Objects/Function/bind">bind</a></code> 方法去<a href="#The_bind_method">設置函式的 <code>this</code> 值,而不管它怎麼被呼叫。</a>ECMAScript 2015 也導入了定義 <code>this</code> 詞法範圍的<a href="../Functions/Arrow_functions">箭頭函式</a>(它的 <code>this</code> 值會維持在詞法作用域)。</p> + +<div>{{EmbedInteractiveExample("pages/js/expressions-this.html")}}</div> + +<h2 id="語法">語法</h2> + +<pre class="syntaxbox">this</pre> + +<h2 id="全域環境下">全域環境下</h2> + +<p><code>this</code> 值在所有函式以外的全域執行環境下,會被當作全域物件,無論是否處於嚴格模式。</p> + +<pre class="brush:js">console.log(this.document === document); // true + +// 在網路瀏覽器中,window 物件也是全域物件。 +console.log(this === window); // true + +this.a = 37; +console.log(window.a); // 37 + +this.b = "MDN"; +console.log(window.b) // "MDN" +console.log(b) // "MDN" +</pre> + +<h2 id="函式環境下">函式環境下</h2> + +<p>在函式內的 <code>this</code> 值取決於該函式如何被呼叫。</p> + +<h3 id="簡易呼叫">簡易呼叫</h3> + +<p>因為以下程式碼並不處於<a href="/zh-TW/docs/Web/JavaScript/Reference/Strict_mode">嚴謹模式</a>下、而 <code>this</code> 值也沒被呼叫(call)設定,<code>this</code> 會變成全域物件,在瀏覽器之下則會變成 <code>window</code>。</p> + +<pre class="brush:js">function f1(){ + return this; +} + +//在瀏覽器中: +f1() === window; // true + +//Node中: +f1() === global; // true +</pre> + +<p>然而,在嚴格模式下,<code>this</code> 值會在進入執行環境時建立並維持該狀態。因此,下例的 <code>this</code> 預設值是 <code>undefined</code>:</p> + +<pre class="brush:js">function f2(){ + "use strict"; // 嚴格模式 + return this; +} + +f2() === undefined; //true</pre> + +<p>所以在嚴格模式下,如果 <code>this</code> 沒有定義到執行環境內,其預設值就會是 <code>undefined</code>。</p> + +<div class="note"> +<p>在第二個例子裡面,<code>this</code> 應為 <a href="/zh-TW/docs/Web/JavaScript/Reference/Global_Objects/undefined"><code>undefined</code></a>,因為 <code>f2</code> 是直接被呼叫,而不是在其為某個物件的方法或屬性的情況下(例如 <code>window.f2()</code>)被直接呼叫。某些瀏覽器首次支援<a href="/zh-TW/docs/Web/JavaScript/Reference/Functions_and_function_scope/Strict_mode" title="Strict mode">嚴格模式</a>時沒導入這個特徵,它們會因此錯誤的回傳 <code>window</code> 物件。</p> +</div> + +<p>要從某個語境訪問另一個 <code>this</code> 語境的值,請使用 <a href="/zh-TW/docs/Web/JavaScript/Reference/Global_Objects/Function/call">call</a> 或 <a href="/zh-TW/docs/Web/JavaScript/Reference/Global_Objects/Function/apply">apply</a>:</p> + +<pre dir="rtl">// 物件可以被當作call或apply的第一個參數,而this會綁定該物件 +var obj = {a: 'Custom'}; + +// 此屬性a為全域物件 +var a = 'Global'; + +function whatsThis(arg) { + return this.a; // this 值取決於此函數如何被呼叫 +} + +whatsThis(); // 'Global' +whatsThis.call(obj); // 'Custom' +whatsThis.apply(obj); // 'Custom' +</pre> + +<p>當函式內部調用 <code>this</code> 關鍵字時,其值會和所有繼承自 <code>Function.prototype</code> 並使用 <code><a href="/zh-TW/docs/Web/JavaScript/Reference/Global_Objects/Function/call">call</a></code> 或 <code><a href="/zh-TW/docs/Web/JavaScript/Reference/Global_Objects/Function/apply">apply</a></code> 方法呼叫的特定物件綁定。</p> + +<pre>function add(c, d) { + return this.a + this.b + c + d; +} + +var o = {a: 1, b: 3}; + +// 第一個參數(parameter)是調用了 this 的物件, +// 後續參數(parameters)會作為函式呼叫內的參數(arguments)而通過 +add.call(o, 5, 7); // 16 + +// 第一個參數(parameter)是調用了 this 的物件, +// 第二個參數的陣列作為函式呼叫內的參數(arguments)之構件 +add.apply(o, [10, 20]); // 34</pre> + +<p>使用 <code>call</code> 和 <code>apply</code> 時,如果被輸入作為 <code>this</code> 的值不是物件,JavaScript 內建的 <code>ToObject</code> 運算符會試著把被輸入的值轉變為物件。如果被輸入的值是一個原始型別,例如 <code>7</code>或是 <code>'foo'</code>,它們會自動被相關的建構方法轉變為物件。因此,原始數值<code>7</code>會轉變成類似用<code>new Number(7)</code>產生的物件,而字串<code>'foo'</code>會轉變成類似用<code>new String('foo')</code>產生的物件。</p> + +<pre class="brush:js">function bar() { + console.log(Object.prototype.toString.call(this)); +} + +bar.call(7); // [object Number] +bar.call('foo'); // [Object String] +</pre> + +<h3 id="bind_方法"><code>bind</code> 方法</h3> + +<p>ECMAScript 5 導入了 <code><a href="/zh-TW/docs/Web/JavaScript/Reference/Global_Objects/Function/bind">Function.prototype.bind</a></code>。呼叫 <code>f.bind(someObject)</code> 會建立和 <code>f</code> 的主體與作用域相同之新函式;但無論函數怎麼被調用,原始函數的 <code>this</code> 在新函數將永遠與 <code>bind</code> 的第一個參數綁定起來。</p> + +<pre><code>function f() { + return this.a; +} + +var g = f.bind({a: 'azerty'}); +console.log(g()); // azerty + +var h = g.bind({a: 'yoo'}); // bind 只能使用一次! +console.log(h()); // azerty + +var o = {a: 37, f: f, g: g, h: h}; +console.log(o.f(), o.g(), o.h()); // 37, azerty, azerty</code> +</pre> + +<h3 id="箭頭函式">箭頭函式</h3> + +<p>在<a href="/zh-TW/docs/Web/JavaScript/Reference/Functions/Arrow_functions">箭頭函式</a>下,<code>this</code> 值保留了其在詞法作用域 的 <code>this</code> 值。在全域程式碼內,則設為全域物件:</p> + +<pre class="brush: js">var globalObject = this; +var foo = (() => this); +console.log(foo() === globalObject); // true</pre> + +<div class="note"> +<p>註:如果這參數被傳遞給箭頭函式的 call, bind, apply 調用,該參數會被忽略。你仍然可以將參數預先調用到call,但第一個參數(thisArg)必須設置為空。</p> +</div> + +<pre class="brush: js">// 作為物件的方法呼叫 +var obj = {foo: foo}; +console.log(obj.foo() === globalObject); // true + +// 使用呼叫以嘗試設置 this +console.log(foo.call(obj) === globalObject); // true + +// 使用 bind 以嘗試設置 this +foo = foo.bind(obj); +console.log(foo() === globalObject); // true</pre> + +<p>無論以上哪種,<code>foo</code> 的 <code>this</code> 在建立的時候,都會設為原本的樣子(以上面的例子來說,就是全域物件)。這同樣適用於在其他函式內創建的箭頭函式:它們的 <code>this</code> 是設置為外部執行上下文。</p> + +<pre class="brush: js">// 建立一個物件,其方法 bar 含有回傳自己的 this 函式。回傳函式作為箭頭函數而建立, +// 因此該函式的 this 將永遠與外圍函式(enclosing function)的 this 綁定。 +// bar 的值可在呼叫內設立,which in turn sets the value of the returned function. +var obj = { bar : function() { + var x = (() => this); + return x; + } + }; + +// 將 bar 作為物件的方法呼叫,把它的 this 設為物件 +// 指派 fn 作為回傳函數的參照(reference) +var fn = obj.bar(); + +// 在不設置 this 情況下呼叫的 fn,通常默認為全域物件,在嚴格模式下則是 undefined +console.log(fn() === obj); // true</pre> + +<p>以上面的程式碼為例,稱作匿名函數(anonymous function)A 的函數被指定為 <code>obj.bar</code>,它回傳的函數(稱作匿名函數 B)作為箭頭函數而建立。因而,函數 B 的 <code>this</code> 在呼叫時,將永遠設為 <code>obj.bar</code> (函數 A)的 <code>this</code>。呼叫被回傳的函數(函數 B)時,它的 <code>this</code> 將一直是原本的樣子。</p> + +<p>再以上面的程式碼為例,函數 B 的 <code>this</code> 被設為函數 A 的 <code>this</code>,而它屬於物件,所以它依然會設為 <code>obj</code>,就算在 <code>this</code> 設為 <code>undefined</code> 或全域物件的呼叫方式下(或在全域執行環境下,上例的任何方法)</p> + +<h3 id="作為物件方法">作為物件方法</h3> + +<p>如果一個函式是以物件的方法呼叫,它的 <code>this</code> 會設為該呼叫函式的物件。</p> + +<p>以下面的程式碼為例,呼叫 <code>o.f()</code> 的時候,函式內的 <code>this</code> 會和 <code>o</code> 物件綁定。</p> + +<pre class="brush:js">var o = { + prop: 37, + f: function() { + return this.prop; + } +}; + +console.log(o.f()); // logs 37 +</pre> + +<p>請注意這個行為,不會受函式如何或何處定義所影響。以上面為例,在我們定義 <code>o</code> 時,也定義了行內函式 <code>f</code> 作為構件(member)。不過,我們也能先定義函式,接著讓它附屬到 <code>o.f</code>。這麼做會得出相同的效果:</p> + +<pre class="brush:js">var o = {prop: 37}; + +function independent() { + return this.prop; +} + +o.f = independent; + +console.log(o.f()); // 37 +</pre> + +<p>這表明了 <code>this</code> 只和 <code>f</code> 作為 <code>o</code> 的構件呼叫有所關聯。</p> + +<p>同樣的,<code>this</code> 綁定只會受最直接的構件引用(most immediate member reference)所影響。在下面的例子,我們將物件 <code>o.b</code> 的方法 <code>g</code> 作為函式呼叫。在執行的期間,函式內的 <code>this</code> 會參照 <code>o.b</code>。物件是否為 <code>o</code> 的構件無關緊要,最直接的引用才是最緊要的。</p> + +<pre class="brush:js">o.b = {g: independent, prop: 42}; +console.log(o.b.g()); // logs 42 +</pre> + +<h4 id="物件原型鏈上的_this">物件原型鏈上的 <code>this</code></h4> + +<p>相同概念也能套用定義物件原型鏈的方法。如果方法放在物件的原型鏈上,<code>this</code> 會指向方法所呼叫的物件,如同該方法在物件上的樣子。</p> + +<pre class="brush:js">var o = {f:function(){ return this.a + this.b; }}; +var p = Object.create(o); +p.a = 1; +p.b = 4; + +console.log(p.f()); // 5 +</pre> + +<p>在這個示例中,分配給變數<code>p</code> 的物件沒有自己的 <code>f</code> 屬性, 它(p)繼承了它(o)的原型。但是查找 <code>f</code> 最終在 <code>o</code>上找到它的成員名為 f 並不重要。查找開始作為 <code>p.f</code>的引用,所以 <code>this</code> 在函式內部物件的值被當作是<code>p</code>的引用。也就是說,<code>f</code> 作為 <code>p</code>的調用方法以來, 它的 <code>this</code> 指的就是 <code>p</code>. 這是一個非常有趣的JavaScript's 原型繼承特性。</p> + +<h4 id="帶著_getter_或_setter_的_this">帶著 getter 或 setter 的 <code>this</code></h4> + +<p>當函式從 getter 或 setter被調用的時候,同樣的概念也成立。用作 getter 或setter 的函式將自己的 <code>this</code> 綁定到從中設置或獲取的物件上。</p> + +<pre class="brush:js">function sum(){ + return this.a + this.b + this.c; +} + +var o = { + a: 1, + b: 2, + c: 3, + get average(){ + return (this.a + this.b + this.c) / 3; + } +}; + +Object.defineProperty(o, 'sum', { + get: sum, enumerable:true, configurable:true}); + +console.log(o.average, o.sum); // logs 2, 6 +</pre> + +<h3 id="作為建構子">作為建構子</h3> + +<p>若函式以建構子的身份呼叫(使用 <code><a href="/zh-TW/docs/Web/JavaScript/Reference/Operators/new">new</a></code> 關鍵字) <code>this</code> 會和被建構的新物件綁定。</p> + +<div class="note"> +<p>建構子預設透過 <code>this</code> 回傳該物件的參照,但它其實能回傳其他物件。如果回傳值不是物件的話,就會回傳 <code>this</code> 這個物件。</p> +</div> + +<pre class="brush:js">/* + * 建構子會如此做動: + * + * function MyConstructor(){ + * // 實際的函式主體碼在這裡 + * // 在|this| 上創建屬性 + * // 希望通過分配給他們,如: + * this.fum = "nom"; + * // et cetera... + * + * // 如果函式有返回狀態它將返回一個物件 + * // 那個物件將是新表達式的結果。 + * // 換句話來說,表達式的結果是現在綁定 |this| 的物件 + * // (例如,最常見的常見情況). + * } + */ + +function C(){ + this.a = 37; +} + +var o = new C(); +console.log(o.a); // logs 37 + + +function C2(){ + this.a = 37; + return {a:38}; +} + +o = new C2(); +console.log(o.a); // logs 38 +</pre> + +<p>在上例的 <code>C2</code>,由於物件在建構的時候被呼叫,新的物件 <code>this</code> was bound to simply gets discarded。這也實質上令 <code>this.a = 37;</code> 宣告死亡:不是真的死亡(因為已經執行了),但它在毫無 outside effects 的情況下遭到消滅。</p> + +<h3 id="作為_DOM_事件處理器">作為 DOM 事件處理器</h3> + +<p>當一個函式用作事件處理器的話,<code>this</code> 值會設在觸發事件的元素(某些瀏覽器如果不用 <code>addEventListener</code> 方法的話,在動態添加監聽器時,就不會遵循這個常規)</p> + +<pre class="brush:js">// 當監聽器被調用,相關元素變為藍色 +function bluify(e){ + // 永遠是真 + console.log(this === e.currentTarget); + // 當當前目標和目標為相同物件為真 + console.log(this === e.target); + this.style.backgroundColor = '#A5D9F3'; +} + +// 取得文件內所有的元素 +var elements = document.getElementsByTagName('*'); + +// Add bluify as a click listener so when the +// element is clicked on, it turns blue +for(var i=0 ; i<elements.length ; i++){ + elements[i].addEventListener('click', bluify, false); +}</pre> + +<h3 id="作為行內事件處理器">作為行內事件處理器</h3> + +<p>當程式碼從行內的<a href="/zh-TW/docs/Web/Guide/Events/Event_handlers"> on 事件處理器</a>呼叫的話,<code>this</code> 就會設在監聽器所置的 DOM 元素:</p> + +<pre class="brush:js"><button onclick="alert(this.tagName.toLowerCase());"> + Show this +</button> +</pre> + +<p>上方的 alert 會秀出 <code>button</code>。但請注意只有外層程式碼的 <code>this</code> 要這樣設定:</p> + +<pre class="brush:js"><button onclick="alert((function(){return this})());"> + Show inner this +</button> +</pre> + +<p>在這裡,內部函式的並沒有設立 <code>this</code>,所以它會回傳全域/window 物件(例如在非嚴格模式下,呼叫函數沒設定 <code>this</code> 的預設物件)</p> + +<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('ESDraft', '#sec-this-keyword', 'The this keyword')}}</td> + <td>{{Spec2('ESDraft')}}</td> + <td> </td> + </tr> + <tr> + <td>{{SpecName('ES6', '#sec-this-keyword', 'The this keyword')}}</td> + <td>{{Spec2('ES6')}}</td> + <td> </td> + </tr> + <tr> + <td>{{SpecName('ES5.1', '#sec-11.1.1', 'The this keyword')}}</td> + <td>{{Spec2('ES5.1')}}</td> + <td> </td> + </tr> + <tr> + <td>{{SpecName('ES3', '#sec-11.1.1', 'The this keyword')}}</td> + <td>{{Spec2('ES3')}}</td> + <td> </td> + </tr> + <tr> + <td>{{SpecName('ES1', '#sec-11.1.1', 'The this keyword')}}</td> + <td>{{Spec2('ES1')}}</td> + <td>初始定義。在 JavaScript 1.0 導入。</td> + </tr> + </tbody> +</table> + +<h2 id="瀏覽器相容性">瀏覽器相容性</h2> + +<div class="hidden">此頁面上的兼容性數據生成自結構化數據。如果你想為數據做出貢獻,請產看<a href="https://github.com/mdn/browser-compat-data">https://github.com/mdn/browser-compat-data</a> 並且向我們發送拉取請求。</div> + +<p>{{Compat("javascript.operators.this")}}</p> + +<h2 id="參見">參見</h2> + +<ul> + <li><a href="/zh-TW/docs/Web/JavaScript/Reference/Functions_and_function_scope/Strict_mode">嚴格模式</a></li> + <li><a href="http://bjorn.tipling.com/all-this">All this</a>,一篇關於 <code>this</code> 上下文不同的相關文章</li> + <li><a href="http://rainsoft.io/gentle-explanation-of-this-in-javascript/">親和地解釋 JavaScript 的「this」關鍵字</a></li> +</ul> diff --git a/files/zh-tw/web/javascript/reference/operators/typeof/index.html b/files/zh-tw/web/javascript/reference/operators/typeof/index.html new file mode 100644 index 0000000000..d1939e5d4f --- /dev/null +++ b/files/zh-tw/web/javascript/reference/operators/typeof/index.html @@ -0,0 +1,177 @@ +--- +title: typeof +slug: Web/JavaScript/Reference/Operators/typeof +tags: + - 運算子 +translation_of: Web/JavaScript/Reference/Operators/typeof +--- +<p>{{jsSidebar("Operators")}}</p> + +<h2 id="摘要">摘要</h2> + +<p style="line-height: 22px;"><span style="line-height: 1.572;">typeof 運算子會傳回一個字串值, 指出未經運算 (unevaluated) 的運算元所代表的型別。</span></p> + +<table class="standard-table" style="line-height: 22px;"> + <thead> + <tr> + <th colspan="2" scope="col">運算子</th> + </tr> + </thead> + <tbody> + <tr> + <td>實作於:</td> + <td>JavaScript 1.1</td> + </tr> + <tr> + <td>ECMA 版本:</td> + <td>ECMA-262 (以及 ECMA-357 for E4X objects)</td> + </tr> + </tbody> +</table> + +<h2 id="語法">語法</h2> + +<p style="line-height: 22px;"><code style="font-size: 14px;">typeof</code> 之後面跟著它的唯一運算元:</p> + +<pre style="font-size: 14px;"><code style="font-size: 14px;">typeof <code style="font-size: 14px;"><em>operand</em></code></code></pre> + +<h2 id="Parameters" name="Parameters" style="margin: 0px 0px 0.8em; padding: 0px;">參數</h2> + +<div><code style="line-height: inherit; font-size: 14px;"><em>operand</em></code><span style="line-height: inherit;"> 表示式代表傳入的物件或原始型別。</span></div> + +<h2 id="Description" name="Description">說明</h2> + +<p>下表摘要列出了 <code>typeof 可能的傳回值</code>:</p> + +<table class="standard-table"> + <thead> + <tr> + <th scope="col">型別</th> + <th scope="col">傳回</th> + </tr> + </thead> + <tbody> + <tr> + <td>Undefined</td> + <td><code>"undefined"</code></td> + </tr> + <tr> + <td>Null</td> + <td><code>"object"</code></td> + </tr> + <tr> + <td>Boolean</td> + <td><code>"boolean"</code></td> + </tr> + <tr> + <td>Number</td> + <td><code>"number"</code></td> + </tr> + <tr> + <td>String</td> + <td><code>"string"</code></td> + </tr> + <tr> + <td>主機端物件 (由 JS 執行環境提供)</td> + <td><em>視實作方式而異</em></td> + </tr> + <tr> + <td>Function 物件 (實作 ECMA-262 所定義的 [[Call]])</td> + <td><code>"function"</code></td> + </tr> + <tr> + <td>E4X XML 物件</td> + <td>"xml"</td> + </tr> + <tr> + <td>E4X XMLList 物件</td> + <td>"xml"</td> + </tr> + <tr> + <td>所有其它物件</td> + <td><code>"object"</code></td> + </tr> + </tbody> +</table> + +<h2 id="範例">範例</h2> + +<h3 id="一般情況">一般情況</h3> + +<pre class="brush:js">// Numbers +typeof 37 === 'number'; +typeof 3.14 === 'number'; +typeof Math.LN2 === 'number'; +typeof Infinity === 'number'; +typeof NaN === 'number'; // 雖然是 "Not-A-Number" +typeof Number(1) === 'number'; // 但是不要使用這種方式! + +// Strings +typeof "" === 'string'; +typeof "bla" === 'string'; +typeof (typeof 1) === 'string'; // typeof 一律會傳回一個字串 +typeof String("abc") === 'string'; // 但是不要使用這種方式! + +// Booleans +typeof true === 'boolean'; +typeof false === 'boolean'; +typeof Boolean(true) === 'boolean'; // 但是不要使用這種方式! + +// Undefined +typeof undefined === 'undefined'; +typeof blabla === 'undefined'; // 一個 undefined 變數 + +// Objects +typeof {a:1} === 'object'; +typeof [1, 2, 4] === 'object'; // 請使用 Array.isArray 或者 Object.prototype.toString.call 以區分正規運算式和陣列 +typeof new Date() === 'object'; + +typeof new Boolean(true) === 'object'; // 這樣會令人混淆。不要這樣用! +typeof new Number(1) === 'object'; // 這樣會令人混淆。不要這樣用! +typeof new String("abc") === 'object'; // 這樣會令人混淆。不要這樣用! + +// Functions +typeof function(){} === 'function'; +typeof Math.sin === 'function'; +</pre> + +<h3 id="null"><code>null</code></h3> + +<pre class="brush:js">typeof null === 'object'; // 自從有 JavaScript 開始就是這樣了 +</pre> + +<p>自從 JavaScript 一開始出現, JavaScript 的值就總以型別標簽跟著一個值的方式表示。物件的型別標簽是 0. 而 <code>null</code> 這個值是使用 NULL 指標 (在大部份平台上是 0x00) 來表示. 因此, null 看起來像是一個以 0 為型別標簽的值, 並使得 <code>typeof</code> 傳回不甚正確的結果. (<a href="http://www.2ality.com/2013/10/typeof-null.html">參考來源</a>)</p> + +<p>這個問題已計畫<a class="external" href="http://wiki.ecmascript.org/doku.php?id=harmony:typeof_null">在下一版 ECMAScript 予以修正</a> (會以 opt-in 方式提供). 屆時它將會做出如 <code>typeof null === 'null'</code> 的正確回傳結果。</p> + +<div class="note"> +<p>註: 此修正計畫已被拒絕</p> +</div> + +<h3 id="正規表示式_(Regular_expressions)">正規表示式 (Regular expressions)</h3> + +<p>可呼叫的正規表示式在某些瀏覽器上面必須借助非正式插件 (need reference to say which).</p> + +<pre class="brush:js">typeof /s/ === 'function'; // Chrome 1-12 ... // 不符合 ECMAScript 5.1 (譯註: 在新版 Chrome 已修正為 'object') +typeof /s/ === 'object'; // Firefox 5+ ... // 符合 ECMAScript 5.1 +</pre> + +<h3 id="其它怪異輸入_(quirks)">其它怪異輸入 (quirks)</h3> + +<h4 id="舊版_Internet_Explorer_請留意_alert_函數">舊版 Internet Explorer 請留意 alert 函數</h4> + +<p>在 IE 6, 7 和 8, <code>typeof alert === 'object'</code></p> + +<div class="note"> +<p>註: 這並不怪異。這是實情。在許多較舊的 IE 中, 主機端物件的確是物件, 而非函數</p> +</div> + +<h2 id="規格">規格</h2> + +<p><a class="external" href="http://ecma-international.org/ecma-262/5.1/#sec-11.4.3">ECMA-262 section 11.4.3</a></p> + +<h2 id="See_also" name="See_also">參照</h2> + +<ul> + <li><a href="/en-US/docs/JavaScript/Reference/Operators/instanceof" title="/en-US/docs/JavaScript/Reference/Operators/instanceof">instanceof</a></li> +</ul> |