prototype
中的属性,JavaScript中遍历一个对象的属性并不太简单,主要有两个缘由:es6
Enumerable
(一个属性描述符) ,若是该值为 true
,则这个属性是可枚举的,不然反之属性描述符
主要有两种形式:数据描述符
和存取描述符
。Object.getOwnPropertyDescriptor
与 Object.getOwnPropertyDescriptors
两个方法获取对象的属性描述符
。var obj = { name: '10', _age: 25, get age(){ return this._age; }, set age(age){ if(age<1){ throw new Error('Age must be more than 0'); }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 * } */
该属性的值(仅针对数据属性描述符有效)数组
当writable
属性设置为false
时,该属性被称为“不可写”。它不能被从新分配。浏览器
获取该属性的访问器函数(getter
)。若是没有访问器, 该值为undefined
。(仅针对包含访问器或设置器的属性描述有效)数据结构
获取该属性的设置器函数(setter
)。 若是没有设置器, 该值为undefined
。(仅针对包含访问器或设置器的属性描述有效)函数
configurable
特性表示对象的属性是否能够被删除,以及除writable
特性外的其余特性是否能够被修改。this
enumerable
定义了对象的属性是否能够在 for...in
循环和 Object.keys()
中被枚举。prototype
'configurable'
、'enumerable'
、'value'
、'writable'
四个属性描述符,统称数据描述符
'configurable'
、'enumerable'
、'get'
、'set'
四个属性描述符,统称存取描述符
分类 | 'configurable' | 'enumerable' | 'value' | 'writable' | 'get' | 'set' |
---|---|---|---|---|---|---|
数据描述符 | yes | yes | yes | yes | no | no |
存取描述符 | yes | yes | no | no | yes | yes |
对象的属性描述符,能够经过Object.defineProperty
和Object.defineProperties
来修改(configurable
为true
的条件下)code
for...in...
遍历Chrome Opera 的 JavaScript 解析引擎遵循的是新版 ECMA-262 第五版规范。所以,使用 for-in 语句遍历对象属性时遍历书序并不是属性构建顺序。而 IE6 IE7 IE8 Firefox Safari 的 JavaScript 解析引擎遵循的是较老的 ECMA-262 第三版规范,属性遍历顺序由属性构建的顺序决定。
for-in 语句没法保证遍历顺序,应尽可能避免编写依赖对象属性顺序的代码。若是想顺序遍历一组数据,请使用数组并使用 for 语句遍历。
var Animal = function({name='none', age=3, weight=80}={}){ this.name = name; this.age = age; this.weight = weight; } Animal.prototype = { color: 'red' } var dog = new Animal() // 将weight属性设置为 不可枚举 Object.defineProperty(dog, 'weight', { 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
循环可使用的范围包括数组、Set
和 Map
结构、某些相似数组的对象(好比arguments对象、DOM NodeList 对象)、Generator 对象,以及字符串。继承
若是不太清楚iterator
,请去看看阮一峰大神的这篇文章,里面关于for...of
以及iterator
都讲的很是详细!
其实for...of
和for...in
都是迭代一些东西,它们之间的主要区别在于它们的迭代方式。
for...in
语句以原始插入顺序迭代对象的可枚举属性。for...of
语句遍历可迭代对象定义要迭代的数据。请仔细看如下实例,理解其中的区别
Object.prototype.objCustom = function() {}; Array.prototype.arrCustom = function() {}; let iterable = [3, 5, 7]; iterable.foo = 'hello'; 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 = 'hello';
在这段代码里面,因为继承和原型链,对象iterable
继承属性objCustom
和arrCustom
。
for (let i in iterable) { console.log(i); // 0, 1, 2, "foo", "arrCustom", "objCustom" }
在这段代码里面,此循环仅以原始插入顺序记录iterable
对象的可枚举属性。它不记录数组元素3, 5, 7
或hello
,由于这些不是枚举属性。可是它记录了数组索引以及arrCustom
和objCustom
(为什么记录arrCustom
和objCustom
在本文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='', age=1, weight=70}={}){ this.name = name; this.age = age; this.weight = weight; } Animal.prototype = { type: 'Animal' } var dog = new Animal() // 将height属性设置为 不可枚举 Object.defineProperty(dog, 'weight', { enumerable: false }) var keys = Object.getOwnPropertyNames(dog); console.log(keys) // ['name', 'age', 'weight']
这篇文章但愿能让你们更加理解js中的遍历,写的很差多多见谅并指出!