如何知道window 对象上有哪些自定义属性?

公司很多项目里,有余各种历史原因,维护代码的人并不一定是写代码的人。有的代码写得不太规范,可能会在window 对象上挂载很多属性。有一天我突然想看看,这个网页的window 对象上到底有哪些自定义属性啊?

网上查了一圈,居然没有找到有相关的查看方法或者是工具。也可能是我搜索的关键字不太对,大家要是有更好的方法欢迎告诉我。

要知道window 上多了哪些属性,目前我有两个思路,

  1. 先确定window上原本有哪些属性,比如定义一个常量列表,[…],然后获取目前window 上的属性,取一个差集,多出来的哪些就是自定义属性。
  2. 如果能获取到一个干净的window对象,两个对象进行diff,也能知道多了哪些属性。

方案一是比较容易想到的,但是并不好,不到万不得已不采用,因为这个方案有比较多的硬伤,首先是麻烦,另外是不好操作,万一不同浏览器属性有差异呢,最后是属性可能随着浏览器更新,之后会增加,难道要一直维护这个常量吗?

所以我还是致力于思考方案二,果然也是有解法的。我想到了了神奇的iframe 元素。iframe里面的内容,其实就是相当于创建了一个和外面隔离的网页,是一个沙盒环境,iframe有自己的window 对象,只要我们获取到这个window,那不就成功获取到干净的window了吗?

只要是同源的iframe,可以使用iframe.contentWindow属性获取window。于是有了下面的这段代码,你可以在浏览器执行看看,就能知道当前页面有多少自定义属性了。目前我已经为自己做成了书签快捷键哈哈。

function getCustomKeys() {
    const iframe = document.createElement("iframe");
    iframe.setAttribute('style','display:none')
    const body=document.getElementsByTagName("body")[0]
    body.appendChild(iframe);
    const newWindow=iframe.contentWindow
    const keys=Object.keys(window)
    const customKeys=[]
    keys.forEach(key=>{
        if(!(key in newWindow)){  // 注意这里要打括号,! 的优先级更高
            customKeys.push(key)
        }
    })
    body.removeChild(iframe)
    return customKeys
}

这里补充一句,Object.keys获取的是对象的自身属性,也就是说,原型链上的属性,是不会获取到的,这样写也是考虑到,大多数挂载在window 上的全球变量,都是window.xxx 这样挂载的,并没有挂载到原型链上,所以使用了Object.keys。如果你需要包括原型链,那边可以使用for…in 语句。

更进一步

目前使用上面的这段代码,可以知道window 上多了哪些自定义属性。但有时候还不够,因为有的函数其实会重写window 的属性,比如:

window.alert=function(...rest){
  console.log('嘿嘿')
  window.alert(...rest)
}

这种情况下,其实不太容易检测当前属性是否被用户改写过,但有的场景其实能判断最好。比如提供仿真js 沙盒、安全检测等。

但我还没想到什么比较好的办法,抛砖引玉一下,欢迎大家留言探讨。

Leave a Comment

电子邮件地址不会被公开。 必填项已用*标注