摘要:而的解析引擎遵循的是較老的第三版規范,屬性遍歷順序由屬性構建的順序決定。將屬性設置為不可枚舉結語這篇文章希望能讓大家更加理解中的遍歷,寫的不好多多見諒并指出
實例屬性和原型屬性
JavaScript中對象的屬性分為兩種: 數據屬性 和 訪問器屬性 。
根據具體的上下文環境的不同,又可以將屬性分為: 原型屬性 和 實例屬性 。
原型屬性 是定義在對象的原型prototype 中的屬性,
實例屬性 一方面來自構造的函數中,然后就是構造函數實例化后添加的新屬性。
js的枚舉JavaScript中遍歷一個對象的屬性并不太簡單,主要有兩個原因:
JavaScript中的對象通常都處在某個原型鏈中,它會從一個或多個的上層原型上繼承一些屬性
JavaScript中的屬性不光有值,它還有一些除了值以外的其他特性,其中一個影響屬性遍歷的特性就是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特性外的其他特性是否可以被修改。
enumerable定義了對象的屬性是否可以在 for...in 循環和 Object.keys() 中被枚舉。
name、_age擁有 "configurable"、"enumerable"、"value"、"writable"四個屬性描述符,統稱數據描述符
age擁有"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的條件下)
常用的遍歷方法 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="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 //colorfor...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中的遍歷,寫的不好多多見諒并指出!
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/94110.html
摘要:和的作用一樣,區別在于寫法語法對象對象作用判斷對象是否在對象的原型鏈上語法對象構造函數作用判斷構造函數的屬性是否在對象的原型鏈上,如果在,就返回屬性是否可枚舉用于檢查給定的屬性是否能夠使用語句。 ## javascript對象原型成員詳解 ## ECMAScript 中的對象就是一組數據和功能的集合,對象可以通過 new 操作符后跟要創建的對象名稱來...
摘要:和數組遍歷方法詳解在中常用的種數組遍歷方法原始的循環語句數組對象內置方法數組對象內置方法數組對象內置方法數組對象內置方法數組對象內置方法數組對象內置方法數組對象內置方法數組對象內置方法循環語句中新增加了一種循環語句三種數組循環示例如下原始循 ES5和ES6數組遍歷方法詳解 在ES5中常用的10種數組遍歷方法: 1、原始的for循環語句2、Array.prototype.forEach數...
摘要:創建數組數組字面量數組構造函數參數為數組建議使用數組字面量方式,性能好,代碼少,簡潔,畢竟代碼少。數組判斷方法用來判斷某個值是否為。的這是最簡潔最直接的遍歷數組元素的語法。把數組轉換為本地數組,并返回結果。 前端學習:前端教程&開發模塊化/規范化/工程化/優化&工具/調試&值得關注的博客/Git&面試-前端資源匯總 歡迎提issues斧正:數組&數組方法使用詳解 Array對象 之前一...
摘要:個人前端文章整理從最開始萌生寫文章的想法,到著手開始寫,再到現在已經一年的時間了,由于工作比較忙,更新緩慢,后面還是會繼更新,現將已經寫好的文章整理一個目錄,方便更多的小伙伴去學習。 showImg(https://segmentfault.com/img/remote/1460000017490740?w=1920&h=1080); 個人前端文章整理 從最開始萌生寫文章的想法,到著手...
閱讀 2083·2021-11-15 17:57
閱讀 747·2021-11-11 16:54
閱讀 2595·2021-09-27 13:58
閱讀 4084·2021-09-06 15:00
閱讀 955·2021-09-04 16:45
閱讀 3511·2019-08-30 15:56
閱讀 1789·2019-08-30 15:53
閱讀 1620·2019-08-30 14:12