使用非匿名函数绑定addEventListener为何无法获取文本框值长度?
嘿,这个问题其实是把事件监听器绑定函数的方式搞混啦,我来给你拆解清楚:
第一种写法的核心问题:你直接调用了函数,而非传递函数引用
先看你的第一段代码:
var first_name = document.getElementById("firstname"); first_name.addEventListener("change", howLong(first_name)); function howLong(first_name) { var p = first_name.value.length; alert("Length of input is " + p); }
这里的howLong(first_name)是立刻执行了这个函数,而不是把函数本身传给addEventListener当回调。
也就是说,当浏览器执行到addEventListener这一行时,howLong就直接跑起来了——这时候用户还没在输入框里填任何内容,first_name.value是空字符串,长度自然是0。更糟的是,howLong没有返回值(默认返回undefined),相当于你给事件监听器传了个undefined,后面用户触发change事件时,根本不会有任何回调执行。
第二种匿名函数写法为什么能工作?
再看你的第二段代码:
var first_name = document.getElementById("firstname"); first_name.addEventListener("change", function(){ var p = first_name.value.length; alert("Length of input is "+p); } );
这里你传给addEventListener的是一个匿名函数的引用,而不是执行它的结果。只有当用户触发change事件(比如输入完离开输入框)时,这个匿名函数才会被调用——这时候输入框里已经有用户输入的内容了,自然能拿到正确的value长度。
想保留命名函数?可以这么改
如果你不想用匿名函数,想保留howLong这个命名函数,有两种靠谱的写法:
- 用匿名函数包裹,在事件触发时再调用
howLong:
var first_name = document.getElementById("firstname"); first_name.addEventListener("change", function(){ howLong(first_name); }); function howLong(el) { var p = el.value.length; alert("Length of input is " + p); }
这样只有事件触发时,才会执行howLong,此时能拿到最新的输入值。
- 利用事件回调的
this指向,不需要额外传参:
var first_name = document.getElementById("firstname"); first_name.addEventListener("change", howLong); // 注意这里不要加括号! function howLong() { var p = this.value.length; // 事件触发时,this就是当前输入框元素 alert("Length of input is " + p); }
事件回调函数执行时,this会自动指向触发事件的DOM元素(也就是这个输入框),所以直接用this就能拿到输入框的value,而且这里传给addEventListener的是howLong函数本身,不是执行结果。
关键总结
addEventListener的第二个参数需要的是函数本身(函数引用),而不是函数执行后的返回值。如果给函数加了括号(),就会立刻执行它,而不是等事件触发再调用。
内容的提问来源于stack exchange,提问作者Stumbler

