【问题标题】:Can't use "download" as a function name in javascript不能在 javascript 中使用“下载”作为函数名
【发布时间】:2011-10-21 16:12:09
【问题描述】:

这个小sn-p有问题:

<script>
function download() {
    alert('Hi');
}
</script>
<a href="#" onClick="javascript:download();">Test</a>

单击 Chrome 14.0 中的链接后,我会得到一个

Uncaught TypeError: string is not a function

在 Firefox 和 IE 中它工作得很好。我通过重命名函数解决了这个问题,但我仍然很好奇 Chrome 中的“下载”是什么。据我所知,它不是保留关键字,那它可能是什么?

【问题讨论】:

  • 您是否安装了任何扩展程序?
  • 已确认。即使删除不应该存在的javascript: 也无济于事。奇怪!
  • 不要使用全局函数。将您的函数放在命名空间中并以编程方式绑定事件处理程序。
  • @Muu,我有很多,但即使我启动一个隐身窗口(这显然会禁用扩展),我仍然会收到错误消息。此外,正如 Tomalak 在下面指出的那样,console.log(download) 给出了 undefined。
  • @Amati:你在哪里做这个?如果您创建了 jsFiddle,请注意实际代码在 iframe 中运行,并且无法从控制台访问全局变量。

标签: javascript google-chrome


【解决方案1】:

&lt;a&gt; 元素在 HTML5 中具有 download 属性,如 here 所述,默认值为 ""(空字符串)。

这意味着onclick处理程序中的download === this.downloadthisonevent属性中的元素),因此该元素的download属性优于@987654338的download属性@。

This fiddle 列出默认存在的所有字符串属性。你可以看到download是一个属性,就像innerHTML一样,其中also fails作为一个函数使用时的原因完全相同(即试图引用window.innerHTML,而是执行elem.innerHTML())。

正如 cmets 中所说,使用 window 不会混淆属性/属性变量的计算结果。


这种作用域行为实际上似乎不是由于 this 值,而是由于正在构建的特定“作用域链”。

根据the HTML5 specification

词法环境范围

Scope 成为NewObjectEnvironment(the element's Document, the global environment) 的结果。

如果元素有一个表单所有者,让ScopeNewObjectEnvironment(the element's form owner, Scope) 的结果。

Scope 成为NewObjectEnvironment(the element's object, Scope) 的结果。

即正在发生的事情是范围链是window -> document -> element(增加优势)。这意味着download 的计算结果为element.download 而不是window.download。由此也可以得出结论,getElementById 会冒泡到document.getElementById(假设elem.getElementById 不存在)。

我设置了a systematic example,以便您可以看到变量如何在作用域链中冒泡:

window.a   = 1;
document.a = 2;
elem.a     = 3;

window.b   = 4;
document.b = 5;

window.c   = 6;

然后,&lt;a ... onclick="console.log(a, b, c)"&gt; 在点击时记录356

【讨论】:

  • 我不喜欢这种奇怪的范围聚合的东西,或者任何你想称呼它的东西......表单也是如此。 +1
  • 这是否表明可以通过将其更改为 onClick="window.download()" 来解决此问题?
  • @Joe: this 不是这里的问题。应该知道this 指的是元素...问题是事件处理程序的 scope 不仅包含全局范围,还包含元素本身作为范围。好像有人这样做了:with(theElement) { theElement.onclick = function() {...} }... 这就是令人困惑的部分。
  • @FelixKling:Here's a reference. "定义为 HTML 属性的事件处理程序具有更复杂的作用域链。作用域链的头部是调用对象...事件中的下一个对象然而,处理程序的作用域链不是全局对象;它是触发事件处理程序的对象。"
  • @Felix Kling & @Ӫ_._Ӫ:对不起,这似乎更接近:w3.org/TR/html5/webappapis.html#event-handler-attributes。 “让 Scope 成为 NewObjectEnvironment(元素的对象,Scope)的结果。”所以这意味着元素本身在任何其他范围(例如窗口)之前被推送。这也是有道理的,因为document.xxx 函数似乎也可用,而无需在处理程序属性中使用documentdocument 也根据那里的规则被推入范围链):jsfiddle.net/pimvdb/X5syU/1
【解决方案2】:

某些函数名称只是保留或已使用。另一个是“评估”。

我建议在你的所有函数和变量名前加上一些东西以避免这种情况。示例:“sto_download”

【讨论】:

  • 如果我从脚本中取出函数定义,console.log(download)console.log(download()),那么我得到download is not defined
  • 并没有真正解释 Chrome 中发生了什么,是吗?
猜你喜欢
  • 1970-01-01
  • 2018-09-23
  • 2014-11-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-06-17
相关资源
最近更新 更多