Why doesn't allow "lang" as function name? [duplicate] - javascript

This question already has answers here:
JS function named `animate` doesn't work in Chrome, but works in IE
(3 answers)
Closed 6 years ago.
In my HTML I define the lang function in the script tag and add the "Test Fire!" button which has to call lang on click:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Testing Functions</title>
<script type="text/javascript">
function lang() {
alert("Hello, World! It's JavaScript this time");
}
</script>
</head>
<body>
<form action="">
<input type="button" value="Test Fire!" onclick="lang();">
</form>
</body>
</html>
However, if I click the button I get this error:
Uncaught TypeError: lang is not a function
But if I change the function name from lang to anything else this code works fine.

Consider this code:
<input type="button" value="Debugger Test" onclick="debugger;" />
<input type="button" value="Prototype Test" onclick="console.log(__proto__);" />
When you click on “Debugger Test” and open your debugger, you’ll see that there seems to be an implicit with scope wrapped around the onclick, making all the <input>’s properties accessible without needing to refer to the button.
Clicking on “Prototype Test” logs the prototype of the current scope. You’ll see that it’s the HTMLInputElement’s prototype, making all the scopable properties of this entire prototype chain available to the scope.
Interestingly, the scopable part of the prototype chain of the current HTMLDocument is included as well.
All this means that all global attributes (lang is one of them) and several others specific to buttons are overridden. E.g. value, type also wouldn’t work. Similarly, variables like createElement (from document) also wouldn’t work, but the unscopable append (from ParentNode.prototype) would.
All this is also explained in this answer to a related question about global variables clashing with window properties.
Your best bet is to use the standard way of adding event listeners: addEventListener.
<input type="button" value="Test" />
<script>
function lang() {
alert("Hello, World! It’s not an HTML event handler attribute this time");
}
document.querySelector("input").addEventListener("click", lang);
</script>

There is no reason to complicate (I really do not know why it does not work), but you can use:
Add the alert directly in the input.
Result: https://jsfiddle.net/cmedina/h4m1qcoq/6/
or
Add listener to input
function lang() {
alert("Hello, World! It's JavaScript this time");
}
document.getElementById('test').onclick = lang
Result: https://jsfiddle.net/cmedina/h4m1qcoq/7/

Related

Getting SCRIPT5009: 'id' is undefined in Internet Explore IE 11

I have a very simple script(setUser) which is called on click of a button.This script is working fine in chrome but in IE 11 i am getting a console error.
Another weird thing is i am getting that error only when dev tool is open.It works fine if devtool is not open.
Error is :-
SCRIPT5009: 'id' is undefined
<!DOCTYPE html>
<html>
<head>
<title></title>
<script type="text/javascript">
function setUser(eventType){
console.log(eventType);
}
</script>
</head>
<body>
<button id="vish" onclick="setUser(id)" style="height:40px;width:200px">Click Me</button>
</body>
</html>
Simple Workaround for this is to declare a
var id; just below the script.But i need the proper documented reason why this doesnot work in ie11 but same works in chrome.And is a better solution than what i tried
Workaround :- by adding var id at the top
<!DOCTYPE html>
<html>
<head>
<title></title>
<script type="text/javascript">
var id;
function setUser(eventType){
console.log(eventType);
}
</script>
</head>
<body>
<button id="vish" onclick="setUser(id)" style="height:40px;width:200px">Click Me</button>
</body>
</html>
expected :-
when dev tool is open in ie11 and when we click the button we should get the console log as "vish"
actual result :-
SCRIPT5009: 'id' is undefined js error
id is simply undefined, as the error message says. If you declare it, the error is gone, but it won't behave like you expected. If you declare it, it exists with value undefined. You probably wanted
onclick="setUser(this.id)"
this.id means the button context, while simply id tries to find it in global context. In case of your error, id is not declared, whereas
var id; // or var id=undefined;
declares it, and leaves it undefined, so the browser at least knows it is a variable. By saying id is undefined Explorer means it is not declared.
I believe the reason is that the browser searches for variables and named elements (referenced by name or id attribute; this is not standard, but browsers do it), which actually doesn't exist in global context and are looked up by reference and Explorer obviously can't handle this situation. If it is declared as var, javascript knows it is not a named element reference.
Example below shows the non-standard behaviour: it should end with error test is not defined (it really is not), but browsers say hello.
<input id="test" value="hello">
<script>
alert(test.value);
</script>
The cause of it not working in IE11 is because you do not specify a doctype for the HTML document in the block of code that threw the error.
If I add <!DOCTYPE html> to the start of the HTML, as in the workaround you show; it works in IE11 as well for me, without adding the var id;
The exact reason is unknown to me, but without the doctype, IE will run the page in quirks mode. And that seems to mess up the determination of the function scope when the browser tries to parse onclick="setUser(id)" into valid JS code.
This would not happen if the doctype is correct and the page can hence be run in the correct mode.
This would also no happen if the browsers HTML engine did not have to parse the HTML string setUser(id) into valid JS code before it can be used. Hence it's not a common issue anymore since the standard these days is to not use inline event handler attributes on HTML tags.
So prefer explicit event binding with javascript when possible to not run into issues like this, where a totally unrelated part, the doctype, messes up your code.
Using onclick="setUser(this.id)" should work.
However, a cleaner workaround would be to do all the onclick handling in JavaScript:
onload = function() {
var buttons = document.getElementsByTagName("button");
for(var i = 0; i < buttons.length; i++) {
buttons[i].onclick = function() {
console.log(this.id);
}
}
}
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
<button id="vish" style="height:40px;width:200px">Click Me</button>
<button id="vish2" style="height:40px;width:200px">Click Me 2</button>
</body>
</html>

Uncaught TypeError: lang is not a function [duplicate]

This question already has answers here:
JS function named `animate` doesn't work in Chrome, but works in IE
(3 answers)
Closed 6 years ago.
In my HTML I define the lang function in the script tag and add the "Test Fire!" button which has to call lang on click:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Testing Functions</title>
<script type="text/javascript">
function lang() {
alert("Hello, World! It's JavaScript this time");
}
</script>
</head>
<body>
<form action="">
<input type="button" value="Test Fire!" onclick="lang();">
</form>
</body>
</html>
However, if I click the button I get this error:
Uncaught TypeError: lang is not a function
But if I change the function name from lang to anything else this code works fine.
Consider this code:
<input type="button" value="Debugger Test" onclick="debugger;" />
<input type="button" value="Prototype Test" onclick="console.log(__proto__);" />
When you click on “Debugger Test” and open your debugger, you’ll see that there seems to be an implicit with scope wrapped around the onclick, making all the <input>’s properties accessible without needing to refer to the button.
Clicking on “Prototype Test” logs the prototype of the current scope. You’ll see that it’s the HTMLInputElement’s prototype, making all the scopable properties of this entire prototype chain available to the scope.
Interestingly, the scopable part of the prototype chain of the current HTMLDocument is included as well.
All this means that all global attributes (lang is one of them) and several others specific to buttons are overridden. E.g. value, type also wouldn’t work. Similarly, variables like createElement (from document) also wouldn’t work, but the unscopable append (from ParentNode.prototype) would.
All this is also explained in this answer to a related question about global variables clashing with window properties.
Your best bet is to use the standard way of adding event listeners: addEventListener.
<input type="button" value="Test" />
<script>
function lang() {
alert("Hello, World! It’s not an HTML event handler attribute this time");
}
document.querySelector("input").addEventListener("click", lang);
</script>
There is no reason to complicate (I really do not know why it does not work), but you can use:
Add the alert directly in the input.
Result: https://jsfiddle.net/cmedina/h4m1qcoq/6/
or
Add listener to input
function lang() {
alert("Hello, World! It's JavaScript this time");
}
document.getElementById('test').onclick = lang
Result: https://jsfiddle.net/cmedina/h4m1qcoq/7/

How to make an anchor tag's href invoke an anonymous function?

I'm working on a cross-site scripting attack on an internet forum where links can be put in post like
[url]http://google.com[/url]
which then gets surfaced as
http://google.com
on the forum's thread. If possible, I want to use the technique of invoking JavaScript functions through the href, i.e.
<script type="text/javascript">
function sayHello ( )
{
alert("Hello");
}
</script>
Clicking here alerts "Hello"
but since I don't have any way of using predefined JavaScript functions, I'm wondering if I can put anonymous functions in there, e.g.
Clicking here alerts "Hello"
I've tested this out in Notepad with the simple page
<html>
<head>
</head>
<body>
<div>
<p>Clicking on this will alert "Hello""</p>
</div>
</body>
</html>
but it didn't work.
Any suggestions for me?
Use an IIFE:
Click here
Although there's not too much difference from doing this without the IIFE, just as top-level JS code:
Click here
The only significant difference is that you can declare local variables within the function.

jquery assumes element id? normal behaviour? [duplicate]

This question already has answers here:
Do DOM tree elements with IDs become global properties?
(5 answers)
Closed 9 years ago.
i have the following index.html:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="http://code.jquery.com/jquery-latest.min.js" type="text/javascript">
</script>
<script type="text/javascript">
jQuery(document).ready(function($) {
console.log(foo); // jQuery assumes foo is an id?
});
</script>
</head>
<body>
<div id="foo">i'm a div</div>
</body>
</html>
the console outputs:
<div id="foo">i'm a div</div>
why?
This has got nothing to do with jQuery.
This is because named elements(elements with an ID or name attribute) become properties of the window object.
console.log(foo) is identical to console.log(window.foo);
Since your div is a named element(id="foo"), it is added to window.
Named access on window
It's not a jQuery behavior, it's (originally) an Internet Explorer behavior. IE has always created global variables for each DOM element that has an id attribute. The variable is named after the id and references the DOM element. Lately, other browsers have been following suit.
http://www.west-wind.com/weblog/posts/2009/Mar/22/Internet-Explorer-Global-Variable-Blow-ups
http://blogs.msdn.com/b/alvar/archive/2009/10/22/internet-explorer-creates-global-variables-for-each-object-in-the-dom.aspx
http://www.shanison.com/2010/06/17/ie-id-and-javascript-global-variable/
http://www.2ality.com/2012/08/ids-are-global.html
JQuery doesn't assume that, but rather JavaScript does. Your foo is unquoted, so it must either be an identifier or undefined. The element with id foo happens to be in the scope of your script, so the element identified by it is logged.
If you renamed it to bar, then you'd be able to reference bar as it'd be a top-level id.
Note that such usage is frowned upon because it is unclear what you're doing in the code without referencing the html. Using document.getElementById(...) or a variant thereof is generally preferred because it is clear what you're doing.

where to embed javascript section in a html page [duplicate]

This question already has answers here:
when and where to put javascript in html
(7 answers)
Closed 9 years ago.
the thing is i'm unable to figure out where to embed javascript in html page whether in head section or body section.
example 1:
<html>
<head>
<title>events</title>
<script>
document.getElementById("b").onclick=function(){displayDate()};
function displayDate()
{
document.getElementById("demo").innerHTML=Date();
}
</script>
</head>
<body>
<p id="demo"></p>
<button id="b">new</button>
</body>
</html>
in the above example I placed script tags in head section but it is not working.
example: 2
<html>
<head>
<title>events</title>
<script>
function upper()
{
var x=document.getElementById("t");
x.value=x.value.toUpperCase();
}
</script>
</head>
<body >
enter some text:<input type="text" id="t" onChange="upper()"/>
</body>
</html>
in the second example I placed the javascript in head section it is working properly.first example demonstrates that on clicking a button date will be displayed in the second example in a text box when data is entered and if we come out of the box the letters in the box will we converted to uppercase.
To have it more readable I prefer to always place JavaScript in the head section. If you need to access elements from there, use the window.onload event:
<head>
<title>events</title>
<script type="text/javascript">
window.onload = function() {
document.getElementById("b").onclick = function() {
displayDate();
};
};
function displayDate()
{
document.getElementById("demo").innerHTML=Date();
}
</script>
</head>
This would work just fine.
Your second example worked because you just defined a function, you didn't try to access any element.
You can put it in the head. The problem is that your examples are not the same. The first one doesn't work because the current date is retrieved by calling Date(), when it should be new Data().getDate(). The second example works because the code is valid.
The problem you're running into is that you're trying to reference an element before it is loaded into the DOM.
When you're putting the script in the HEAD tag, the dom hasn't been loaded yet and the document.getElementById won't find what you're looking for.
You have a few different options to deal with this. You can put the script at the end of the page, which will work for your small example here.
Probably a better option is to take a look at learning/using jquery or another js utility. Jquery makes it easy to solve this issue by giving you a "ready" event. This ready event will be triggered when the DOM is fully loaded. So:
$(document).ready(
function()
{
$("#demo").html((new Date()).toString());
});
Is all you really need. With this approach, it doesn't matter where the script it on the page.

Categories