aboutsummaryrefslogtreecommitdiff
path: root/files/zh-tw/web/javascript/reference/global_objects/isnan/index.html
blob: 6f055cb8fa48d3ab978f58c0e2959bbfd3347a50 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
---
title: isNaN()
slug: Web/JavaScript/Reference/Global_Objects/isNaN
translation_of: Web/JavaScript/Reference/Global_Objects/isNaN
---
<div>{{jsSidebar("Objects")}}</div>

<p><code><strong>isNaN()</strong></code> 函式會判斷某個數值是不是 {{jsxref("NaN")}}。注意:在 <code>isNaN</code> 函式裡面,有個<a href="#描述">有趣的</a>強制性規則。你可能會想改用在 ECMAScript 2015 導入的 {{jsxref("Number.isNaN()")}}</p>

<div>{{EmbedInteractiveExample("pages/js/globalprops-isnan.html")}}</div>

<h2 id="語法">語法</h2>

<pre class="syntaxbox"><code>isNaN(<em>value</em>)</code></pre>

<h3 id="參數">參數</h3>

<dl>
 <dt><code>value</code></dt>
 <dd>要測試的數值。</dd>
</dl>

<h3 id="回傳值">回傳值</h3>

<p>如果給定值是 {{jsxref("NaN")}} 就回傳 <strong><code>true</code></strong>、否則就回傳 <strong><code>false</code></strong></p>

<h2 id="描述">描述</h2>

<h3 id="為什麼要用_isNaN_函式">為什麼要用 <code>isNaN</code> 函式</h3>

<p>與其他 JavaScript 的值不同,你不可能靠等號運算符(== 與 ===)來判斷某個值是不是 {{jsxref("NaN")}},因為連 <code>NaN == NaN</code><code>NaN === NaN</code> 的結果都是 <code>false</code>。因此,<code>isNaN</code> 函式是必要的。</p>

<h3 id="NaN_值的來源"><code>NaN</code> 值的來源</h3>

<p><code>NaN</code> 會在算術運算(arithmetic operations)出現 <em>undefined</em> 或是 <em>unrepresentable</em> 值的結果時產生。這些值不一定是溢出條件。<code>NaN</code> 亦為試圖給毫無可用數字的原始值、予以強制運算之結果。</p>

<p>例如,零除以零的結果會是 <code>NaN</code>——不過把其他數字除以零則不是 <code>NaN</code></p>

<h3 id="令人困惑的特殊狀況行為">令人困惑的特殊狀況行為</h3>

<p>從最早的 <code>isNaN</code> 函式版本規範始,其針對非數值之行為,不斷教人困惑至極。當 <code>isNaN</code> 函式的參數並非<a href="http://es5.github.com/#x8.5" title="http://es5.github.com/#x8.5">數字</a>型別時,此值會先強制轉換到數字。該值接著會測定此值是否為 {{jsxref("NaN")}}。因此,當被強制轉換的非數字,給出了有效的非 NaN 值(經典案例為空的字串與布林原始值:它們在強制轉換時,會給予數字結果 0 或 1)時,會回傳不如預期的「false」值:以空的字串為例,它很明顯地「非數字」。這段教人糾結的點,乃出於「非數字」術語的「數字」一詞、由 IEEE-754 浮點值定義之事實而來。這個函式要解釋為「當這個值,被強制轉換為數值時,它還是 IEEE-754 的『非數字』值嗎?」的答案。</p>

<p>最新的 ECMAScript(ES2015)版本導入了 {{jsxref("Number.isNaN()")}} 函式。儘管 <code>Number.isNaN</code><code>NaN</code> 依舊維持了數字上的意義、而不是簡單的「非數字」,<code>Number.isNaN(x)</code> 在偵測 <code>x</code><code>NaN</code> 與否時比較可靠。另外,如果在缺少 <code>Number.isNaN</code> 的情況下,通過表達式<code>(x != x)</code> 來檢測變量<code>x</code>是否是NaN會更加的可靠。</p>

<p>一個 <code>isNaN</code> 的 polyfill 可以理解為(這個 polyfill 利用了 <code>NaN</code> 自身永不等於自身這一特性):</p>

<pre class="brush: js">var isNaN = function(value) {
    var n = Number(value);
    return n !== n;
};</pre>

<h2 id="範例">範例</h2>

<pre class="brush: js">isNaN(NaN);       // true
isNaN(undefined); // true
isNaN({});        // true

isNaN(true);      // false
isNaN(null);      // false
isNaN(37);        // false

// 字串
isNaN("37");      // false: "37" 轉換成數字的 37 後就不是 NaN 了
isNaN("37.37");   // false: "37.37" 轉換成數字的 37.37 後就不是 NaN 了
isNaN("123ABC");  // true:  parseInt("123ABC") 是 123 但 Number("123ABC") 是 NaN
isNaN("");        // false: 空字串轉換成數字的 0 後就不是 NaN 了
isNaN(" ");       // false: 有空白的字串轉換成數字的 0 後就不是 NaN 了

// 日期
isNaN(new Date());                // false
isNaN(new Date().toString());     // true

// 這個偵測的錯誤是不能完全信賴 isNaN 的理由
isNaN("blabla")   // true: "blabla" 被轉換為數字,將其解析為數字失敗後回傳了 NaN
</pre>

<h3 id="實用的特殊狀況行為">實用的特殊狀況行為</h3>

<p>當然,你能以更用途導向的方法去思考 <code>isNaN()</code>:如果 <code>isNaN()</code> 回傳 <code>false</code>,那麼把 <code>x</code> 用在任何算術表達式都不會回傳 <code>NaN</code>。相反地,如果回傳 <code>true</code>,那麼把 <code>x</code> 用在任何算術表達式都會是 <code>NaN</code>。這在 JavaScript 的意義是 <code>isNaN(x) == true</code> 等於 <code>x - 0</code> 回傳 <code>NaN</code>(儘管在 JavaScript 裡面 <code>x - 0 == NaN</code> 永遠回傳 false,你因而無法測試)──事實上,<code>isNaN(x)</code><code>isNaN(x - 0)</code><code>isNaN(Number(x))</code><code>Number.isNaN(x - 0)</code><code>Number.isNaN(Number(x))</code> 在 JavaScript 裡面,都會回傳一樣的東西。而 <code>isNaN(x)</code> 是所有表達式裡面最短的一種。</p>

<p>比方說,你可以用這個式子,去測試函式的參數能不能透過算術處理(也就是能「像」數字一樣被利用)、否則就提供預設值之類的。你可以透過上下文的根據以隱式數值轉換(implicitly converting values),以使用 JavaScript 提供的全部功能。</p>

<h2 id="範例_2">範例</h2>

<pre class="brush: js">function increment(x) {
  if (isNaN(x)) x = 0;
  return x + 1;
};

// 與 Number.isNaN() 一樣:
function increment(x) {
  if (Number.isNaN(Number(x))) x = 0;
  return x + 1;
};

// 以下範例的函式參數 x,isNaN(x) 都會回傳 false,
// 儘管 x 不是數字,依舊能用在算術表達式。
increment("");            // 1: "" 被轉換成 0
increment(new String());  // 1: 空字串的新字串物件被轉換成 0
increment([]);            // 1: [] 被轉換成 0
increment(new Array());   // 1: 空陣列的新陣列物件被轉換成 0
increment("0");           // 1: "0" 被轉換成 0
increment("1");           // 2: "1" 被轉換成 1
increment("0.1");         // 1.1: "0.1" 被轉換成 0.1
increment("Infinity");    // Infinity: "Infinity" 被轉換成 Infinity
increment(null);          // 1: null 被轉換成 0
increment(false);         // 1: false 被轉換成 0
increment(true);          // 2: true 被轉換成 1
increment(new Date());    // 回傳以毫秒為單位加 1,當今的日期/時間

// 以下範例的函式參數 x,isNaN(x) 都會回傳 false,而 x 的確是數字。
increment(-1);            // 0
increment(-0.1);          // 0.9
increment(0);             // 1
increment(1);             // 2
increment(2);             // 3
// …等等…
increment(Infinity);      // Infinity

// 以下範例的函式參數 x,isNaN(x) 都會回傳 true,x 也的確不是數字。
// 使得函式會被 0 取代,並回傳 1
increment(String);            // 1
increment(Array);             // 1
increment("blabla");          // 1
increment("-blabla");         // 1
increment(0/0);               // 1
increment("0/0");             // 1
increment(Infinity/Infinity); // 1
increment(NaN);               // 1
increment(undefined);         // 1
increment();                  // 1

// isNaN(x) 與 isNaN(Number(x)) 永遠一樣,不過這裡的 x 是強制存在的!
isNaN(x) == isNaN(Number(x)) // 針對所有 x 的值都是 true,x == undefined 也不例外,
                             // 因為 isNaN(undefined) == true 且 Number(undefined) 回傳 NaN,
                             // 不過……
isNaN() == isNaN(Number())   // false,因為 isNaN() == true 且 Number() == 0
</pre>

<h2 id="規範">規範</h2>

<table class="standard-table">
 <tbody>
  <tr>
   <th scope="col">規範</th>
   <th scope="col">狀態</th>
   <th scope="col">註解</th>
  </tr>
  <tr>
   <td>{{SpecName('ES1')}}</td>
   <td>{{Spec2('ES1')}}</td>
   <td>Initial definition.</td>
  </tr>
  <tr>
   <td>{{SpecName('ES5.1', '#sec-15.1.2.4', 'isNaN')}}</td>
   <td>{{Spec2('ES5.1')}}</td>
   <td> </td>
  </tr>
  <tr>
   <td>{{SpecName('ES6', '#sec-isnan-number', 'isNaN')}}</td>
   <td>{{Spec2('ES6')}}</td>
   <td> </td>
  </tr>
  <tr>
   <td>{{SpecName('ESDraft', '#sec-isnan-number', 'isNaN')}}</td>
   <td>{{Spec2('ESDraft')}}</td>
   <td> </td>
  </tr>
 </tbody>
</table>

<h2 id="瀏覽器相容性">瀏覽器相容性</h2>



<p>{{Compat("javascript.builtins.isNaN")}}</p>

<h2 id="參見">參見</h2>

<ul>
 <li>{{jsxref("NaN")}}</li>
 <li>{{jsxref("Number.isNaN()")}}</li>
</ul>