繁体   English   中英

JavaScript绑定函数未按预期传递参数

[英]Javascript bind function not passing arguments as expected

我希望有人可以从事件侦听器将多个参数传递给函数时解释绑定行为。 我一直找不到能解释它的东西。

我有一个按钮,可在onclick上执行JS函数。 设置事件侦听器时,我试图将一些参数绑定到该函数。

每当执行该函数时,“ CategoryId”都会正确通过,但“ SubheadingText”将作为事件对象通过,“ event”也将通过。

请问有没有理由这样做? 第二个事件对象来自哪里?

下面的JS代码

小提琴可在这里找到: http : //jsfiddle.net/8w5geqxj/12/

var faqCategoryButtons = document.getElementsByClassName('button-faq-cat')[0];
var categoryId = 'mycatid';
var subheadingText = 'my cat text';

faqCategoryButtons.addEventListener('click', categoryNavigation.bind(categoryId, subheadingText, event));

function categoryNavigation(categoryId, subheadingText, event){
  if (event && event.preventDefault) {
    event.preventDefault();
  } else if (event) {
    event.returnValue = false;
  }
}

绑定第一个参数始终是您要绑定“ ”对象的函数,即分配给函数所具有的参数的以下值。 如果您选中Fiddle ,则单击按钮后,将具有以下值:

this:           "mycatid",
categoryId:    "my cat text"
subheadingText: Event
event:          MouseEvent

因此,为了使代码按预期工作:

var faqCategoryButtons = document.getElementsByClassName('button-faq-cat')[0];
var categoryId = 'mycatid';
var subheadingText = 'my cat text';

faqCategoryButtons.addEventListener('click', categoryNavigation.bind(null, categoryId, subheadingText, event));

function categoryNavigation(categoryId, subheadingText, event){
  if (event && event.preventDefault) {
    event.preventDefault();
  } else if (event) {
    event.returnValue = false;
  }
}

在这种情况下,我添加了一个额外的“ null”使其起作用,因为我了解您没有使用“ this”,但是,您可以添加任何值,它将变成函数的“ this”。

编辑:回复评论的问题

即使将参数绑定到函数时,它看起来也应该按以下顺序categoryNavigation.bind(null,categoryId,subheadingText,event)定义,但是当我定义函数时,参数就必须按照此次序categoryNavigation(categoryId ,subheadingText,上下文,事件){}是调用该函数时参数重新排列的预期行为吗?

就像我在回答中提到的那样,进行绑定时的第一个参数是“ this”,即所谓的上下文,即函数执行的真正“重排”。 除此之外,参数的顺序是相同的。 但是,需要考虑的一点是,“绑定”将返回具有已“绑定”到旧函数的那些参数的函数,应再次调用它。

在您的情况下,您绑定了null,categoryId,subheadingText和event 但是,在所示的代码中, 定义了categoryId和subheadingText ,但未定义事件 这意味着从技术上讲,您绑定到那里的事件应该是“未定义的”-但此时可能是代码具有的随机事件值-。 另一方面, click确实会返回其自己的“ event”值作为参数 ,因此,最后,在代码中,您将获得一个click事件,该事件将调用您预先绑定的函数“ null,cathegoryId,subheadingText,”和当事件发生时,将调用该事件并将click事件放置在那里(但是没有空间放置该事件,因为所有参数都已定义)

换句话说,您的代码(在此绑定修复程序之后)

var faqCategoryButtons = document.getElementsByClassName('button-faq-cat')[0];
var categoryId = 'mycatid';
var subheadingText = 'my cat text';

faqCategoryButtons.addEventListener('click', categoryNavigation.bind(null, categoryId, subheadingText, event));

function categoryNavigation(categoryId, subheadingText, event){
  if (event && event.preventDefault) {
    event.preventDefault();
  } else if (event) {
    event.returnValue = false;
  }
}

等效于:

var faqCategoryButtons = document.getElementsByClassName('button-faq-cat')[0];
var categoryId = 'mycatid';
var subheadingText = 'my cat text';

function categoryNavigationBinded(eventForTheclick){
    const categoryNavigationThis = cagegoryNavigation.bind(null); // in the fixed code, categoryNavigation has its "this = null" 
    categoryNavigationThis(categoryId, subheadingText, event) // note that event is not defined, and for what I know is "undefined"
}

faqCategoryButtons.addEventListener('click', categoryNavigationBinded);

function categoryNavigation(categoryId, subheadingText, event){
  if (event && event.preventDefault) {
    event.preventDefault();
  } else if (event) {
    event.returnValue = false;
  }
}

对于代码,我假设您想执行以下操作:

var faqCategoryButtons = document.getElementsByClassName('button-faq-cat')[0];
var categoryId = 'mycatid';
var subheadingText = 'my cat text';

function categoryNavigationBinded(eventForTheclick){
    const categoryNavigationThis = cagegoryNavigation.bind(null); // in the fixed code, categoryNavigation has its "this = null" 
    categoryNavigationThis(categoryId, subheadingText, eventForTheclick) // here I am placing the click's event into the 3rd categoryNavigation parameter
}

faqCategoryButtons.addEventListener('click', categoryNavigationBinded);

function categoryNavigation(categoryId, subheadingText, event){
  if (event && event.preventDefault) {
    event.preventDefault();
  } else if (event) {
    event.returnValue = false;
  }
}

那将是“扩展”版本,所以我可以解释会发生什么,而使用绑定的“简短版本”与在代码中所做的相同:

var faqCategoryButtons = document.getElementsByClassName('button-faq-cat')[0];
var categoryId = 'mycatid';
var subheadingText = 'my cat text';

faqCategoryButtons.addEventListener('click', categoryNavigation.bind(null, categoryId, subheadingText)); // the last parameter, "event", will be the parameter the click will place its own event

function categoryNavigation(categoryId, subheadingText, event){
  if (event && event.preventDefault) {
    event.preventDefault();
  } else if (event) {
    event.returnValue = false;
  }
}

TLDR :除了第一个“ this”外,该参数实际上没有在绑定中重新组织,但是在您的代码中,您在真正具有实际事件值之前定义了“ event”参数,因此它被“丢失”(并发送单击时作为“第五个”参数)

开始放置参数,从第二个参数开始:

faqCategoryButtons.addEventListener('click', categoryNavigation.bind(null, categoryId, subheadingText, event));

bind()总是将上下文( this )作为第一个参数,因此其他参数在您的情况下是偏移量:

faqCategoryButtons.addEventListener('click',
  categoryNavigation.bind(
    null, /* <- context */
    categoryId,
    subheadingText,
    event
  )
);

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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