【问题标题】:How can I test if a DOM element property is read-only如何测试 DOM 元素属性是否为只读
【发布时间】:2020-08-09 09:21:08
【问题描述】:

这是一个关于使用纯 Javascript(不是 jQuery 等)与 DOM 交互的问题

我的最终目标是收集任何给定 DOM 元素的可写属性的当前值,因此我想跳过该元素的所有不可写属性。

虽然我可以查看规范并创建一个列表,但规范会发生变化,所以我想动态地(并且尽可能高效地)进行。

我已经搜索过,但出现空白,因此欢迎任何建议。

PSEUDOCODE:我需要一种在下面的代码中实现 is_writable(element)->boolean 的方法

let myObject = {};
for (propertyName in HTMLElement) {
    if(is_writable(HTMLElement[propertyName])){
        myObject[propertyName] = HTMLElement[propertyName];
    }
}

【问题讨论】:

  • “元素属性是只读的”是什么意思?来自<input> 类型元素或<textarea> 元素或内容可编辑<div> ???到目前为止您尝试过的代码在哪里?你的 HTML 在哪里?
  • 您能否澄清一下您是指 JS 对象 property 还是在谈论元素 attributes
  • 为了更清楚而编辑了问题

标签: javascript dom propertyinfo


【解决方案1】:

一个属性是否可写可以从它的属性描述符中确定。 您可以使用 Object.getOwnPropertyDescriptor() 获取对象的属性描述符。但是,此函数只会查找对象自身的属性。

因此,我们需要一个函数来搜索对象的原型链,直到找到我们要查找的属性并返回属性描述符:

function findPrototypeProperty(object, propertyName){
    while (object && object.constructor && object.constructor.name !== 'Object'){
        let desc = Object.getOwnPropertyDescriptor(object, propertyName);
        if(desc){
            return desc;
        }
        object = Object.getPrototypeOf(object);
    }
    return null;
}

属性描述符是最多可以包含 6 个值的对象(从 MDN 复制):

value - The value associated with the property (data descriptors only).

writable - true if and only if the value associated with the property may be changed (data descriptors only).

get - A function which serves as a getter for the property, or undefined if there is no getter (accessor descriptors only).

set - A function which serves as a setter for the property, or undefined if there is no setter (accessor descriptors only).

configurable - true if and only if the type of this property descriptor may be changed and if the property may be deleted from the corresponding object.

enumerable - true if and only if this property shows up during enumeration of the properties on the corresponding object. 

首先要做的是检查可写值。如果为真,则该属性是可写的。但是,您还应该检查“值”是否不是函数。

有些属性没有实际值,而是一个 getter 和 setter 函数。如果一个属性有一个 set 函数,它通常也是可写的。

这就是你的 is_writeable 函数的样子:

function is_writeable(object, propertyName){
    let desc = findPrototypeProperty(object, propertyName);
    if(!desc){
        return false;
    }
    if(desc.writable && typeof desc.value !== "function"){
        return true;
    }
    return !!desc.set;
}

结论: 不要这样做。使用列表。

【讨论】:

  • 我想接受这个答案,因为它可以满足我的需要。我同意列表是最好的,但这段代码是生成列表的好方法。
  • 为了生成一个列表,代码可以很好地工作。你只需要注意一些特殊的属性,比如innerHtml 和outerHtml。
【解决方案2】:

使用document.querySelectorAll检查DOM Elements的具体属性

像这样:

document.querySelectorAll('*[readonly]')

将返回具有readonly 属性的所有元素的数组。

【讨论】:

    【解决方案3】:

    一种方法是使用 try/catch:

    const is_writable = (element, propName) => {
      const originalValue = element[propName]
      try {
        element[propName] = 1  // set it to an arbitrary value
      } catch () {
        return false
      }
      element[propName] = originalValue
      return true
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多