Why JS function name conflicts with element ID?
This is a legacy scope chain issue originating from JavaScript 1.0 to 1.3 when there was no distinction between the programming language and what we now call a DOM API ("Dynamic HTML" back then).
If your form control (here: a select
element) is part of a form (descendant of a form
element), then the Form
object that represents the form
element is third-next in the scope chain of code in the control's event-handler attribute values (second-next is the form control object itself, next is the Variable Object of that code).
JavaScript™ was designed by Brendan Eich (then at Netscape) as a programming language that is easy to use for beginners and that works well with HTML documents (as complement to Sun's Java; hence the ever-confusing name). Because in those early days language and (Netscape) DOM API were one, this (over)simplification applied to the DOM API as well: A Form
object has the names of the controls contained in the form that it represents as the names of its properties that refer to the corresponding form control objects. IOW, you can write
myForm.border
which is the proprietary shorthand of the standards-compliant (W3C DOM Level 2 HTML), but equally backwards-compatible
document.forms["myForm"].elements["border"]
Now, if you use a form control's name in an event-handler attribute value of a form control in a form, like
<form …>
<… name="border" onchange='border(this.value)' …>
</form>
that is the same as if you had written the half-proprietary
<form …>
<… name="border" onchange='this.form.border(this.value)' …>
</form>
or the standards-compliant
<form …>
<… name="border" onchange='this.form.elements["border"](this.value)' …>
</form>
because a potential global border()
function is a property of the ECMAScript Global Object which comes last, after the Form
object (an object implementing the HTMLFormElement
interface in the W3C DOM), in the scope chain.
However, the form control object referred here by border
is not callable (does not implement the ECMAScript-internal [[Call]]
method or implements it so that it throws an exception when called). So if you try to call the object with border(this.value)
, a TypeError
exception is thrown, which you should see in the script consoles (like "TypeError: border is not a function" in the Developer Tools of Chromium 16.0.912.77 [Developer Build 118311 Linux]).
Microsoft, Netscape's competitor in the 1990s, had to copy that feature for the MSHTML DOM so that code written for Netscape would also run in Internet Explorer (3.0), with JScript (1.0). And Microsoft's competitors copied it to their DOM implementations for exactly the same reason. It became part of a quasi-standard (now called "DOM Level 0").
Then came the DOM Level 2 HTML Specification, a continuing effort to standardize and extend common features of existing DOM implementations at the time. A W3C Recommendation since 2003-01-09, its ECMAScript Language Binding specifies that items of HTMLCollection
s can be accessed by their name or ID with the bracket property accessor syntax [
…]
, equivalent to calling the namedItem()
method of the object implementing the HTMLCollection
interface.
form
element objects and element objects for form controls in forms are items of HTMLCollection
s in the W3C DOM, HTMLDocument::forms
and HTMLFormElement::elements
, respectively. But for backwards compatibility in browsers,
document.forms["myForm"].elements["myControl"]
needs to be equivalent to
document.myForm.myControl
So, with the implementations of W3C DOM Level 2 HTML interfaces at the latest, this feature started to apply to elements with ID (id
attribute value) as well (which can be seen in Chromium, for example).
As a result, the convenience feature introduced in JavaScript™ 16 years ago still bites you like a bug in client-side DOM scripting today.
If you avoid using the same name or ID for form controls and forms that you use as identifier of user-defined functions, and that are already used for built-in form properties (like action
, submit
, and reset
), then this becomes less of an issue. Also, it is a bad idea to use the same identifier for the function and one of its arguments as (confusing code aside) that makes the function object inaccessible from within the function (the Variable Object of the function context comes first in its scope chain).
Whats the best way to resolve name conflicts in javascript?
Try the JavaScript module pattern (or namespaces) used in various libraries.
Try to be DRY (don't repeat yourself) so you can avoid name collisions. If the code is almost the same you better avoid code duplication by creating a function which can handle both cases. The function can take two parameters: which dropdown to populate and with what data. This helps maintainability as well.
update: I assume that you take the XML from an AJAX request. In this case you can create on-the-fly anonymous functions with the appropriate parameters for callback inside a loop.
Can an onclick() function not have the same name as the element calling it?
Inline event handlers are magical (i.e. not intuitive).
The properties of the enclosing <form>
element are in scope of the inline event handlers. And since the name of each form control element becomes a property of the form element, using such a name inside the event handler will refer to the element instead.
The scope chain of the inline event handler is roughly:
Global scope / properties of window
^
|
Properties of document (e.g. body)
^
|
Properties of enclosing form (e.g. newTreatment or submit)
^
|
Properties of <button id="newTreatment" /> (e.g. type, onclick)
^
|
Function scope of inline event handler
Bindings in closer scopes (e.g. the form) shadow bindings in higher scopes, e.g. the global scope.
A simple solution would be explicitly refer to the global variable via window.newTreatment
.
I described this in more detail here.
This seems to be formalized in the HTML5 spec.
Best approach avoid naming conflicts for javascript functions in separate .js files?
I limit the scope of the function to that file.
(function () {
var AddTag = function AddTag () {
};
}());
… and sometimes make some functions in it available to the global scope:
var thisNamespace = function () {
var AddTag = function AddTag () {
…
};
var foo = function foo() {
AddTag();
…
};
var bar = function bar() {
…
};
return {
foo: foo,
bar: bar
}
}();
Solution for javascript variable name conflict other than iframe?
solution is to use javascript closures.
for instance:
http://jsfiddle.net/C7yen/
<ul>
<li>a</li>
<li>b</li>
<li>c</li>
</ul>
<script>
obj={
id:1,
set:function()
{
setF=(function(ev){ return function(){ $(this).html(ev.id) } })(this);
$('li').each(
setF
);
}
}
window.onload=function()
{
obj.set()
}
</script>
Why does my function returns not a function when name attribute of input is the same?
As per the spec
A control's "control name" is given by its name attribute. The scope
of the name attribute for a control within a FORM element is the FORM
element.
So, the name's scope is changed inside a FORM, just a like a variable's scope is changed when declared again inside a function
.
Try this without a Form
function myFunction() { alert("Hello World");}
<input type='checkbox' name='myFunction' onclick="myFunction()">
Related Topics
How to Change an Element'S Class With JavaScript
"Submit Is Not a Function" Error in JavaScript
Using an HTML Button to Call a JavaScript Function
How Does Content Security Policy (Csp) Work
Detect All Changes to a ≪Input Type="Text"≫ (Immediately) Using Jquery
How to Get the Pure Text Without HTML Element Using JavaScript
How to Check Whether a Storage Item Is Set
How to Go to a Specific Element on Page
How to Perform a Real Time Search and Filter on a HTML Table
Selecting All Text in HTML Text Input When Clicked
JavaScript Function Doesn't Work When Link Is Clicked
Get Cursor Position (In Characters) Within a Text Input Field
Get File Size, Image Width and Height Before Upload
What Is the Most Efficient Way to Create HTML Elements Using Jquery
Get Div Height With Plain JavaScript
How to Get Selected Text from a Textbox Control With JavaScript
How to Add Line Breaks to an HTML Textarea
Removing All Script Tags from HTML With Js Regular Expression