“清除”是 Javascript 中的保留字吗?

IT技术 javascript
2021-01-12 15:36:29

我花了很长时间才弄清楚我不应该在 Javascript 中使用 clear() 作为函数的名称:

<head>
    <script type="text/javascript" src="Array.js"></script>
</head>
<body>
    Hello!!!!<br>
    <button type="button" onClick="clear()" id="ppp">Shoo!</button><br>
    <button type="button" onClick="add()" id="add">Add a few elements</button><br>
    <button type="button" onClick="check()" id="check">Check the array</button><br>
    <p id="results">Results will appear here.</p>
    <script type="text/javascript">
initialize();
    </script>
</body>

这是 Array.js:

var results;

function initialize(){
 results = document.getElementById("results");
}

function add() {
results.firstChild.data="add";    
}

function clear() {
results.firstChild.data = "Hello?";
}

function check() {
results.firstChild.data = "check";
}

症状:单击“添加”和“检查”按钮会得到我期望的结果,但单击“清除”按钮什么也没做。

如果我将clear()重命名clearxyz(),它工作正常。

我的问题:

  1. “clear”是保留字吗?我没有在列表中看到它:https : //developer.mozilla.org/en/JavaScript/Reference/Reserved_Words
  2. 我将来是否应该使用调试技巧来解决此类问题?我花了很长时间(我是菜鸟!)才发现函数的名称是我的问题。

非常感谢。编辑:我使用的是 Firefox 6.0,我添加了一个换行符来显示 Array.js 的开始位置。

4个回答

正如有人说,clear不是保留关键字。似乎被调用的函数是document.clear [MDN]调用

console.log(clear === document.clear);

在事件处理程序中返回true

演示

所以看起来,document在事件处理程序的作用域链中......现在的问题是为什么。

JavaScript:权威指南说:

在作为 HTML 属性的事件处理程序中,Document 对象位于 Window 对象之前的作用域链中 (...)

由于您的方法是全局的,这意味着它是window对象的一个属性,因此在作用域链中找不到它,就像document.clear在作用域链中一样。

我还没有找到任何规范。该指南还说人们不应该依赖它,所以我认为这不是官方的。

如果表单中有表单元素,那么即使是相应的form元素也会在作用域链中(但不确定这是否适用于所有浏览器)。这是混淆的另一个原因。


有两种(非排他性)方法可以避免这种情况:

  • 不要使用内联事件处理程序。它被认为是不好的做法,因为它混合了逻辑和表示。还有其他 方法可以附加事件处理程序。

  • 不要污染全局命名空间。在创建全球范围内一个对象(一个名字你肯定不会有任何碰撞windowdocument属性或HTML元素的IDS)和分配功能,因为这对象的属性。每当你调用一个函数时,你就是通过这个对象来引用它的。还有其他方法可以命名您的代码。

虽然使用动态添加的侦听器修复了 OP 问题,但同样重要的是要指出必须注意函数名称。window 对象有大量的默认属性,因此具有通用名称(如“clear”、“add”和“check”)的全局函数比具有更具体名称(如“clearForm”或“clearInput”)的函数更容易发生冲突(或无论该函数的实际目的是什么)。与合适的“命名空间”或前缀结合使用,冲突的机会可以减少到接近于零。
2021-03-12 15:36:29
...有趣的是,您可以document.getElementById内联那样从调用中消除
2021-03-18 15:36:29
哦,你很快就会收到我的账单。;) 我实际上正要发布一个arguments.callee === document.clear答案,但后来我看到了你答案,而且你也有范围解释,所以我想说你把它打出了公园。
2021-03-19 15:36:29
@patrickdw:谢谢......你实际上通过在评论中提到它给了我提示......我觉得我偷了你的想法;)
2021-03-26 15:36:29

不,clear不是保留关键字。

问题是,由于您使用事件处理程序内容属性,您的全局函数window.clear被过时的document.clear.

此行为在获取事件处理程序的当前值的第 10 步中进行解释

词法环境范围

  1. 如果H是元素的事件处理程序,则让Scope成为 NewObjectEnvironment( document全局环境) 的结果。

    否则,H是一个Window对象的事件处理程序:让 Scope成为全局环境

  2. 如果表单所有者不为空,则让Scope为 NewObjectEnvironment( form owner , Scope ) 的结果。

  3. 如果element不为 null,则令Scope为 NewObjectEnvironment( element, Scope ) 的结果。

注意:NewObjectEnvironment() 在 ECMAScript 第 5 版第10.2.2.3NewObjectEnvironment (O, E) 中定义

这意味着全局范围被

  1. 文件
  2. 表单所有者(如果有)
  3. 元素

因此,您可以

  • 重命名您的函数。

    function clear__() { document.body.style.background = 'green'; }
    <button type="button" onclick="clear__()">Click me</button>

    这种方法并不完全可靠,因为某些浏览器可能会实现隐藏变量的非标准功能。或者未来的规范可以引入该功能(示例)。

  • 调用您的函数作为全局对象的方法。

    例如,假设window没有阴影,您可以使用window.clear.

    function clear() { document.body.style.background = 'green'; }
    <button type="button" onclick="window.clear()">Click me</button>

  • 避免事件处理程序内容属性。

    相反,您可以使用事件处理程序 IDL 属性或事件侦听器。

    function clear() { document.body.style.background = 'green'; }
    document.querySelector('button').onclick = clear;
    <button type="button">Click me</button>

    function clear() { document.body.style.background = 'green'; }
    document.querySelector('button').addEventListener('click', clear);
    <button type="button">Click me</button>

不是根据MDN

编辑:

你让我好奇,所以我把这个小 jsfiddle放在一起

function clear() {
    alert("you cleared just fine");
}

$('clear').addEvent('click', clear);

有一个命名的函数clear似乎工作得很好。

哈哈……是的。不知何故,我第一次错过了这个问题。
2021-03-13 15:36:29
你的 jsfiddle 是不同的。它通过传递对函数的引用来附加事件处理程序。问题是 OP 正在使用内联事件处理程序,它具有特定的作用域链,我们必须找出哪个。
2021-03-14 15:36:29
是的,那是 OP 在他的问题中链接到的页面。
2021-03-27 15:36:29

好问题。我认为这个问题是一个范围问题 - 你onClick="clear()"不会去clear你定义函数,但我不确定它会去哪里。将其更改为window.clear()或一个简单地调用您的clear作品的新函数

<body>
    Hello!!!!<br>
    <button type="button" onClick="clear()" id="ppp">Shoo!</button><br>
    <button type="button" onClick="window.clear()" id="ppp">window.clear!</button><br>
    <button type="button" onClick="clear2()" id="ppp">clear2!</button><br>
    <button type="button" onClick="add()" id="add">Add a few elements</button><br>
    <button type="button" onClick="check()" id="check">Check the array</button><br>
    <p id="results">Results will appear here.</p>
    <script type="text/javascript">
    var results;

function initialize(){
 results = document.getElementById("results");
}

function add() {
results.firstChild.data="add";    
}

function clear() {
results.firstChild.data = "Hello";
}

function clear2() {
clear();
}

function check() {
results.firstChild.data = "check";
}
initialize();
    </script>
</body>
这是有帮助的,以一种加重/令人困惑的方式。我想我也需要更多地了解范围!我仍然想找到一种方法来避免将来使用其他保留字避免此问题。
2021-03-26 15:36:29
@Uncle:clear不是保留关键字。这是一个范围问题。
2021-04-03 15:36:29