6 mins
property和attribute对比

本文介绍property和attribute对比,详细介绍属性值和特性值之间的区别

下列示例中,我们希望观察两种方式从获取属性值到设置属性值的区别。

<body>
<input type="text" id="input1" class="input11" />
<button id="btn1">设置为riverwood</button>
<button id="btn2">设置为hurstville</button>
<script>
var inputElem1 = document.querySelector('#input1')
console.log("inputElem1.getAttribute('value'):", inputElem1.getAttribute('value'))
console.log('inputElem1.value:', inputElem1.value)
var btn1 = document.querySelector('#btn1')
var btn2 = document.querySelector('#btn2')
btn1.onclick = function () {
console.log('点击btn1')
inputElem1.setAttribute('value', 'riverwood')
console.log("inputElem1.getAttribute('value'):", inputElem1.getAttribute('value'))
console.log('inputElem1.value:', inputElem1.value)
}
btn2.onclick = function () {
console.log('点击btn2')
inputElem1.value = 'hurstville'
console.log("inputElem1.getAttribute('value'):", inputElem1.getAttribute('value'))
console.log('inputElem1.value:', inputElem1.value)
}
</script>
</body>

让我们一步一步拆解。

默认值h2

HTML 属性(Attribute)DOM属性(Property)
是HTML标记中的原始值是DOM对象在内存中的当前值
使用 getAttribute() 方法获取直接通过 .value 访问
只在HTML解析时初始化,修改后不会自动更新对应的DOM属性会随着用户输入而实时变化
<body>
<input type="text" id="input1" class="input11" />
<button id="btn1">设置为riverwood</button>
<button id="btn2">设置为hurstville</button>
<script>
var inputElem1 = document.querySelector('#input1')
console.log("inputElem1.getAttribute('value'):", inputElem1.getAttribute('value')) // inputElem1.getAttribute('value'): null
console.log('inputElem1.value:', inputElem1.value) //inputElem1.value:
</script>
</body>

没有默认值的情况,因为HTML标记中没有value属性,所以inputElem1.getAttribute('value')返回的是null;而inputElem1.value返回的是空字符串,表示当前输入框的值。

如果input元素value属性有默认值,比如我们设置成value="riverwood"

<body>
<input type="text" id="input1" class="input11" value="riverwood" />
<button id="btn1">设置为riverwood</button>
<button id="btn2">设置为hurstville</button>
<script>
var inputElem1 = document.querySelector('#input1')
console.log("inputElem1.getAttribute('value'):", inputElem1.getAttribute('value')) // inputElem1.getAttribute('value'): riverwood
console.log('inputElem1.value:', inputElem1.value) //inputElem1.value: riverwood
</script>
</body>

有默认值的情况下,一个是从HTML标记中读取的初始值,一个是当前DOM对象的value属性值,返回的都是riverwood

点击btn1 btn2按钮 再次点击btn1h2

第一阶段:同步期(点击 btn1)h3

当我们点击 btn1 时,执行了 setAttribute('value', 'riverwood')

// 控制台输出:
"inputElem1.getAttribute('value'):" "riverwood"
"inputElem1.value:" "riverwood"

分析: 此时输入框处于“干净(Clean)”状态。浏览器认为用户尚未介入,因此当我们修改 HTML 特性(Attribute)这一“默认值”时,浏览器会自动同步更新 DOM 属性(Property),输入框显示的内容也随之改变。

第二阶段:决裂期(点击 btn2)h3

紧接着,我们要点击 btn2,执行 inputElem1.value = 'hurstville'

// 控制台输出:
"inputElem1.getAttribute('value'):" "riverwood" // 保持不变
"inputElem1.value:" "hurstville" // 发生了变化

分析: 这一步至关重要!

  1. Property 变了:我们将 DOM 对象的 value 属性直接修改为 hurstville,界面内容也随之更新。
  2. Attribute 没变:可以看到 getAttribute 依然是 riverwood。这说明修改 Property 不会反向同步 Attribute。
  3. 脏值标记(Dirty Value Flag):更重要的是,在这一刻,浏览器内部将该输入框标记为“脏(Dirty)”。这意味着浏览器认为:“用户(或脚本)已经显式接管了当前值,它不再依赖默认值了。”

第三阶段:失效期(再次点击 btn1)h3

现在,我们再次点击 btn1,试图通过 setAttribute 把值改回 riverwood

// 控制台输出:
"inputElem1.getAttribute('value'):" "riverwood" // Attribute 确实是 riverwood
"inputElem1.value:" "hurstville" // !!! Property 依然是 hurstville

分析: 发生了什么?为什么 setAttribute 失效了? 因为此时输入框已经是“脏”的了。一旦 Property 和 Attribute 的同步关系断裂,Attribute(默认值)的修改将不再影响 Property(当前值)。 界面上依然顽固地显示着 hurstville

有图为证

特殊情况:手动输入会发生什么?h2

除了用 JS 修改 .value,还有一个最常见的场景:用户直接在输入框里打字。

假设页面刷新后,我们不点任何按钮,直接在输入框手动输入 hurstville1,然后点击 btn2(代码中打印当前状态),会得到什么结果?

// 1. 手动输入 "hurstville1"
// 此时 Property = "hurstville1", Attribute = null (因为没人设置过)
// 2. 点击 btn2 (执行 input.value = 'hurstville')
// 控制台输出:
"inputElem1.getAttribute('value'):" null
"inputElem1.value:" "hurstville"

这里的机理是: 用户的手动输入等同于修改 Property。 当你敲下第一个字符时,浏览器的“脏值标记”就已经置位了。

  1. getAttribute 返回 null,因为 HTML 标签上从来没有过 value="...",用户打字也不会把字写到 HTML 标签上去。
  2. value 返回 hurstville,因为我们的 btn2 代码把它覆盖了。

总结h2

通过上述实验,我们可以得出一个关键结论:

  • Attribute (setAttribute):本质是设置 defaultValue(默认值)。它只在元素初始化,或者元素处于“干净”状态时,才能影响界面显示。
  • Property (.value):代表 当前值。
  • 铁律:一旦用户操作过输入框,或者脚本修改过 .value,Attribute 和 Property 的同步链接就会永久断开。此时再用 setAttribute 是无法改变输入框内容的。

最佳实践: 作为原生 JS 开发者,除非你需要利用 Attribute 进行 CSS 选择器匹配(如 input[value="abc"]),否则在处理表单值时,请始终优先使用 .value

Comments