2

我有一个小的拖放设置并运行,但它使用内联javascript,我更愿意将它全部移动到外部文件。从理论上讲,这是一个简单的交换,但是我的检查器中出现了 referenceErrors 并且我的缩小失败了。

据我所知,问题来自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);
4

2 回答 2

10

Javascript 是一种语言,其中函数是“一流的对象”。这意味着,可能与您可能有经验的其他编程语言相反,您可以像对待任何其他对象一样对待函数:您可以传递它,您可以返回它,您可以拥有一个函数,其中包含一个带有里面的函数,以此类推。

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

好吧,你说,我们有函数。我们可以传递它们并将它们视为变量。怎么办?

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

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`

但是回顾一下我们的赋值语句a,它们都是函数的别名b:在那些情况下,我们没有使用括号,因为 --在这里它变得非常重要,所以要注意cmyfun

调用函数(并获取函数的返回值),请在其名称后使用括号。

要传递函数引用,请不要使用括号。

如果我们改为这样做会怎样:

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

a, b, 并且c不再是指向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、为什么您的代码无法正常工作以及您需要做什么才能使其正常工作。

于 2013-04-01T23:14:01.533 回答
0

当然,您必须将提供给 addEventListener 的函数内容包装到一个函数中。

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

于 2013-04-01T22:47:53.997 回答