2013-04-01 162 views
1

我已经设置并运行了一个小的拖放操作,但它使用的是内嵌JavaScript,我宁愿将它全部移到外部文件中。理论上这是一个简单的交换,但我在检查员中得到referenceErrors,我的小工具失败。将javascript中的多个事件侦听器添加到元素

从我可以告诉,问题来自return

原始的HTML

<section id="titles" ondrop="dropClip(this, event)" ondragenter="return false" ondragover="return false"></section> 

所需的HTML

<section id="titles"></section> 

的JavaScript

var titles = document.getElementById('titles'); 

titles 
    .addEventListener('drop', dropClip(this, event)) 
    .addEventListener('dragenter', return false) 
    .addEventListener('dragover', return false); 
+0

如果我不得不猜测,我会说您的外部脚本正在加载到您的页面标题中,并且正在'titles'创建之前运行。您可以将脚本加载到页脚(这也会使您的页面加载速度更快),或者在'onload'处理程序中运行脚本。 – Jerry

+0

@JerrySeeger脚本是在页面的底部,并且所有JS正在执行文档准备好 – technopeasant

+0

两件事情。 (1)'addEventListener'中没有_call_函数,只是使用函数名来指定它们。 (2)'return false'不是函数。你可以在'addEventListener'中使用'function(){return false;}'。 – Ejaz

回答

7

JavaScript是其中的功能是“第一类对象”的语言。这意味着,可能与您可能遇到的其他编程语言相反,您可以像处理任何其他对象一样处理函数:可以传递它,可以返回它,也可以使用带有函数的函数里面的函数,等等。

这样做的后果可能是一个非常意想不到的编程风格,需要在Javascript中成功。在其他语言中,UI事件绑定以各种方式发生(例如C#的Button1.Click += new System.EventHandler(this.myEventHandler);或经典VB的Button_Click())。在C#中,可以传递委托,委托是具有特定定义的参数集和返回值的特殊对象,函数可以绑定到这些参数和返回值。但所有这一切都在javascript中消失,因为您可以直接将函数附加到属性直接。对于浏览器DOM事件处理,该属性被假定为函数引用,并且在该事件的本机事件处理代码期间,它会调用与该事件具有相同名称的属性所附带的函数。

好的,你说我们有功能。我们可以将它们传递给它们并像变量一样对待它们。怎么办?

首先请特别注意以下两个函数声明是相同的。它们产生完全相同的结果,在当前范围内(在浏览器中,window对象或当前正在运行的函数中)声明名为myfun的函数。

function myfun(param1, param2) { 
    //do some stuff 
}; 

var myfun = function (param1, param2) { 
    //do some stuff 
}; 

实际上,第一个将最终获得一个name的特性,即第二个则不会,可能还有一些其他的微小差别,但对于所有的实际意图和目的它们是相同的)。

第一个只是第二个快捷方式。基本上,你创建一个函数(可能有或没有名字)并将其分配给一个变量。程序员使用调用结果“myfun函数”的方便捷径,但实际上情况是“myfun变量 - 它现在包含一个特定的函数”。

你可以得到相同的功能,许多文献 - 这是一个真正的对象 - 只要将其分配给其他变量:

function myfun(param1, param2) { 
    //do some stuff 
}; 

var a = myfun, b = myfun, c = myfun; 

a(); // runs `myfun` 
b(); // runs `myfun` 
c(); // runs `myfun` 

下一个要注意的是,调用一个函数,你必须在其名称后面使用圆括号,并且任何参数都放在圆括号内。

var result = myfun('a', 1); // invoke the `myfun` function 
    // and store its return value in variable `result` 

但回头一看我们的赋值语句使abc全部为myfun函数的别名:在这种情况下,我们没有使用括号,因为 - 这里是它变得非常重要,所以要注意

调用功能(并获得函数的返回值),使用括号其名称后。

要通过函数参考,不要使用括号。

,如果我们做了什么,而不是这样:

var a = myfun(), b = myfun(), c = myfun(); 

abc将不再是指针指向myfun功能。它们全部是结果myfun,并且将包含任何返回的myfun - 或undefined如果它没有返回任何东西。如果你试图调用其中的一个,说a()你会得到一些类似的错误:

> TypeError: a is not a function 

现在,我已经画所有的背景下,有一个简单的事情,要知道,将让你的轨道上与addEventListener成功:它期望一个函数作为第二个参数。在你的示例代码中,当addEventListener调用它们时,你已经放入了你想运行的函数的内容,但是没有实际的功能。

可以解决通过实际声明功能第一,如:

function doNothing() { 
    return false; 
} 

titles.addEventListener('dragenter', doNothing); 
    // Note: this is not invocation like `doNothing()`, but passing a reference 

或者,你可以简单地包裹你的函数声明为匿名函数。请记住,JavaScript中的函数实际上并不具有名称,我们只是具有包含函数的变量。匿名函数是根本没有任何名称的函数,它可以通过隐式名称赋值(例如作为参数传递 - 它将具有参数名称)或通过执行魔法调用直接调用后面加括号的动作。

这将是这个样子:

titles.addEventListener('dragenter', function() { // anonymous function 
    return false; 
}); 

如果要调用一个匿名函数,你必须让JavaScript的知道你要像对待一个值,而不是正常的快捷方式,方法在当前作用域中创建一个已命名的函数(其中function myfun被视为var myfun = function)。这是由一个多组括号环绕整个事情做,就像这样:

(function() { // begin a function value containing an anonymous function 
    // do something 
}()); //invoke it, and close the function value 

我希望这可以帮助您了解更多关于JavaScript的,为什么你的代码是不工作的,你需要做的,做什么这行得通。

+1

令人难以置信,非常感谢您为此付出的时间。真的很清楚和说明性。过去几年里,我一直在javascript中徘徊,没有阅读过任何一本书,也没有阅读过任何教程,所以我所有的知识都来自于解剖其他人的代码并绘制我自己的意思。虽然我理解了大多数方法和概念,但我现在明白了他们的实际内容,而不是我的意思。最近,我觉得我终于可以写js而不是使用它 - 这真的证实了我。非常感谢!希望我有更多的赞扬和接受! – technopeasant

+0

不客气!有时候,当我发现某人的回答富有洞察力并且有帮助时,我会阅读他们关于我感兴趣的话题的其他答案。如果这些最终也有帮助,那么,那么他们也是。 :) – ErikE

+0

哈哈,会做。你介意给我发一封电子邮件@我的公开地址吗?我想让你参与我正在进行的一个项目的学分 – technopeasant

0

为确保您有包装你给的addEventListener到函数的函数内容。

例如,而不是.addEventListener('drop', dropClip(this, event))你会写.addEventListener('drop', function(event) { dropClip(this, event); })

+0

想知道'this'会在'function(event){dropClip(this,event) }' – Ejaz

+0

@ejay我使用它作为绑定到DOM元素事件的函数将子项移动到 – technopeasant

+0

@ejay的目标,'this'始终是DOM元素本身。 – ErikE

相关问题