attribute 和 property 的区别

浏览器在解析 HTML 时会创建对应的 Element 元素对象,这个对象将包含 acceptaccesskeyaltattributes 等属性。Properties 指的是这个 Element 对象的所有属性,而 Attributes 指的是 Element 对象的 attributes 属性。

1
<input type='text' value=''>

attributes

attributes(特性),是一个特性节点。每个 DOM 元素都有一个对应的 attributes 属性,返回该元素所有特性节点的实时集合。该集合是一个 NamedNodeMap 对象,是一个类数组对象。更确切的说,attributes 是字符串形式的键值对,每一对键值对应一个属性节点。

操作

  • 添加或修改

    1
    2
    3
    4
    5
    6
    7
    // 方法一
    element.setAttributes(key, value);

    // 方法二
    const $attr = document.createAttribute(key);
    $attr.value = value;
    element.attributes.setNamedItem($attr);
  • 获取

    1
    2
    3
    4
    5
    // 方法一
    element.getAttribute(key);

    // 方法二
    element.attributes.getNamedItem(key).value;
  • 移除

    1
    2
    3
    4
    5
    // 方法一
    element.removeAttribute(key);

    // 方法二
    element.attributes.removeNamedItem(key);

properties

properties(属性)属于 DOM,DOM 其实就是 JS 中的 Object。因此,可以像操作普通的 JS 对象一个操作 property。Properties 也是键值对,但值可以是任意类型。

操作

  • 新增或修改

    1
    element.key = value;
  • 获取

    1
    const value = element.key;
  • 删除

    1
    delete element.key;

关联

  • 对于非自定义的 attribute,如 idclasstitlechecked 等,attributes 与 properties 都是 1:1 映射的,只有一方改变,另一方也会一起变

    • idtitle

      1
      2
      3
      4
      5
      6
      <div id='test' class='button' foo='1'></div>

      const $div = document.getElementById('test');

      $div.id; // test
      $div.getAttribute('id'); // test
    • classfor

      classfor 是 JS 中的保留字,通过 property 方式操作时需要使用 classNamehtmlFor

      1
      2
      3
      4
      5
      6
      7
      <label for='name' class='mr10'></label>

      const $label = docuemnt.querySelector('label');

      $label.getAttribute('for');
      $label.attributes.getNamedItem('for');
      $label.htmlFor;
    • checkedreadOnlymultiple

      对于 Boolean 类型的 attribute,通过 attribute 方式获取的是设置的值,通过 property 方式 获取的是对应的 Boolean 值;另外,只有存在该类型属性节点,对应的 property 的值就是 true。

      另外,attribute 只是初始化 DOM 状态,之后通过 attribute 方式修改 DOM 状态无法生效,只有通过 property 方式才能生效。

      1
      2
      3
      4
      5
      6
      <input type='radio' checked='checked' id='raido'>

      const $radio = document.getElementById('radio');

      $radio.getAttribute('checked'); // checked
      $radio.checked; // true
    • type

      对于 type 这种 attribute 节点,虽然也是 1:1 映射,但是 type 值有限制,只能是有效值;通过 attribute 方式可以设置无效的 type 值,但通过 property 方式读取时,读取的是会默认值(text);通过 property 方式设置无效的 type 值,会报语法错误。

      1
      2
      3
      4
      5
      6
      7
      8
      9
      <input type='text' value='' id='input' />

      const $input = document.getElementById('input');

      $input.setAttribute('type', 'a');
      $input.type; // text

      // Uncaught SyntaxError: Invalid or unexpected token
      $input.type = 'a';
    • href

      对于 href 等路径相关的 attribute 属性,两种方式取值不相同,attribute 方式获取的是字面值,property 方式获取的是计算后的完整路径

      1
      2
      3
      4
      5
      6
      <a id='a' href='#'>link</a>

      const $a = document.getElementById('a');

      $a.href; // 完整路径
      $a.getAttribute('href'); // '#'

  • value attribute 与 value property 并非 1:1 映射;如果在 input 中进行输入或者通过 property 方式改变 value,改变的是 value property,但 value attribute 并不会对应的发生改变;同理,通过 attribute 方式改变 value,对应的 value property 也不会发生改变

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    <input type='text' value='' id='input' />

    const $input = document.getElementById('input');

    $input.value = '1';
    $input.getAttribute('value'); // ''
    $input.defaultValue; // ''

    $input.setAttribute('value', '2');
    $input.value; // '1'
    $input.defaultValue; // '2'
  • 部分 attribute 没有对应的 property,如:colspan

  • 部分 property 也没有对应的 attributes,如:textContent

  • 自定义 attribute

    对于自定义 attribute 属性,一般情况下无法通过 property 方式获取;如果自定义的 attribute 属性名是以 data- 开头,则可以通过 property 方式获取。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    <input type='text' id='input' value='' data-type='text'>

    const $input = document.getElementById('input');

    $input.getAttribute('data-type'); // 'text'
    $input['data-type']; // undefined
    $input.dataset.type; // 'text'

    $input.setAttribute('data-type', 'number');
    $input.dataset.type; // 'number'
  • 自定义 property

    对于自定义 property,无法通过 attribute 方式获取。

    1
    2
    3
    4
    5
    6
    <input type='text' id='input' value='' data-type='text'>

    const $input = document.getElementById('input');

    $input['data-type'] = 'number';
    $input.getAttribute('data-type'); // null

参考