2019-04-21 11:50:48 +08:00

206 lines
14 KiB
HTML
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<article id="wikiArticle">
<div></div>
<p><code><strong>isNaN()</strong></code> 函数用来确定一个值是否为<a href="Reference/Global_Objects/NaN" title="全局属性 NaN 的值表示不是一个数字Not-A-Number。"><code>NaN</code></a> 。注:<code>isNaN</code>函数内包含一些非常有趣的<a href="#Description">规则</a>你也可以通过ECMAScript 2015/ES6 中定义的<a href="Reference/Global_Objects/Number/isNaN" title="Number.isNaN() 方法确定传递的值是否为 NaN和其类型是 Number。它是原始的全局isNaN()的更强大的版本。"><code>Number.isNaN()</code></a>或者 可以使用<code><a href="/en-US/docs/Web/JavaScript/Reference/Operators/typeof">typeof</a></code> 来判断该值是否为一个非数字。</p>
<h2 id="Syntax" name="Syntax">语法</h2>
<pre><code class="language-javascript"><code>isNaN(<em>testValue</em>)</code></code></pre>
<h3 id="Parameters" name="Parameters">参数</h3>
<dl>
<dt><code>testValue</code></dt>
<dd>要被检测的值。</dd>
</dl>
<h3 id="返回值">返回值</h3>
<p>如果给定值为 <a href="Reference/Global_Objects/NaN" title="全局属性 NaN 的值表示不是一个数字Not-A-Number。"><code>NaN</code></a>则返回值为<code>true</code>;否则为<code>false</code></p>
<h2 id="Description" name="Description">描述</h2>
<h3 id="The_necessity_of_an_isNaN_function" name="The_necessity_of_an_isNaN_function"><code>isNaN</code> 函数的必要性</h3>
<p>与 JavaScript 中其他的值不同,<a href="Reference/Global_Objects/NaN" title="全局属性 NaN 的值表示不是一个数字Not-A-Number。"><code>NaN</code></a>不能通过相等操作符(== 和 ===)来判断 ,因为 <code>NaN == NaN</code><code>NaN === NaN</code> 都会返回 <code>false</code>。 因此,<code>isNaN</code> 就很有必要了。</p>
<h3 id="Origin_of_NaN_values" name="Origin_of_NaN_values"><code>NaN值</code>的产生</h3>
<p><font face="Courier New, Andale Mono, monospace">当算术运算返回一个未定义的或无法表示的值时NaN就产生了。但是<code>NaN</code>并不一定用于表示某些值超出表示范围的情况。</font><font face="Consolas, Monaco, 'Andale Mono', monospace">将某些不能强制转换为数值的非数值转换为数值的时候,也会得到<code>NaN</code></font></p>
<p>例如0 除以0会返回<code>NaN </code>—— 但是其他数除以0则不会返回<code>NaN</code></p>
<h3 id="令人费解的怪异行为">令人费解的怪异行为</h3>
<p>如果<code>isNaN</code>函数的参数不是<code>Number</code>类型, <code>isNaN</code>函数会首先尝试将这个参数转换为数值,然后才会对转换后的结果是否是<a href="Reference/Global_Objects/NaN" title="全局属性 NaN 的值表示不是一个数字Not-A-Number。"><code>NaN</code></a>进行判断。因此对于能被强制转换为有效的非NaN数值来说空字符串和布尔值分别会被强制转换为数值0和1返回<code>false</code>值也许会让人感觉莫名其妙。比如说空字符串就明显“不是数值not a number”。这种怪异行为起源于"不是数值not a number"在基于IEEE-754数值的浮点计算体制中代表了一种特定的含义。<code>isNaN</code>函数其实等同于回答了这样一个问题被测试的值在被强制转换成数值时会不会返回IEEE-754中所谓的“不是数值not a number”。</p>
<p>下一个版本的ECMAScript (ES2015)包含<a href="Reference/Global_Objects/Number/isNaN" title="Number.isNaN() 方法确定传递的值是否为 NaN和其类型是 Number。它是原始的全局isNaN()的更强大的版本。"><code>Number.isNaN()</code></a>函数。通过<code>Number.isNaN(x)</code>来检测<code>变量x</code>是否是一个<code>NaN</code><font face="'Open Sans', sans-serif">将会是一种可靠的做法</font>。然而,在缺少<code>Number.isNaN</code>函数的情况下, 通过表达式<code>(x != x)</code> 来检测<code>变量x</code>是否是<code>NaN</code>会更加可靠。</p>
<p>一个<code>isNaN</code>的 polyfill 可以理解为这个polyfill利用了<code>NaN</code>自身永不相等于自身这一特征 </p>
<pre><code class="language-javascript"><code class="language-js"><span class="keyword token">var</span> isNaN <span class="operator token">=</span> <span class="keyword token">function</span><span class="punctuation token">(</span>value<span class="punctuation token">)</span> <span class="punctuation token">{</span>
<span class="keyword token">var</span> n <span class="operator token">=</span> <span class="function token">Number</span><span class="punctuation token">(</span>value<span class="punctuation token">)</span><span class="punctuation token">;</span>
<span class="keyword token">return</span> n <span class="operator token">!==</span> n<span class="punctuation token">;</span>
<span class="punctuation token">}</span><span class="punctuation token">;</span></code></code></pre>
<h2 id="Examples" name="Examples">示例</h2>
<pre><code class="language-javascript">isNaN(NaN); // true
isNaN(undefined); // true
isNaN({}); // true
isNaN(true); // false
isNaN(null); // false
isNaN(37); // false
// strings
isNaN("37"); // false: 可以被转换成数值37
isNaN("37.37"); // false: 可以被转换成数值37.37
isNaN("37,5");    // true
isNaN('123ABC');  // true: parseInt("123ABC")的结果是 123, 但是Number("123ABC")结果是 NaN
isNaN(""); // false: 空字符串被转换成0
isNaN(" "); // false: 包含空格的字符串被转换成0
// dates
isNaN(new Date()); // false
isNaN(new Date().toString()); // true
isNaN("blabla") // true: "blabla"不能转换成数值
// 转换成数值失败, 返回NaN
</code></pre>
<h3 id="有用的特殊行为">有用的特殊行为</h3>
<p>有许多方式来看待isNaN()如果isNaN(x)返回false那么x在任何算数表达式中都不会使表达式等于NaN如果返回truex会使所有算数表达式返回NaN。这就意味着在JavaScript中isNaN(x)==true等价于x-0=NaN(在JavaScript中 x-0 == NaN 总是返回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中isNaN(x)是这些表达式中最短的表达。</p>
<p>举个例子可以利用这个特殊行为来检测函数的参数是可运算的可以像number一样进行加减乘除等运算。如果不可运算则可赋予这个参数一个默认的值或其他合适的内容。这样就可以得到一个隐式转换参数值的函数而这得益于Javascript的全功能性。</p>
<h2 id="例子">例子</h2>
<pre><code class="language-javascript">function increment(x) {
if (isNaN(x)) x = 0;
return x + 1;
};
// The same effect with Number.isNaN():
function increment(x) {
if (Number.isNaN(Number(x))) x = 0;
return x + 1;
};
// In the following cases for the function's argument x,
// isNaN(x) is always false, although x is indeed not a
// number, but can be used as such in arithmetical
// expressions
increment(""); // 1: "" is converted to 0
increment(new String()); // 1: String object representing an empty string is converted to 0
increment([]); // 1: [] is converted to 0
increment(new Array()); // 1: Array object representing an empty array is converted to 0
increment("0"); // 1: "0" is converted to 0
increment("1"); // 2: "1" is converted to 1
increment("0.1"); // 1.1: "0.1" is converted to 0.1
increment("Infinity"); // Infinity: "Infinity" is converted to Infinity
increment(null); // 1: null is converted to 0
increment(false); // 1: false is converted to 0
increment(true); // 2: true is converted to 1
increment(new Date()); // returns current date/time in milliseconds plus 1
// In the following cases for the function's argument x,
// isNaN(x) is always false and x is indeed a number
increment(-1); // 0
increment(-0.1); // 0.9
increment(0); // 1
increment(1); // 2
increment(2); // 3
// ... and so on ...
increment(Infinity); // Infinity
// In the following cases for the function's argument x,
// isNaN(x) is always true and x is really not a number,
// thus the function replaces it by 0 and returns 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) is always the same as isNaN(Number(x)),
// but the presence of x is mandatory here!
isNaN(x) == isNaN(Number(x)) // true for every value of x, including x == undefined,
// because isNaN(undefined) == true and Number(undefined) returns NaN,
// but ...
isNaN() == isNaN(Number()) // false, because isNaN() == true and Number() == 0</code></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><a class="external" href="https://www.ecma-international.org/publications/files/ECMA-ST-ARCH/ECMA-262,%201st%20edition,%20June%201997.pdf" hreflang="en" lang="en" rel="noopener" title="ECMAScript 1st Edition (ECMA-262)">ECMAScript 1st Edition (ECMA-262)</a></td>
<td><span class="spec-Standard">Standard</span></td>
<td>Initial definition.</td>
</tr>
<tr>
<td><a class="external" href="https://www.ecma-international.org/ecma-262/5.1/#sec-15.1.2.4" hreflang="en" lang="en" rel="noopener">ECMAScript 5.1 (ECMA-262)<br/><small lang="zh-CN">isNaN</small></a></td>
<td><span class="spec-Standard">Standard</span></td>
<td> </td>
</tr>
<tr>
<td><a class="external" href="https://www.ecma-international.org/ecma-262/6.0/#sec-isnan-number" hreflang="en" lang="en" rel="noopener">ECMAScript 2015 (6th Edition, ECMA-262)<br/><small lang="zh-CN">isNaN</small></a></td>
<td><span class="spec-Standard">Standard</span></td>
<td> </td>
</tr>
<tr>
<td><a class="external" href="https://tc39.github.io/ecma262/#sec-isnan-number" hreflang="en" lang="en" rel="noopener">ECMAScript Latest Draft (ECMA-262)<br/><small lang="zh-CN">isNaN</small></a></td>
<td><span class="spec-Draft">Draft</span></td>
<td> </td>
</tr>
</tbody>
</table>
<h2 id="浏览器兼容性">浏览器兼容性</h2>
<p></p><div class="blockIndicator warning"><strong><a class="external" href="https://github.com/mdn/browser-compat-data" rel="noopener">We're converting our compatibility data into a machine-readable JSON format</a></strong>.
This compatibility table still uses the old format,
because we haven't yet converted the data it contains.
<strong><a class="new" href="/zh-CN/docs/MDN/Contribute/Structures/Compatibility_tables" rel="nofollow">Find out how you can help!</a></strong></div>
<div class="htab">
<a id="AutoCompatibilityTable" name="AutoCompatibilityTable"></a>
<ul>
<li class="selected"><a>Desktop</a></li>
<li><a>Mobile</a></li>
</ul>
</div><p></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><span style="color: #888;" title="Please update this with the earliest version of support.">(Yes)</span></td>
<td><span style="color: #888;" title="Please update this with the earliest version of support.">(Yes)</span></td>
<td><span style="color: #888;" title="Please update this with the earliest version of support.">(Yes)</span></td>
<td><span style="color: #888;" title="Please update this with the earliest version of support.">(Yes)</span></td>
<td><span style="color: #888;" title="Please update this with the earliest version of support.">(Yes)</span></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><span style="color: #888;" title="Please update this with the earliest version of support.">(Yes)</span></td>
<td><span style="color: #888;" title="Please update this with the earliest version of support.">(Yes)</span></td>
<td><span style="color: #888;" title="Please update this with the earliest version of support.">(Yes)</span></td>
<td><span style="color: #888;" title="Please update this with the earliest version of support.">(Yes)</span></td>
<td><span style="color: #888;" title="Please update this with the earliest version of support.">(Yes)</span></td>
<td><span style="color: #888;" title="Please update this with the earliest version of support.">(Yes)</span></td>
</tr>
</tbody>
</table>
</div>
<h2 id="相关链接">相关链接</h2>
<ul>
<li><a href="Reference/Global_Objects/NaN" title="全局属性 NaN 的值表示不是一个数字Not-A-Number。"><code>NaN</code></a></li>
<li><a href="Reference/Global_Objects/Number/isNaN" title="Number.isNaN() 方法确定传递的值是否为 NaN和其类型是 Number。它是原始的全局isNaN()的更强大的版本。"><code>Number.isNaN()</code></a></li>
</ul>
</article>