ホームページ  >  記事  >  ウェブフロントエンド  >  jsのトラバーサル問題の詳細な説明

jsのトラバーサル問題の詳細な説明

不言
不言オリジナル
2018-04-10 16:55:041382ブラウズ

この記事で共有する内容は、js のトラバーサル問題の詳細な説明に関するもので、必要な友人は参照できます

JavaScript のオブジェクトの属性。

    データプロパティ
  • アクセサープロパティの2種類に分かれています。 特定のコンテキストに従って、属性は、

  • プロトタイプ属性
  • インスタンス属性に分類できます。

  • プロトタイプ属性
  • は、オブジェクトのプロトタイプprototypeで定義された属性であり、prototype 中的属性,

  • 实例属性 一方面来自构造的函数中,然后就是构造函数实例化后添加的新属性。

js的枚举

JavaScript中遍历一个对象的属性并不太简单,主要有两个原因:

  • JavaScript中的对象通常都处在某个原型链中,它会从一个或多个的上层原型上继承一些属性

  • JavaScript中的属性不光有值,它还有一些除了值以外的其他特性,其中一个影响属性遍历的特性就是Enumerable(一个属性描述符) ,如果该值为 true ,则这个属性是可枚举的,否则反之

属性描述符
  • 属性描述符 主要有两种形式:数据描述符存取描述符

  • 使用Object.getOwnPropertyDescriptorObject.getOwnPropertyDescriptors两个方法获取对象的属性描述符

var obj = {
  name: '10',
  _age: 25,
  get age(){
    return this._age;
  },
  set age(age){
    if(age<1){
      throw new Error(&#39;Age must be more than 0&#39;);
    }else{
      this._age = age;
    }
  }
};

var des = Object.getOwnPropertyDescriptors(obj);
console.log(des);
/**
 * des: {
 *  name: {
 *    configurable: true,
 *    enumerable: true,
 *    value: "10",
 *    writable: true,
 *    __proto__: Object
 *  },
 *  _age: {
 *    configurable: true,
 *    enumerable: true,
 *    value: 25,
 *    writable: true,
 *    __proto__: Object
 *  },
 *  age: {
 *    configurable: true,
 *    enumerable: true,
 *    get: f age(),
 *    set: f age(age),
 *    __proto__: Object
 *  },
 *  __proto__: Object
 * }
*/
value

该属性的值(仅针对数据属性描述符有效)

writable

writable属性设置为false时,该属性被称为“不可写”。它不能被重新分配。

get

获取该属性的访问器函数(getter)。如果没有访问器, 该值为undefined。(仅针对包含访问器或设置器的属性描述有效)

set

获取该属性的设置器函数(setter)。 如果没有设置器, 该值为undefined。(仅针对包含访问器或设置器的属性描述有效)

configurable

configurable特性表示对象的属性是否可以被删除,以及除writable特性外的其他特性是否可以被修改。

enumerable

enumerable定义了对象的属性是否可以在 for...in 循环和 Object.keys() 中被枚举。

  • name、_age拥有 'configurable''enumerable''value''writable'四个属性描述符,统称数据描述符

  • age拥有'configurable''enumerable''get''set'四个属性描述符,统称存取描述符

    インスタンス属性
は、構築された関数から取得され、次にコンストラクターから取得されます。インスタンス化後に新しいプロパティが追加されました。
属性記述子
属性記述子は主に 2 つあります。形式: データ記述子 および アクセス記述子
var Animal = function({name=&#39;none&#39;, age=3, weight=80}={}){
  this.name = name;
  this.age = age;
  this.weight = weight;
}

Animal.prototype = {
  color: &#39;red&#39;
}

var dog = new Animal()

// 将weight属性设置为 不可枚举
Object.defineProperty(dog, &#39;weight&#39;, {
  enumerable: false
})

for(let i in dog){
  console.log(n);
}

//原型链上的color同样被遍历出来了,并且由于weight属性被设置成了enumerable:false,所以不可被遍历
//name 
//age 
//color
value
writable
get
set
configurable
configurable 属性は、オブジェクトの属性を削除できるかどうかを示します (writable を除く) code> プロパティ以外のプロパティを変更できるかどうか。
enumerable
分類
js 列挙 JavaScript でオブジェクトのプロパティをトラバースすることは、主に 2 つの理由により、それほど単純ではありません: JavaScript のオブジェクトは通常、特定のプロトタイプ チェーン内にあり、いくつかのプロパティを継承することから始まります。または複数の上位層プロトタイプから JavaScript のプロパティには値があるだけでなく、値以外の機能もあります。プロパティのトラバーサルに影響を与える機能の 1 つは Enumerable(属性記述子) です。 )、値が true の場合、この属性は列挙可能です。それ以外の場合、
Object.getOwnPropertyDescriptor メソッドと Object.getOwnPropertyDescriptors メソッドを使用して、オブジェクトの プロパティ記述子 を取得します。 この属性の値 (データ属性記述子にのみ有効) writable 属性がに設定されている場合false の場合、プロパティは「書き込み不可」であると言われます。再割り当てはできません。 この属性のアクセサー関数 (getter) を取得します。アクセサーがない場合、値は unknown になります。 (アクセサーまたはセッターを含むプロパティ記述にのみ有効) プロパティのセッター関数 (setter) を取得します。 セッターがない場合、値は unknown になります。 (アクセサーまたはセッターを含む属性の説明にのみ有効)
enumerable は、オブジェクトのプロパティを for...in ループと Object.keys で使用できるかどうかを定義します。 () code> が列挙されます。 name と _age には 'configurable''enumerable''value''writable' があります。 > >データ記述子 ageと総称される4つの属性記述子には、'configurable''enumerable'があります。 >' get''set' の 4 つの属性記述子。総称して アクセス記述子 と呼ばれます
🎜'構成可能'🎜 🎜 '列挙可能'🎜🎜'値'🎜🎜'書き込み可能'🎜🎜'get'🎜🎜'set'🎜🎜🎜🎜🎜🎜データ記述子🎜🎜はい🎜🎜はい🎜🎜はい🎜 🎜はい🎜🎜いいえ🎜🎜いいえ🎜🎜🎜🎜アクセス記述子🎜🎜はい🎜🎜はい🎜🎜いいえ🎜🎜いいえ🎜🎜はい🎜🎜はい🎜🎜🎜🎜

对象的属性描述符,可以通过Object.definePropertyObject.defineProperties来修改(configurabletrue的条件下)

常用的遍历方法

for...in...遍历

  • 遍历自身及原型链上所有可枚举的属性

  • 使用 for...in 循环遍历对象属性时返回的属性会因为各个 浏览器不同 导致对象属性遍历的顺序有可能不是当初构建时的顺序。

Chrome Opera 的 JavaScript 解析引擎遵循的是新版 ECMA-262 第五版规范。因此,使用 for-in 语句遍历对象属性时遍历书序并非属性构建顺序。而 IE6 IE7 IE8 Firefox Safari 的 JavaScript 解析引擎遵循的是较老的 ECMA-262 第三版规范,属性遍历顺序由属性构建的顺序决定。
for-in 语句无法保证遍历顺序,应尽量避免编写依赖对象属性顺序的代码。如果想顺序遍历一组数据,请使用数组并使用 for 语句遍历。
var Animal = function({name=&#39;none&#39;, age=3, weight=80}={}){
  this.name = name;
  this.age = age;
  this.weight = weight;
}

Animal.prototype = {
  color: &#39;red&#39;
}

var dog = new Animal()

// 将weight属性设置为 不可枚举
Object.defineProperty(dog, &#39;weight&#39;, {
  enumerable: false
})

for(let i in dog){
  console.log(n);
}

//原型链上的color同样被遍历出来了,并且由于weight属性被设置成了enumerable:false,所以不可被遍历
//name 
//age 
//color

for...of遍历

一个数据结构只要部署了Symbol.iterator属性,就被视为具有 iterator 接口,就可以用for...of循环遍历它的成员。也就是说,for...of循环内部调用的是数据结构的Symbol.iterator方法。

for...of循环可以使用的范围包括数组、SetMap 结构、某些类似数组的对象(比如arguments对象、DOM NodeList 对象)、Generator 对象,以及字符串。

如果不太清楚iterator,请去看看阮一峰大神的这篇文章,里面关于for...of以及iterator都讲的非常详细!

其实for...offor...in都是迭代一些东西,它们之间的主要区别在于它们的迭代方式。

  • for...in语句以原始插入顺序迭代对象的可枚举属性。

  • for...of 语句遍历可迭代对象定义要迭代的数据。

请仔细看以下实例,理解其中的区别

Object.prototype.objCustom = function() {}; 
Array.prototype.arrCustom = function() {};

let iterable = [3, 5, 7];
iterable.foo = &#39;hello&#39;;

for (let i in iterable) {
  console.log(i); //  0, 1, 2, "foo", "arrCustom", "objCustom"
}

for (let i in iterable) {
  if (iterable.hasOwnProperty(i)) {
    console.log(i); //  0, 1, 2, "foo"
  }
}

for (let i of iterable) {
  console.log(i); //  3, 5, 7
}
Object.prototype.objCustom = function() {};
Array.prototype.arrCustom = function() {}; 

let iterable = [3, 5, 7]; 
iterable.foo = &#39;hello&#39;;

在这段代码里面,由于继承和原型链,对象iterable继承属性objCustomarrCustom

for (let i in iterable) {
  console.log(i); // 0, 1, 2, "foo", "arrCustom", "objCustom" 
}

在这段代码里面,此循环仅以原始插入顺序记录iterable 对象的可枚举属性。它不记录数组元素3, 5, 7hello,因为这些不是枚举属性。但是它记录了数组索引以及arrCustomobjCustom(为何记录arrCustomobjCustom在本文for...in里面有讲过)。

for (let i in iterable) {
  if (iterable.hasOwnProperty(i)) {
    console.log(i); //  0, 1, 2, "foo"
  }
}

hasOwnProperty()用来检查找到的枚举属性是不是对象自己的(即是不是继承的)

for (let i of iterable) {
  console.log(i); //  3, 5, 7 
}

该循环迭代并记录iterable作为可迭代对象定义的迭代值,这些是数组元素 3, 5, 7,而不是任何对象的属性。

Object.keys遍历

Object.keys() 方法会返回一个由一个给定对象的自身可枚举属性组成的数组,数组中属性名的排列顺序和使用 for...in 循环遍历该对象时返回的顺序一致 (两者的主要区别是 一个 for-in 循环还会枚举其原型链上的属性)。

Object.getOwnPropertyNames()遍历

Object.getOwnPropertyNames()方法返回一个由指定对象的所有自身属性的属性名(包括不可枚举属性但不包括Symbol值作为名称的属性)组成的数组,此方法不会获取原型链上的属性。

var Animal = function({name=&#39;&#39;, age=1, weight=70}={}){
  this.name = name;
  this.age = age;
  this.weight = weight;
}

Animal.prototype = {
  type: &#39;Animal&#39;
}

var dog = new Animal()

// 将height属性设置为 不可枚举
Object.defineProperty(dog, &#39;weight&#39;, {
  enumerable: false
})

var keys = Object.getOwnPropertyNames(dog);
console.log(keys)
// [&#39;name&#39;, &#39;age&#39;, &#39;weight&#39;]

结语

这篇文章希望能让大家更加理解js中的遍历,写的不好多多见谅并指出!

相关推荐:

实例详解AngularJS遍历获取数组元素

JS遍历对象属性的方法示例

JS遍历页面所有对象属性及实现方法

以上がjsのトラバーサル問題の詳細な説明の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。