184 lines
15 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>instanceof运算符用于测试构造函数的prototype属性是否出现在对象的原型链中的任何位置</p>
<div><iframe class="interactive interactive-js" frameborder="0" height="250" src="https://interactive-examples.mdn.mozilla.net/pages/js/expressions-instanceof.html" width="100%"></iframe></div>
<p 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 class="external" href="https://github.com/mdn/interactive-examples" rel="noopener">https://github.com/mdn/interactive-examples</a> and send us a pull request.</p>
<h2 id="Syntax" name="Syntax">语法</h2>
<pre><code><em>object</em> instanceof <em>constructor</em></code></pre>
<h3 id="Parameters" name="Parameters">参数</h3>
<dl>
<dt><code>object</code></dt>
<dd>要检测的对象.</dd>
</dl>
<dl>
<dt><code>constructor</code></dt>
<dd>某个构造函数</dd>
</dl>
<h2 id="Description" name="Description">描述</h2>
<p><code>instanceof </code>运算符用来检测 <code>constructor.prototype </code>是否存在于参数 <code>object</code> 的原型链上。</p>
<pre class="brush: js">// 定义构造函数
function C(){}
function D(){}
var o = new C();
o instanceof C; // true因为 Object.getPrototypeOf(o) === C.prototype
o instanceof D; // false因为 D.prototype不在o的原型链上
o instanceof Object; // true,因为Object.prototype.isPrototypeOf(o)返回true
C.prototype instanceof Object // true,同上
C.prototype = {};
var o2 = new C();
o2 instanceof C; // true
o instanceof C; // false,C.prototype指向了一个空对象,这个空对象不在o的原型链上.
D.prototype = new C(); // 继承
var o3 = new D();
o3 instanceof D; // true
o3 instanceof C; // true 因为C.prototype现在在o3的原型链上
</pre>
<p>需要注意的是,如果表达式 <code>obj instanceof Foo</code> 返回<code>true</code>,则并不意味着该表达式会永远返回<code>true</code>,因为<code>Foo.prototype</code>属性的值有可能会改变,改变之后的值很有可能不存在于<code>obj</code>的原型链上,这时原表达式的值就会成为<code>false</code>。另外一种情况下,原表达式的值也会改变,就是改变对象<code>obj</code>的原型链的情况虽然在目前的ES规范中我们只能读取对象的原型而不能改变它但借助于非标准的<code>__proto__</code>伪属性,是可以实现的。比如执行<code>obj.__proto__ = {}</code>之后,<code>obj instanceof Foo</code>就会返回<code>false</code>了。</p>
<h3 id="instanceof和多全局对象(多个frame或多个window之间的交互)"><code>instanceof</code>和多全局对象(多个frame或多个window之间的交互)</h3>
<p>在浏览器中,我们的脚本可能需要在多个窗口之间进行交互。多个窗口意味着多个全局环境,不同的全局环境拥有不同的全局对象,从而拥有不同的内置类型构造函数。这可能会引发一些问题。比如,表达式 <code>[] instanceof window.frames[0].Array</code> 会返回<code>false</code>,因为 <code>Array.prototype !== window.frames[0].Array.prototype</code>,并且数组从前者继承。</p>
<p>起初你会认为这样并没有意义但是当你在你的脚本中开始处理多个frame或多个window以及通过函数将对象从一个窗口传到另一个窗口时这就是一个有效而强大的话题。比如实际上你可以通过使用 <code>Array.isArray(myObj)</code> 或者<code>Object.prototype.toString.call(myObj) === "[object Array]"</code>来安全的检测传过来的对象是否是一个数组。</p>
<p>比如检测一个<code>Nodes</code>在另一个窗口中是不是<code>SVGElement</code>,你可以使用<code>myNode instanceof myNode.ownerDocument.defaultView.SVGElement</code></p>
<div class="note"><strong>Mozilla开发者注意:</strong><br/>
在代码中使用 XPCOM <code>instanceof </code>有特殊影响: 如果查询接口成功执行后,<code>obj instanceof </code><em><code>xpcomInterface</code></em> (e.g. <code>Components.interfaces.nsIFile</code>) 调用<code>obj.QueryInterface(<em>xpcomInterface</em>)</code> 并且返回 <code>true</code> 。这种调用的副作用是在一次成功的<code>instanceof</code>测试后,你可以在<code>obj</code>上使用<code>xpcomInterface</code>的属性。这与标准的<code>JavaScript</code>全局变量不同,即使<code>obj</code>来自不同的作用域, <code>obj instanceof xpcomInterface</code>也可以按预期产生作用。</div>
<h2 id="Examples" name="Examples">示例</h2>
<h3 id="Example:_Demonstrating_that_String_and_Date_are_of_type_Object" name="Example:_Demonstrating_that_String_and_Date_are_of_type_Object">演示<code>String</code>对象和<code>Date</code>对象都属于<code>Object</code>类型和一些特殊情况</h3>
<p>下面的代码使用了<code>instanceof</code>来证明:<code>String和</code><code>Date</code>对象同时也属于<code>Object</code>类型(他们是由<code>Object</code>类派生出来的)。</p>
<p>但是使用对象文字符号创建的对象在这里是一个例外虽然原型未定义但instanceof Object返回true。</p>
<pre class="brush: js"><code>var simpleStr = "This is a simple string";
var myString = new String();
var newStr = new String("String created with constructor");
var myDate = new Date();
var myObj = {};
var myNonObj = Object.create(null);
simpleStr instanceof String; // 返回 false, 检查原型链会找到 undefined
myString instanceof String; // 返回 true
newStr instanceof String; // 返回 true
myString instanceof Object; // 返回 true
myObj instanceof Object; // 返回 true, 尽管原型没有定义
({}) instanceof Object; // 返回 true, 同上
myNonObj instanceof Object; // 返回 false, 一种创建对象的方法这种方法创建的对象不是Object的一个实例
myString instanceof Date; //返回 false
myDate instanceof Date; // 返回 true
myDate instanceof Object; // 返回 true
myDate instanceof String; // 返回 false</code></pre>
<h3 id="Example:_Demonstrating_that_mycar_is_of_type_Car_and_type_Object" name="Example:_Demonstrating_that_mycar_is_of_type_Car_and_type_Object">演示<code>mycar</code>属于<code>Car</code>类型的同时又属于<code>Object</code>类型</h3>
<p>下面的代码创建了一个类型<code>Car</code>,以及该类型的对象实例<code>mycar</code>. <code>instanceof</code>运算符表明了这个<code>mycar</code>对象既属于<code>Car</code>类型,又属于<code>Object</code>类型。</p>
<pre class="brush: js">function Car(make, model, year) {
this.make = make;
this.model = model;
this.year = year;
}
var mycar = new Car("Honda", "Accord", 1998);
var a = mycar instanceof Car; // 返回 true
var b = mycar instanceof Object; // 返回 true
</pre>
<h3 id="不是一个实例">不是一个实例</h3>
<p>要测试对象是否不是特定构造函数的实例,你可以这样做</p>
<pre><code>if (!(mycar instanceof Car)) {
// Do something, like mycar = new Car(mycar)
}</code></pre>
<p>下面代码完全不同</p>
<pre><code>if (!mycar instanceof Car)</code></pre>
<p>这将永远是假的(<code>!mycar</code>将在<code>instanceof</code>之前被处理所以你总是验证布尔值是否是Car的一个实例</p>
<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://tc39.github.io/ecma262/#sec-relational-operators" hreflang="en" lang="en" rel="noopener">ECMAScript Latest Draft (ECMA-262)<br/><small lang="zh-CN">Relational Operators</small></a></td>
<td><span class="spec-Draft">Draft</span></td>
<td> </td>
</tr>
<tr>
<td><a class="external" href="https://www.ecma-international.org/ecma-262/6.0/#sec-relational-operators" hreflang="en" lang="en" rel="noopener">ECMAScript 2015 (6th Edition, ECMA-262)<br/><small lang="zh-CN">Relational Operators</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/5.1/#sec-11.8.6" hreflang="en" lang="en" rel="noopener">ECMAScript 5.1 (ECMA-262)<br/><small lang="zh-CN">The instanceof operator</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/publications/files/ECMA-ST-ARCH/ECMA-262,%203rd%20edition,%20December%201999.pdf#sec-11.8.6" hreflang="en" lang="en" rel="noopener">ECMAScript 3rd Edition (ECMA-262)<br/><small lang="zh-CN">The instanceof operator</small></a></td>
<td><span class="spec-Standard">Standard</span></td>
<td>Initial definition. Implemented in JavaScript 1.4.</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 class="external" href="https://github.com/mdn/browser-compat-data" rel="noopener">https://github.com/mdn/browser-compat-data</a> and send us a pull request.</p>
</div>
<p></p><div class="bc-data"><a class="bc-github-link external" href="https://github.com/mdn/browser-compat-data" rel="noopener">Update compatibility data on GitHub</a><table class="bc-table bc-table-js"><thead><tr class="bc-platforms"><td></td><th class="bc-platform-desktop" colspan="6"><span>Desktop</span></th><th class="bc-platform-mobile" colspan="7"><span>Mobile</span></th><th class="bc-platform-server" colspan="1"><span>Server</span></th></tr><tr class="bc-browsers"><td></td><th class="bc-browser-chrome"><span class="bc-head-txt-label bc-head-icon-chrome">Chrome</span></th><th class="bc-browser-edge"><span class="bc-head-txt-label bc-head-icon-edge">Edge</span></th><th class="bc-browser-firefox"><span class="bc-head-txt-label bc-head-icon-firefox">Firefox</span></th><th class="bc-browser-ie"><span class="bc-head-txt-label bc-head-icon-ie">Internet Explorer</span></th><th class="bc-browser-opera"><span class="bc-head-txt-label bc-head-icon-opera">Opera</span></th><th class="bc-browser-safari"><span class="bc-head-txt-label bc-head-icon-safari">Safari</span></th><th class="bc-browser-webview_android"><span class="bc-head-txt-label bc-head-icon-webview_android">Android webview</span></th><th class="bc-browser-chrome_android"><span class="bc-head-txt-label bc-head-icon-chrome_android">Chrome for Android</span></th><th class="bc-browser-edge_mobile"><span class="bc-head-txt-label bc-head-icon-edge_mobile">Edge Mobile</span></th><th class="bc-browser-firefox_android"><span class="bc-head-txt-label bc-head-icon-firefox_android">Firefox for Android</span></th><th class="bc-browser-opera_android"><span class="bc-head-txt-label bc-head-icon-opera_android">Opera for Android</span></th><th class="bc-browser-safari_ios"><span class="bc-head-txt-label bc-head-icon-safari_ios">Safari on iOS</span></th><th class="bc-browser-samsunginternet_android"><span class="bc-head-txt-label bc-head-icon-samsunginternet_android">Samsung Internet</span></th><th class="bc-browser-nodejs"><span class="bc-head-txt-label bc-head-icon-nodejs">Node.js</span></th></tr></thead><tbody><tr><th scope="row"><code>instanceof</code></th><td class="bc-supports-yes bc-browser-chrome"><span class="bc-browser-name">Chrome</span><abbr class="bc-level-yes only-icon" title="Full support">
<span>Full support</span>
</abbr>
Yes</td><td class="bc-supports-yes bc-browser-edge"><span class="bc-browser-name">Edge</span><abbr class="bc-level-yes only-icon" title="Full support">
<span>Full support</span>
</abbr>
Yes</td><td class="bc-supports-yes bc-browser-firefox"><span class="bc-browser-name">Firefox</span><abbr class="bc-level-yes only-icon" title="Full support">
<span>Full support</span>
</abbr>
1</td><td class="bc-supports-yes bc-browser-ie"><span class="bc-browser-name">IE</span><abbr class="bc-level-yes only-icon" title="Full support">
<span>Full support</span>
</abbr>
Yes</td><td class="bc-supports-yes bc-browser-opera"><span class="bc-browser-name">Opera</span><abbr class="bc-level-yes only-icon" title="Full support">
<span>Full support</span>
</abbr>
Yes</td><td class="bc-supports-yes bc-browser-safari"><span class="bc-browser-name">Safari</span><abbr class="bc-level-yes only-icon" title="Full support">
<span>Full support</span>
</abbr>
Yes</td><td class="bc-supports-yes bc-browser-webview_android"><span class="bc-browser-name">WebView Android</span><abbr class="bc-level-yes only-icon" title="Full support">
<span>Full support</span>
</abbr>
Yes</td><td class="bc-supports-yes bc-browser-chrome_android"><span class="bc-browser-name">Chrome Android</span><abbr class="bc-level-yes only-icon" title="Full support">
<span>Full support</span>
</abbr>
Yes</td><td class="bc-supports-yes bc-browser-edge_mobile"><span class="bc-browser-name">Edge Mobile</span><abbr class="bc-level-yes only-icon" title="Full support">
<span>Full support</span>
</abbr>
Yes</td><td class="bc-supports-yes bc-browser-firefox_android"><span class="bc-browser-name">Firefox Android</span><abbr class="bc-level-yes only-icon" title="Full support">
<span>Full support</span>
</abbr>
4</td><td class="bc-supports-yes bc-browser-opera_android"><span class="bc-browser-name">Opera Android</span><abbr class="bc-level-yes only-icon" title="Full support">
<span>Full support</span>
</abbr>
Yes</td><td class="bc-supports-yes bc-browser-safari_ios"><span class="bc-browser-name">Safari iOS</span><abbr class="bc-level-yes only-icon" title="Full support">
<span>Full support</span>
</abbr>
Yes</td><td class="bc-supports-yes bc-browser-samsunginternet_android"><span class="bc-browser-name">Samsung Internet Android</span><abbr class="bc-level-yes only-icon" title="Full support">
<span>Full support</span>
</abbr>
Yes</td><td class="bc-supports-yes bc-browser-nodejs"><span class="bc-browser-name">nodejs</span><abbr class="bc-level-yes only-icon" title="Full support">
<span>Full support</span>
</abbr>
Yes</td></tr></tbody></table><section class="bc-legend" id="sect1"><h3 class="offscreen" id="Legend">Legend</h3><dl><dt><span class="bc-supports-yes bc-supports">
<abbr class="bc-level bc-level-yes only-icon" title="Full support">
<span>Full support</span>
 
</abbr></span></dt><dd>Full support</dd></dl></section></div><p></p>
<h2 id="See_also" name="See_also">相关链接</h2>
<ul>
<li><a href="/zh-CN/docs/JavaScript/Reference/Operators/typeof" title="/zh-CN/docs/JavaScript/Reference/Operators/typeof">typeof</a></li>
<li><a href="Reference/Global_Objects/Symbol/hasInstance" title="Symbol.hasInstance 用于判断某对象是否为某构造器的实例。 因此你可以用它自定义 instanceof 操作符在某个类上的行为。"><code>Symbol.hasInstance</code></a></li>
</ul>
</article>