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

时间:2018-07-24 06:02:41

标签: javascript

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

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

无论何时执行该函数,“ CategoryId”都会正确通过,但是“ SubheadingText”会作为事件对象通过,“事件”也会如此。

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

下面的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;
  }
}

3 个答案:

答案 0 :(得分:1)

Bind第一个参数始终将是您要绑定“ this”对象的函数,是分配给该函数所具有的参数的以下值。如果您选中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”。 / p>

编辑:回复评论的问题

  

即使我   将参数绑定到需要按此顺序排列的函数   categoryNavigation.bind(null,categoryId,subheadingText,event)但是   当我定义函数时,参数需要按此顺序排列   categoryNavigation(categoryId,subheadingText,context,event){}是   当参数被重新排列时的预期行为   函数被调用?

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

在您的情况下,您绑定了 null,categoryId,subheadingText,事件。但是,在显示的代码中,仅定义了 categoryId和subheadingText ,但未定义 event 。这意味着从技术上讲,您绑定到那里的事件应该是“未定义的”-但此时可能是代码具有的随机事件值-。另一方面, click确实会返回其自己的“事件”值作为参数,因此最后,在代码中,您会有一个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”参数,因此它是“丢失的”(并在点击时作为“第5个”参数发送)

答案 1 :(得分:0)

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

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

答案 2 :(得分:0)

bind()始终将上下文(this)作为第一个参数,因此其他参数在您的情况下会发生偏移:

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