简体   繁体   English

Javascript 绑定高阶函数,输入 onchange 不起作用

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM