[英]Javascript binding Higher-order function with input onchange not working
My goal is to call a function with a string argument, calling function will return a function which will receive the event object from html input object, and I want to use the string argument in the second function.我的目标是使用字符串参数调用函数,调用函数将返回一个函数,该函数将从 html 输入对象接收事件对象,我想在第二个函数中使用字符串参数。
const person = { name:'', age:'' }; const regForm = (field) => { console.log('field : ', field); return event => { person[field]=event.target.value; document.getElementById("demo").innerHTML = JSON.stringify(person); } };
<input onchange="regForm('name')"/> <input onchange="regForm('age')"/> <p id="demo"></p>
The issue is your onchange
attribute currently has a string-based value and it is effectively eval
d when the change event is fired.问题是您的onchange
属性当前具有基于字符串的值,并且在触发 change 事件时它实际上是eval
d 。 As @PeterSeliger comments, regForm
simply returns a function.正如@PeterSeliger 评论的那样, regForm
只是返回一个函数。
regForm
could return anything, and so the default change handler makes no assumptions about your answer. regForm
可以返回任何内容,因此默认更改处理程序不会对您的答案做出任何假设。 You maybe be expecting that the returned function would be called with the event, but instead the default handler simply discards the value.您可能期望返回的函数会随事件一起被调用,但默认处理程序只是简单地丢弃该值。
One solution would be to use JavaScript's onchange
property , instead of HTML's onchange
attribute -一种解决方案是使用 JavaScript 的onchange
属性,而不是 HTML 的onchange
属性-
const person = { name:'', age:'' } const regForm = field => event => person[field] = event.target.value const form = document.forms.sample form.name.onchange = regForm("name") form.age.onchange = regForm("age") form.onsubmit = event => { event.preventDefault() console.log("Submitted", JSON.stringify(person)) }
<form id="sample"> <input name="name" placeholder="enter your name" /> <input name="age" placeholder="enter your age" /> <input type="submit" /> </form>
And since you are familiar with event delegation, ie event.target
, you can remove additional duplication.由于您熟悉事件委托,即event.target
,您可以删除额外的重复项。 Looks like regForm
just kinda disappeared!看起来regForm
只是有点消失了! - ——
const data = {} const form = document.forms.sample form.onchange = event => data[event.target.name] = event.target.value form.onsubmit = event => { event.preventDefault() console.log("Submitted", JSON.stringify(data)) }
<form id="sample"> <input name="name" placeholder="enter your name"><br> <input name="age" placeholder="enter your age"><br> <input name="foo" placeholder="enter your foo"><br> <input name="bar" placeholder="enter your bar"><br> <input type="submit" /> </form>
Output输出
Submitted {"name":"1","age":"2","foo":"3","bar":"4"}
Functions that take other functions as input and/or return other functions as output are called higher-order functions .将其他函数作为输入和/或返回其他函数作为输出的函数称为高阶函数。 There are a variety of terminologies and techniques for dealing with them.有各种各样的术语和技术来处理它们。 For related reading, see What do multiple arrow functions mean ?有关相关阅读,请参阅多箭头函数的含义是什么?
const preventDefault = f => event => ( event.preventDefault() , f(event) ) const logKeypress = event => console.log(event.which) document .querySelector('input[name=foo]') .addEventListener('keydown', preventDefault(logKeypress))
<input name="foo" placeholder="type here to see ascii codes" size="50">
In oder to come close to what the OP might have wished to achieve, one should break down the code into the state-change handling task(, maybe a render task) and the listener-initializing task ...为了接近 OP 可能希望实现的目标,应该将代码分解为状态更改处理任务(可能是渲染任务)和侦听器初始化任务......
const person = { name:'', age:'' }; function renderPersonStateChange(personReference, key, value) { personReference[key] = value; document.body.querySelector('#demo').textContent = JSON.stringify(personReference); } function handleTextInputStateChange(evt) { const elm = evt.currentTarget; const key = elm.name; renderPersonStateChange(person, key, elm.value); } // initialize event listeners document.body.querySelectorAll('input').forEach(elm => elm.addEventListener('change', handleTextInputStateChange, false) );
<input name='name' placeholder="enter person's name"/> <input name='age' placeholder="enter person's age"/> <p> <code> <pre id="demo"> </pre> </code> </p>
If one wishes to bind
the reference that's state should be changed, the above code then slightly alters (only for the change-handler and the event-initialization parts) towards ...如果希望bind
应该更改状态的引用,则上面的代码会稍微更改(仅针对更改处理程序和事件初始化部分)朝向 ...
const person = { name:'', age:'' }; function renderPersonStateChange(personReference, key, value) { personReference[key] = value; document.body.querySelector('#demo').textContent = JSON.stringify(personReference); } function handleStateChangeForBoundPerson(evt) { const personReference = this; const elm = evt.currentTarget; const key = elm.name; renderPersonStateChange(personReference, key, elm.value); } // initialize event listeners document.body.querySelectorAll('input').forEach(elm => elm.addEventListener('change', handleStateChangeForBoundPerson.bind(person), false) );
<input name='name' placeholder="enter person's name"/> <input name='age' placeholder="enter person's age"/> <p> <code> <pre id="demo"> </pre> </code> </p>
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.