摘要:像和使用內置構造函數所創建的對象都會繼承自和的不可枚舉屬性,例如的方法或的方法。循環將遍歷對象本身的所有可枚舉屬性,以及對象從其構造函數原型中繼承的屬性更接近原型鏈中對象的屬性覆蓋原型屬性。在中,非對象參數被強制轉換為對象。
for...in
for...in 循環只遍歷可枚舉屬性。像 Array和 Object使用內置構造函數所創建的對象都會繼承自Object.prototype和String.prototype的不可枚舉屬性,例如 String 的 indexOf()方法或 Object的toString()方法。循環將遍歷對象本身的所有可枚舉屬性,以及對象從其構造函數原型中繼承的屬性(更接近原型鏈中對象的屬性覆蓋原型屬性)。
刪除,添加或者修改屬性
for...in 循環以任意序迭代一個對象的屬性(請參閱delete運算符,了解為什么不能依賴于迭代的表面有序性,至少在跨瀏覽器設置中)。如果一個屬性在一次迭代中被修改,在稍后被訪問,其在循環中的值是其在稍后時間的值。一個在被訪問之前已經被刪除的屬性將不會在之后被訪問。在迭代進行時被添加到對象的屬性,可能在之后的迭代被訪問,也可能被忽略。
通常,在迭代過程中最好不要在對象上進行添加、修改或者刪除屬性的操作,除非是對當前正在被訪問的屬性。這里并不保證是否一個被添加的屬性在迭代過程中會被訪問到,不保證一個修改后的屬性(除非是正在被訪問的)會在修改前或者修改后被訪問,不保證一個被刪除的屬性將會在它被刪除之前被訪問。
數組迭代和 for...in節提示:for...in不應該用于迭代一個 Array,其中索引順序很重要。
數組索引只是具有整數名稱的枚舉屬性,并且與通用對象屬性相同。不能保證for ... in將以任何特定的順序返回索引。for ... in循環語句將返回所有可枚舉屬性,包括非整數類型的名稱和繼承的那些。
因為迭代的順序是依賴于執行環境的,所以數組遍歷不一定按次序訪問元素。因此當迭代訪問順序很重要的數組時,最好用整數索引去進行for循環(或者使用 Array.prototype.forEach() 或 for...of 循環)。
僅迭代自身的屬性節如果你只要考慮對象本身的屬性,而不是它的原型,那么使用 getOwnPropertyNames() 或執行 hasOwnProperty() 來確定某屬性是否是對象本身的屬性(也能使用propertyIsEnumerable)。或者,如果你知道不會有任何外部代碼干擾,您可以使用檢查方法擴展內置原型。
示例下面的函數接受一個對象作為參數。被調用時迭代傳入對象的所有可枚舉屬性然后返回一個所有屬性名和其對應值的字符串。
var obj = {a:1, b:2, c:3};
for (var prop in obj) {
console.log("obj." + prop + " = " + obj[prop]);
}
// Output:
// "obj.a = 1"
// "obj.b = 2"
// "obj.c = 3"
下面的函數說明了hasOwnProperty()的用法:繼承的屬性不顯示。
var triangle = {a: 1, b: 2, c: 3};
function ColoredTriangle() {
this.color = "red";
}
ColoredTriangle.prototype = triangle;
var obj = new ColoredTriangle();
for (var prop in obj) {
if (obj.hasOwnProperty(prop)) {
console.log(`obj.${prop} = ${obj[prop]}`);
}
}
// Output:
// "obj.color = red"
用于獲取對象自身所有的可枚舉的屬性值,但不包括原型中的屬性,然后返回一個由屬性名組成的數組。注意它同for..in一樣不能保證屬性按對象原來的順序輸出。
復制代碼
// 遍歷數組
var colors = ["red", "green", "blue"];
colors.length = 10;
colors.push("yellow");
Array.prototype.demo = function () {};
Object.keys(colors); // ["0", "1", "2", "10"]
// 遍歷對象
function Person(name, age) {
this.name = name;
this.age = age;
}
Person.prototype.demo = function() {};
var jenemy = new Person("jenemy", 25);
Object.keys(jenemy); // ["name", "age"]
復制代碼
注意在 ES5 環境,如果傳入的參數不是一個對象,而是一個字符串,那么它會報 TypeError。在 ES6 環境,如果傳入的是一個非對象參數,內部會對參數作一次強制對象轉換,如果轉換不成功會拋出 TypeError。
復制代碼
// 在 ES5 環境
Object.keys("foo"); // TypeError: "foo" is not an object
// 在 ES6 環境
Object.keys("foo"); // ["0", "1", "2"]
// 傳入 null 對象
Object.keys(null); // Uncaught TypeError: Cannot convert undefined or null to object
// 傳入 undefined
Object.keys(undefined); // Uncaught TypeError: Cannot convert undefined or null to object
復制代碼
由于Object.keys()為ES5上的方法,因此對于ES5以下的環境需要進行polyfill
復制代碼
// From https://developer.mozilla.org...
if (!Object.keys) {
Object.keys = (function() {
"use strict"; var hasOwn = Object.prototype.hasOwnProperty, hasDontEnumBug = !({ toString: null }).propertyIsEnumerable("toString"), dontEnums = [ "toString", "toLocaleString", "valueOf", "hasOwnProperty", "isPrototypeOf", "propertyIsEnumerable", "constructor" ], dontEnumsLength = dontEnums.length; return function(obj) { if (typeof obj !== "object" && (typeof obj !== "function" || obj === null)) { throw new TypeError("Object.keys called on non-object"); } var result = [], prop, i; for (prop in obj) { if (hasOwn.call(obj, prop)) { result.push(prop); } } if (hasDontEnumBug) { for (i = 0; i < dontEnumsLength; i++) { if (hasOwn.call(obj, dontEnums[i])) { result.push(dontEnums[i]); } } } return result; }
}) ();
}
Object.getOwnPropertyNames()方法返回一個由指定對象的所有自身屬性的屬性名(包括不可枚舉屬性但不包括Symbol值作為名稱的屬性)組成的數組。
Object.getOwnPropertyNames() 返回一個數組,該數組對元素是 obj自身擁有的枚舉或不可枚舉屬性名稱字符串。 數組中枚舉屬性的順序與通過 for...in 循環(或 Object.keys)迭代該對象屬性時一致。數組中不可枚舉屬性的順序未定義。
var arr = ["a", "b", "c"];
console.log(Object.getOwnPropertyNames(arr).sort()); // ["0", "1", "2", "length"]
// 類數組對象
var obj = { 0: "a", 1: "b", 2: "c"};
console.log(Object.getOwnPropertyNames(obj).sort()); // ["0", "1", "2"]
// 使用Array.forEach輸出屬性名和屬性值
Object.getOwnPropertyNames(obj).forEach(function(val, idx, array) {
console.log(val + " -> " + obj[val]);
});
// 輸出
// 0 -> a
// 1 -> b
// 2 -> c
//不可枚舉屬性
var my_obj = Object.create({}, {
getFoo: {
value: function() { return this.foo; }, enumerable: false
}
});
my_obj.foo = 1;
console.log(Object.getOwnPropertyNames(my_obj).sort()); // ["foo", "getFoo"]
如果你只要獲取到可枚舉屬性,查看Object.keys或用for...in循環(還會獲取到原型鏈上的可枚舉屬性,不過可以使用hasOwnProperty()方法過濾掉)。
下面的例子演示了該方法不會獲取到原型鏈上的屬性:
function ParentClass() {}
ParentClass.prototype.inheritedMethod = function() {};
function ChildClass() {
this.prop = 5;
this.method = function() {};
}
ChildClass.prototype = new ParentClass;
ChildClass.prototype.prototypeMethod = function() {};
console.log(
Object.getOwnPropertyNames(
new ChildClass() // ["prop", "method"]
)
);
只獲取不可枚舉的屬性節
下面的例子使用了 Array.prototype.filter() 方法,從所有的屬性名數組(使用Object.getOwnPropertyNames()方法獲得)中去除可枚舉的屬性(使用Object.keys()方法獲得),剩余的屬性便是不可枚舉的屬性了:
var target = myObject;
var enum_and_nonenum = Object.getOwnPropertyNames(target);
var enum_only = Object.keys(target);
var nonenum_only = enum_and_nonenum.filter(function(key) {
var indexInEnum = enum_only.indexOf(key); if (indexInEnum == -1) { // 沒有發現在enum_only健集中意味著這個健是不可枚舉的, // 因此返回true 以便讓它保持在過濾結果中 return true; } else { return false; }
});
console.log(nonenum_only);
注:Array.filter(filt_func)方法創建一個新數組, 其包含通過所提供函數實現的測試的所有元素。
提示節
在 ES5 中,如果參數不是一個原始對象類型,將拋出一個 TypeError 異常。在 ES2015 中,非對象參數被強制轉換為對象 。
Object.getOwnPropertyNames("foo");
// TypeError: "foo" is not an object (ES5 code)
Object.getOwnPropertyNames("foo");
// ["length", "0", "1", "2"] (ES2015 code)
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/103498.html
摘要:簡單說就是一個有一個函數,這個函數執行的返回值一定是一個對象,對象有兩個屬性標記迭代是否結束,標記這次迭代的結果值。 引言 遍歷對象是平常工作中很常見的一個操作,幾乎是日常操作,但是遍歷對象真的是一件很容易的事情么,顯然不是的。 常用的方式 for...in for (variable in object) {...} 這個是一個很常見的用法,相信每個人順手都可以寫出來。但是這里需要主...
摘要:對于每個枚舉的屬性,部分都會被執行。被迭代枚舉的對象。三對數組的每個元素執行一次提供的函數。沒有辦法終止會跳出循環,除了拋出一個異常。當到達包含值的項時,整個數組的第一個項被移除了,這導致所有剩下的項前移了一個位置。 showImg(https://segmentfault.com/img/remote/1460000015236979?w=1776&h=1080); 前言 初學Jav...
摘要:但實例化該構造函數仍然得到的是的實例。或者,為了避免在所有查找屬性的地方都插入這段樣本代碼,我們可以將該模式抽象到的構造函數中。該構造函數封裝了所有在單一數據類型定義中編寫健壯字典的技術細節。 參考書籍:《Effective JavaScript》 數組和字典 對象是JavaScript中最萬能的數據結構。取決于不同的環境,對象可以表示一個靈活的鍵值關聯記錄,一個繼承了方法的面向對象數...
摘要:等內置的方法和屬性都是不可枚舉的北京北京可以遍歷可枚舉但對象,包括不是它本身但存在于原型鏈上的屬性。北京循環可迭代對象循環可迭代對象包括,,,,,類數組的對象比如對象對象以及生成器對象等。 在JavaScript中,我們經常需要去循環迭代方法操作數組對象等,常見等循環方法有 for、for in、for of、forEach等。 1.for循環 for循環是最基礎常見的一種循環,圓括號...
摘要:語法參數當前遍歷項。遍歷的范圍在第一次調用前就會確定。已刪除的項不會被遍歷到。的是由提出的,目的是作為遍歷所有數據結構的統一方法。不僅可以遍歷數組,還可以遍歷結構,某些類似數組的對象如對象對象,對象,以及字符串。 即使是最簡單的循環,其中也深藏學問 ECMAScript5(es5)有三種for循環 簡單for for in forEach ECMAScript6(es6)新增 fo...
閱讀 2721·2023-04-26 02:28
閱讀 2551·2021-09-27 13:36
閱讀 3123·2021-09-03 10:29
閱讀 2751·2021-08-26 14:14
閱讀 2101·2019-08-30 15:56
閱讀 830·2019-08-29 13:46
閱讀 2609·2019-08-29 13:15
閱讀 454·2019-08-29 11:29