属性的可枚举性和所有权

  • 版本网址缩略名: Enumerability_and_ownership_of_properties
  • 版本标题: 属性的可枚举性和所有权
  • 版本 id: 346605
  • 创建于:
  • 创建者: ziyunfei
  • 是否是当前版本?
  • 评论

修订内容

可枚举属性是指那些可以通过for..in循环遍历到的和属性.

属性所有权是由该属性是当前对象的自身属性还是当前对象从原型链上继承的属性来决定的.

Properties of an object can also be retrieved in total.

There are a number of built-in means of detecting, iterating/enumerating, and retrieving object properties, with the chart showing which are available. Some sample code follows which demonstrates how to obtain the missing categories.

 

Property enumerability and ownership - built-in methods of detection, retrieval, and iteration
Functionality Own object Own object and its prototype chain Prototype chain only
Detection
Enumerable Nonenumerable Enumerable and Nonenumerable
in and hasOwnProperty in and not propertyIsEnumerable hasOwnProperty
Not available without extra code Not available without extra code
Retrieval
Enumerable Nonenumerable Enumerable and Nonenumerable
Object.keys getOwnPropertyNames filtered to include properties when not passing propertyIsEnumerable getOwnPropertyNames
Not available without extra code Not available without extra code
Iteration
Enumerable Nonenumerable Enumerable and Nonenumerable
for..in filtered by hasOwnProperty Iterate over getOwnPropertyNames filtered to include properties when not passing propertyIsEnumerable Iterate over getOwnPropertyNames
Enumerable Nonenumerable Enumerable and Nonenumerable
for..in Not available without extra code Not available without extra code
Not available without extra code

   

Obtaining properties by enumerability/ownership

// Note that this is not the most efficient algorithm for all cases, but useful for a quick demonstration
// Detection can occur by SimplePropertyRetriever.theGetMethodYouWant(obj).indexOf(prop) > -1
// Iteration can occur by SimplePropertyRetriever.theGetMethodYouWant(obj).forEach(function (value, prop) {}); // Or use filter(), map(), etc.

var SimplePropertyRetriever = {
    getOwnEnumerables: function (obj) {
        return this._getPropertyNames(obj, true, false, this._enumerable); // Or could use for..in filtered with hasOwnProperty or just this: return Object.keys(obj);
    },
    getOwnNonenumerables: function (obj) {
        return this._getPropertyNames(obj, true, false, this._notEnumerable);
    },
    getOwnEnumerablesAndNonenumerables: function (obj) {
        return this._getPropertyNames(obj, true, false, this._enumerableAndNotEnumerable); // Or just use: return Object.getOwnPropertyNames(obj);
    },
    getPrototypeEnumerables: function (obj) {
        return this._getPropertyNames(obj, false, true, this._enumerable);
    },
    getPrototypeNonenumerables: function (obj) {
        return this._getPropertyNames(obj, false, true, this._notEnumerable);
    },
    getPrototypeEnumerablesAndNonenumerables: function (obj) {
        return this._getPropertyNames(obj, false, true, this._enumerableAndNotEnumerable);
    },
    getOwnAndPrototypeEnumerables: function (obj) {
        return this._getPropertyNames(obj, true, true, this._enumerable); // Or could use unfiltered for..in
    },
    getOwnAndPrototypeNonenumerables: function (obj) {
        return this._getPropertyNames(obj, true, true, this._notEnumerable);
    },
    getOwnAndPrototypeEnumerablesAndNonenumerables: function (obj) {
        return this._getPropertyNames(obj, true, true, this._enumerableAndNotEnumerable);
    },
    // Private static property checker callbacks
    _enumerable : function (obj, prop) {
        return obj.propertyIsEnumerable(prop);
    },
    _notEnumerable : function (obj, prop) {
        return !obj.propertyIsEnumerable(prop);
    },
    _enumerableAndNotEnumerable : function (obj, prop) {
        return true;
    },
    // Inspired by http://stackoverflow.com/a/8024294/271577
    _getPropertyNames : function getAllPropertyNames(obj, iterateSelfBool, iteratePrototypeBool, includePropCb) {
        var props = [];

        do {
            if (iterateSelfBool) {
                Object.getOwnPropertyNames(obj).forEach(function (prop) {
                    if (props.indexOf(prop) === -1 && includePropCb(obj, prop)) {
                        props.push(prop);
                    }
                });
            }
            if (!iteratePrototypeBool) {
                break;
            }
            iterateSelfBool = true;
        } while (obj = Object.getPrototypeOf(obj));

        return props;
    }
};

统计表

  in hasOwnProperty propertyIsEnumerable 在Object.keys返回结果中 在Object.getOwnPropertyNames返回结果中
可枚举自身属性 true true true true true
不可枚举自身属性 true true false false true
可枚举继承属性 true false false false false
不可枚举继承属性 true false false false false

相关链接

 

修订版来源

<p>可枚举属性是指那些可以通过<code>for..in</code>循环遍历到的和属性.</p>
<p>属性所有权是由该属性是当前对象的自身属性还是当前对象从原型链上继承的属性来决定的.</p>
<p>Properties of an object can also be retrieved in total.</p>
<p>There are a number of built-in means of detecting, iterating/enumerating, and retrieving object properties, with the chart showing which are available. Some sample code follows which demonstrates how to obtain the missing categories.</p>
<p>&nbsp;</p>
<table height="138" summary="Property enumerability and ownership - detection, retrieval, and iteration" width="598">
  <caption>
    Property enumerability and ownership - built-in methods of detection, retrieval, and iteration</caption>
  <tbody>
    <tr>
      <th>Functionality</th>
      <th>Own object</th>
      <th>Own object and its prototype chain</th>
      <th>Prototype chain only</th>
    </tr>
    <tr>
      <td>Detection</td>
      <td>
        <table summary="Enumerability">
          <thead>
            <tr>
              <th scope="col">Enumerable</th>
              <th scope="col">Nonenumerable</th>
              <th scope="col">Enumerable and Nonenumerable</th>
            </tr>
          </thead>
          <tbody>
            <tr>
              <td><a href="/en-US/docs/JavaScript/Reference/Operators/in" title="/en-US/docs/JavaScript/Reference/Operators/in">in</a> and <a href="/en-US/docs/JavaScript/Reference/Global_Objects/Object/hasOwnProperty" title="/en-US/docs/JavaScript/Reference/Global_Objects/Object/hasOwnProperty">hasOwnProperty</a></td>
              <td><a href="/en-US/docs/JavaScript/Reference/Operators/in" title="/en-US/docs/JavaScript/Reference/Operators/in">in</a> and not <a href="/en-US/docs/JavaScript/Reference/Global_Objects/Object/propertyIsEnumerable" title="/en-US/docs/JavaScript/Reference/Global_Objects/Object/propertyIsEnumerable">propertyIsEnumerable</a></td>
              <td><a href="/en-US/docs/JavaScript/Reference/Global_Objects/Object/hasOwnProperty" title="/en-US/docs/JavaScript/Reference/Global_Objects/Object/hasOwnProperty">hasOwnProperty</a></td>
            </tr>
          </tbody>
        </table>
      </td>
      <td>Not available without extra code</td>
      <td>Not available without extra code</td>
    </tr>
    <tr>
      <td>Retrieval</td>
      <td>
        <table summary="Enumerability">
          <thead>
            <tr>
              <th scope="col">Enumerable</th>
              <th scope="col">Nonenumerable</th>
              <th scope="col">Enumerable and Nonenumerable</th>
            </tr>
          </thead>
          <tbody>
            <tr>
              <td><a href="/en-US/docs/JavaScript/Reference/Global_Objects/Object/keys" title="/en-US/docs/JavaScript/Reference/Global_Objects/Object/keys">Object.keys</a></td>
              <td><a href="/en-US/docs/JavaScript/Reference/Global_Objects/Object/getOwnPropertyNames" title="/en-US/docs/JavaScript/Reference/Global_Objects/Object/getOwnPropertyNames">getOwnPropertyNames</a> filtered to include properties when not passing <a href="/en-US/docs/JavaScript/Reference/Global_Objects/Object/propertyIsEnumerable" title="/en-US/docs/JavaScript/Reference/Global_Objects/Object/propertyIsEnumerable">propertyIsEnumerable</a></td>
              <td><a href="/en-US/docs/JavaScript/Reference/Global_Objects/Object/getOwnPropertyNames" title="/en-US/docs/JavaScript/Reference/Global_Objects/Object/getOwnPropertyNames">getOwnPropertyNames</a></td>
            </tr>
          </tbody>
        </table>
      </td>
      <td>Not available without extra code</td>
      <td>Not available without extra code</td>
    </tr>
    <tr>
      <td>Iteration</td>
      <td>
        <table summary="Enumerability">
          <thead>
            <tr>
              <th scope="col">Enumerable</th>
              <th scope="col">Nonenumerable</th>
              <th scope="col">Enumerable and Nonenumerable</th>
            </tr>
          </thead>
          <tbody>
            <tr>
              <td><a href="/en-US/docs/JavaScript/Reference/Statements/for...in" title="/en-US/docs/JavaScript/Reference/Statements/for...in">for..in</a> filtered by <a href="/en-US/docs/JavaScript/Reference/Global_Objects/Object/hasOwnProperty" title="/en-US/docs/JavaScript/Reference/Global_Objects/Object/hasOwnProperty">hasOwnProperty</a></td>
              <td>Iterate over <a href="/en-US/docs/JavaScript/Reference/Global_Objects/Object/getOwnPropertyNames" title="/en-US/docs/JavaScript/Reference/Global_Objects/Object/getOwnPropertyNames">getOwnPropertyNames</a> filtered to include properties when not passing <a href="/en-US/docs/JavaScript/Reference/Global_Objects/Object/propertyIsEnumerable" title="/en-US/docs/JavaScript/Reference/Global_Objects/Object/propertyIsEnumerable">propertyIsEnumerable</a></td>
              <td>Iterate over <a href="/en-US/docs/JavaScript/Reference/Global_Objects/Object/getOwnPropertyNames" title="/en-US/docs/JavaScript/Reference/Global_Objects/Object/getOwnPropertyNames">getOwnPropertyNames</a></td>
            </tr>
          </tbody>
        </table>
      </td>
      <td>
        <table summary="Enumerability">
          <thead>
            <tr>
              <th scope="col">Enumerable</th>
              <th scope="col">Nonenumerable</th>
              <th scope="col">Enumerable and Nonenumerable</th>
            </tr>
          </thead>
          <tbody>
            <tr>
              <td><a href="/en-US/docs/JavaScript/Reference/Statements/for...in" title="/en-US/docs/JavaScript/Reference/Statements/for...in">for..in</a></td>
              <td>Not available without extra code</td>
              <td>Not available without extra code</td>
            </tr>
          </tbody>
        </table>
      </td>
      <td>Not available without extra code</td>
    </tr>
  </tbody>
</table>
<p>&nbsp;&nbsp;&nbsp;</p>
<h2 id="Obtaining_properties_by_enumerability.2Fownership">Obtaining properties by enumerability/ownership</h2>
<pre class="brush: js">
// Note that this is not the most efficient algorithm for all cases, but useful for a quick demonstration
// Detection can occur by SimplePropertyRetriever.theGetMethodYouWant(obj).indexOf(prop) &gt; -1
// Iteration can occur by SimplePropertyRetriever.theGetMethodYouWant(obj).forEach(function (value, prop) {}); // Or use filter(), map(), etc.

var SimplePropertyRetriever = {
&nbsp;&nbsp;&nbsp; getOwnEnumerables: function (obj) {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return this._getPropertyNames(obj, true, false, this._enumerable); // Or could use for..in filtered with hasOwnProperty or just this: return Object.keys(obj);
&nbsp;&nbsp;&nbsp; },
&nbsp;&nbsp;&nbsp; getOwnNonenumerables: function (obj) {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return this._getPropertyNames(obj, true, false, this._notEnumerable);
&nbsp;&nbsp;&nbsp; },
&nbsp;&nbsp;&nbsp; getOwnEnumerablesAndNonenumerables: function (obj) {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return this._getPropertyNames(obj, true, false, this._enumerableAndNotEnumerable); // Or just use: return Object.getOwnPropertyNames(obj);
&nbsp;&nbsp;&nbsp; },
&nbsp;&nbsp;&nbsp; getPrototypeEnumerables: function (obj) {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return this._getPropertyNames(obj, false, true, this._enumerable);
&nbsp;&nbsp;&nbsp; },
&nbsp;&nbsp;&nbsp; getPrototypeNonenumerables: function (obj) {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return this._getPropertyNames(obj, false, true, this._notEnumerable);
&nbsp;&nbsp;&nbsp; },
&nbsp;&nbsp;&nbsp; getPrototypeEnumerablesAndNonenumerables: function (obj) {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return this._getPropertyNames(obj, false, true, this._enumerableAndNotEnumerable);
&nbsp;&nbsp;&nbsp; },
&nbsp;&nbsp;&nbsp; getOwnAndPrototypeEnumerables: function (obj) {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return this._getPropertyNames(obj, true, true, this._enumerable); // Or could use unfiltered for..in
&nbsp;&nbsp;&nbsp; },
&nbsp;&nbsp;&nbsp; getOwnAndPrototypeNonenumerables: function (obj) {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return this._getPropertyNames(obj, true, true, this._notEnumerable);
&nbsp;&nbsp;&nbsp; },
&nbsp;&nbsp;&nbsp; getOwnAndPrototypeEnumerablesAndNonenumerables: function (obj) {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return this._getPropertyNames(obj, true, true, this._enumerableAndNotEnumerable);
&nbsp;&nbsp;&nbsp; },
&nbsp;&nbsp;&nbsp; // Private static property checker callbacks
&nbsp;&nbsp;&nbsp; _enumerable : function (obj, prop) {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return obj.propertyIsEnumerable(prop);
&nbsp;&nbsp;&nbsp; },
&nbsp;&nbsp;&nbsp; _notEnumerable : function (obj, prop) {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return !obj.propertyIsEnumerable(prop);
&nbsp;&nbsp;&nbsp; },
&nbsp;&nbsp;&nbsp; _enumerableAndNotEnumerable : function (obj, prop) {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return true;
&nbsp;&nbsp;&nbsp; },
&nbsp;&nbsp;&nbsp; // Inspired by http://stackoverflow.com/a/8024294/271577
&nbsp;&nbsp;&nbsp; _getPropertyNames : function getAllPropertyNames(obj, iterateSelfBool, iteratePrototypeBool, includePropCb) {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var props = [];

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; do {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (iterateSelfBool) {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Object.getOwnPropertyNames(obj).forEach(function (prop) {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (props.indexOf(prop) === -1 &amp;&amp; includePropCb(obj, prop)) {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; props.push(prop);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; });
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (!iteratePrototypeBool) {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; iterateSelfBool = true;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } while (obj = Object.getPrototypeOf(obj));

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return props;
&nbsp;&nbsp;&nbsp; }
};</pre>
<h2 id="Detection_Table">统计表</h2>
<table align="center">
  <thead>
    <tr>
      <th scope="row">&nbsp;</th>
      <th scope="col">in</th>
      <th scope="col">hasOwnProperty</th>
      <th scope="col">propertyIsEnumerable</th>
      <th scope="col">在Object.keys返回结果中</th>
      <th scope="col">在Object.getOwnPropertyNames返回结果中</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th scope="row">可枚举自身属性</th>
      <td style="text-align: center;">true</td>
      <td style="text-align: center;">true</td>
      <td style="text-align: center;">true</td>
      <td style="text-align: center;">true</td>
      <td style="text-align: center;">true</td>
    </tr>
    <tr>
      <th scope="row">不可枚举自身属性</th>
      <td style="text-align: center;">true</td>
      <td style="text-align: center;">true</td>
      <td style="text-align: center;">false</td>
      <td style="text-align: center;">false</td>
      <td style="text-align: center;">true</td>
    </tr>
    <tr>
      <th scope="row">可枚举继承属性</th>
      <td style="text-align: center;">true</td>
      <td style="text-align: center;">false</td>
      <td style="text-align: center;">false</td>
      <td style="text-align: center;">false</td>
      <td style="text-align: center;">false</td>
    </tr>
    <tr>
      <th scope="row">不可枚举继承属性</th>
      <td style="text-align: center;">true</td>
      <td style="text-align: center;">false</td>
      <td style="text-align: center;">false</td>
      <td style="text-align: center;">false</td>
      <td style="text-align: center;">false</td>
    </tr>
  </tbody>
</table>
<h2 id="See_also">相关链接</h2>
<ul>
  <li><a href="/en-US/docs/JavaScript/Reference/Operators/in" title="/en-US/docs/JavaScript/Reference/Operators/in">in</a></li>
  <li><a href="/en-US/docs/JavaScript/Reference/Statements/for...in" title="/en-US/docs/JavaScript/Reference/Statements/for...in">for..in</a></li>
  <li><a href="/en-US/docs/JavaScript/Reference/Global_Objects/Object/hasOwnProperty" title="/en-US/docs/JavaScript/Reference/Global_Objects/Object/hasOwnProperty">hasOwnProperty</a></li>
  <li><a href="/en-US/docs/JavaScript/Reference/Global_Objects/Object/propertyIsEnumerable" title="/en-US/docs/JavaScript/Reference/Global_Objects/Object/propertyIsEnumerable">propertyIsEnumerable</a></li>
  <li><a href="/en-US/docs/JavaScript/Reference/Global_Objects/Object/getOwnPropertyNames" title="/en-US/docs/JavaScript/Reference/Global_Objects/Object/getOwnPropertyNames">getOwnPropertyNames</a></li>
  <li><a href="/en-US/docs/JavaScript/Reference/Global_Objects/Object/keys" title="/en-US/docs/JavaScript/Reference/Global_Objects/Object/keys">Object.keys</a></li>
</ul>
<p>&nbsp;</p>
恢复到这个版本