首先,我得想,怎么遍歷window對象的所有屬性。因為window是一個全局對象,所有全局變量都是它的屬性。不過直接用for...in循環(huán)可能會遍歷到很多內(nèi)置屬性和方法,比如document、console這些,可能需要過濾掉一些不可枚舉的或者來自原型的屬性。不過用戶可能希望檢查所有屬性,不管是不是可枚舉的,所以應(yīng)該使用Object.getOwnPropertyNames來獲取所有自身屬性,包括不可枚舉的。
但用戶還提到不只是直接變量,還要遍歷變量下的子元素。比如,如果window有一個屬性a,而a對象又有屬性b,那么也要檢查a.b是否包含creation_id。這看起來像是一個遞歸遍歷的問題。所以需要遞歸地檢查每個對象的屬性。
不過遞歸遍歷可能會有問題,比如循環(huán)引用,比如對象之間相互引用導(dǎo)致無限循環(huán)。所以需要記錄已經(jīng)訪問過的對象,避免重復(fù)遍歷。可以用一個Set或者WeakSet來保存已經(jīng)處理過的對象引用。
接下來,變量名包含“creation_id”的條件,指的是屬性名中包含這個字符串,而不是屬性值。所以需要檢查每個屬性的名稱是否包含該字符串,而不是屬性的值。例如,如果有一個屬性名為“my_creation_id”,那么符合條件,需要輸出這個變量名。
但是如何跟蹤變量名的路徑呢?比如,如果有一個對象window.a.b.c,其中c的屬性名是“creation_id”,那么應(yīng)該輸出完整的路徑,比如“a.b.c”嗎?或者只需要輸出屬性名本身?用戶的需求是輸出變量名,可能是指完整的路徑,但原問題描述沒有明確說明。需要再仔細看問題。
function findAllCreationIdVariables() {
const visited = new WeakSet(); // 用于跟蹤已訪問對象,避免循環(huán)引用
function traverse(obj, path = '') {
if (obj === null || typeof obj !== 'object' && typeof obj !== 'function') {
return;
}
if (visited.has(obj)) return;
visited.add(obj); // 標(biāo)記當(dāng)前對象為已訪問
try {
// 獲取對象的所有自身屬性(包括不可枚舉屬性)
const props = Object.getOwnPropertyNames(obj);
for (const prop of props) {
// 構(gòu)建當(dāng)前屬性的完整路徑
const currentPath = path ? `${path}.${prop}` : prop;
// 檢查屬性名是否包含目標(biāo)字符串
if (prop.includes('creation_id')) {
console.log('發(fā)現(xiàn)變量:', currentPath);
}
try {
// 獲取屬性值(可能拋出異常)
const value = obj[prop];
// 遞歸遍歷子屬性(如果是對象/函數(shù))
traverse(value, currentPath);
} catch (error) {
// 忽略無法訪問的屬性(如安全限制)
}
}
} catch (error) {
// 忽略無法獲取屬性列表的對象(如跨域iframe)
}
}
traverse(window); // 從window對象開始遍歷
}
// 執(zhí)行函數(shù)
findAllCreationIdVariables();