So I have a good grasp of most static typed languages mainly C and C++. But when I went into javascript I noticed something that bummed me out.
I learned to write this function to interact with inner HTML:
document.getElementById("SomeHTML").onclick = function(){
document.getElementById("AnotherHTML").innerHTML = "<p> Joe has a cat </p>";
}
That is all fine and well but there is a problem. How am I supposed to reuse this and keep it readable?... coming from a C++, I was always taught to write code in this way:
function MyFunc()
{
document.getElementById("AnotherHTML").innerHTML = "<p> Joe has a cat </p>";
}
document.getElementById("SomeHTML").onclick = MyFunc();
The latter code being cleaner (at least to me) and I can reuse the function, but it doesn't work ... I am able to write this way in every programming language yet in javascript it produces an error. I don't know what I am missing, I know its something simple. Can someone please help me understand why I cant write javascript functions in this way? Or if I can please tell me how, because I much prefer the latter than the former. thanx in advance.
You're in luck! The latter code will work in JavaScript as well.
Below, I've outlined three different ways you can achieve this using a more familiar syntax.
// The function to call
function MyFunc(){
alert('Working!');
}
// Option 1 (Link 1)
document.getElementById("one").addEventListener("click", MyFunc);
// Option 2 (Link 2)
document.getElementById("two").onclick = MyFunc;
Link 1<br>
Link 2<br>
Link 3
Your function is not quite reusable, to me I would have used another approach
// Original version
function MyFunc() {
document.getElementById("AnotherHTML").innerHTML = "<p> Joe has a cat </p>";
}
document.getElementById("SomeHTML").onclick = MyFunc();
// Function Generator
function MyFunc_generator(element, html_content) {
return function() {
element.innerHTML = html_content;
}
}
myfunc = MyFunc_generator(
document.getElementById("AnotherHTML"),
"<p> Joe has a cat </p>"
}
document.getElementById("SomeHTML").addEventListener("click", myfunc);
There are quite some difference in the code.
We can start with comparing the original MyFunc function and the MyFunc_generator one.
The first does not have a return statement and so the assignment
document.getElementById("SomeHTML").onclick = MyFunc(); would assign the value undefined the the onclik handler of the html element whose id is "SomeHTML".
The "MyFunc_generator" function is an Higher order function, a function that return a function as result of his evaluation.
The execution of the generator function has the result to create a specialized function with real values instead that generic ones.
The assignment in the example would create a function (anonymous) and assign the name myfunc to it. That function will be equal to your.
You can change the parameters of the generator to create similar function with different targets, and/or different content.
Obviously the effort in a such simple case will not worth the result but if the strategy you have to describe is quite complex the benefit will increase.
One last note. The assignment of the handler function to the event is different. In javascript the preferred way is with addEventListener
Related
Firstly, I'm a beginner, so don't be mad if what I'm saying is stupid.
So, this is the code that is using parameters:
function simpleExample (x) {
document.write ("I love " + x);
}
simpleExample ("my mom.");
And this is the code that doesn't use the parameters:
function simpleExample () {
var x = ("my mom");// Does not use the parameters
document.write ("I love " + x);
}
simpleExample ();
So, the result is the same and... the global and local thing is also the same [both is local right?] So what does the difference?
Sorry if it's a dumb question.
You maybe right if you just want to say you're loving your mom. But, what if you also want to say other persons that you love? You write all that hard code everytime?
the answer is : no.
You just call that function with a parameter. And that's it. Nothing more.
simpleExample("my mom");
simpleExample("my dad");
simpleExample("justin bieber"); //we all hope you don't.
Why use the parameters if we can use variables?
The point is that often we cannot use static (global) or constant variables. Consider your first function:
simpleExample("my mom.");
simpleExample("my dad.");
We are calling the same function multiple times with different arguments. This requires parametrisation of the code in the function that is otherwise the same for all cases.
Using a parameter for a function allows the result of the function (be it a process or a result value) to differ based on an input that is not fixed at the time of writing the function.
Even with your simple example it should be obvious that the simpleExample(x) function with a parameter can be easily reused like so:
simpleExample('my mom');
simpleExample('and my dad too!');
simpleExample('my sister not so much');
This wouldn't be as easy with the variable approach.
Using parameters is the essence of functions.
In the second case, the variable x is local to the scope of the fonction and will never change. That is, the execution of your function simpleExample will always have the same effect (logging "I love my mom" in the console).
The use of parameters allows your function to have an effect dependent to the input. In this case, the person you love can be changed depending of the parameter x.
Im a newbie programmer who got the function below from Stoyan Stefanovs object oriented JavaScript Book. He says that if you call next three times, it will output "a" and "b" and then "c". When I tried it in firebug console, it kept giving me "a", so that`s one question (a) i.e. is there something about firebug that would explain my result?
Next, I tried to run it in jsfiddle.net but it won`t output anything. http://jsfiddle.net/mjmitche/SkSMm/
Im sure Im doing something wrong, but what? Please explain if you can. Note, I did next(); and got A, and then I did next(); again and got 'a' and next(); again and got 'a'. In other words, the counter didnt change or didnt remember.
function setup(x) {
var i = 0;
return function () {
return x[i++];
};
}
var next = setup(['a','b','c']);
next();
Here is the jsfiddle link to show it works:
http://jsfiddle.net/ZnZTk/
JsFiddle is not like the console, it doesn't have a window where it will output return values. The result of the code is a web page, that is shown at the lower right.
You can use the alert method to show the values:
alert(next());
http://jsfiddle.net/SkSMm/4/
As you see, calling next three times will actually output the three values in the array. The setup function returns a delegate to the anonumous function that is created in the function. As that anonymous function uses variables outside itself, but which are local to the surrounding function, a closure is created for the function. The closure will contain the i and x variables. As the closure belongs to the delegate, it will survive from one function call to the next, and retain the values of it's variables.
You could do a similar thing just using global variables:
var x = ['a','b','c'];
var i = 0;
function next() {
return x[i++];
}
alert(next());
alert(next());
alert(next());
As the variables are declared outside the function, they will survive between the function calls.
The drawback of using global variables is that one script easily clashes with another if the variables are not given very unique names. If you use a closure, there is no risk of the variables of one script to conflict with variables of another script.
You did it wrong:
And jsfiddle: http://jsfiddle.net/ZHgW2/
Here's a neat demo that takes advantage of an imported say function and relies on a button:
http://jsfiddle.net/entropo/wxTqR/
This is a great way to test your scripts without relying on the log or alerts.
The say function is from jQuery in Action. Excerpt:
Within this function, we employ the services of a small utility function, say() C,
that we use to emit text messages to a dynamically created element on the page
that we’ll call the “console.” This function is declared within the imported support
script file (jqia2.support.js), and will save us the trouble of using annoying and disruptive alerts to indicate when things happen on our page. We’ll be using this handy function in many of the examples throughout the remainder of the book.
Suppose I had the following function:
function alertMesg()
{
alert("This ok function alerts message!");
}
Now at run time I would like to change the alertMesg function to do something else. My thought was to do somehting like this.
var temp = window.alertMesg.toString.replace("ok","great")
temp = temp.replace('function alertMesg()',"");
window.alertMesg = new Function(temp);
Basically, the problem is I have no control over the source in the alertMesg function. I would like to change the function, but I can't actually change the source of it because it is produced server side. That being said, I need it to act differently.
PS: I forgot to mention an important part: I have to keep most of the function. I can't just replace the function out right. I have to keep 95% of the function the way it is, and change the other five percent.
#Barlow Tucker, quixoto, pekka
Thanks, for the interest.
Basically, I don't think the proxy idea will work because I am not just adding functionality, I am changing the functionality of the code. I want for example, the third line of the function to be different. In my real life example I have to add a line right in the middle of a function.
If you must replace the content of a function, it is possible:
function alertMesg()
{
alert ("This ok function alerts my message!");
}
alertMesg(); // alerts "This ok function alerts my message!"
// do whatever you want to the function here
var temp = alertMesg.toString();
temp = temp.replace('my', 'your');
// now replace the original function
alertMesg=new Function(temp.substring(temp.indexOf('{')+1,temp.lastIndexOf('}')));
alertMesg(); // alerts "This ok function alerts your message!"
This probably isn't the best way to do what you're trying to achieve, but I can't really suggest anything else unless you provide more details.
Dynamic code replacement like you're suggesting might work in some cases, but it's a scary road to go down-- fragile, one wrong step and you're busted, and it quickly becomes a maintenance nightmare.
As a commenter said, your cleaner bet is to just wrap the native window.alert and then do the right thing when the string you care about comes through, per the answer here:
JavaScript: Overriding alert()
(Insert standard comment here about how you should get your server side people on the same page/team as you on this so you don't need to hack around your own page.)
UPDATE: You're not asking about alert, you're asking about this problem generally. Yes, you could what others are suggesting. But if you have the original code for the function, why not just replace it entirely? If the function you want is a global function called foo(), you can run JS that does:
window.foo = function() {
// The stuff I know is there (A)
...
// Some new stuff I want to change (B)
...
// More stuff I know is there (C)
}
Which will throw away the original and replace it with your version. This would work reasonably well, although "monkey patching" the stuff in the page definitely comes with some maintenance headaches.
I will definitely note here that if you can't do this for some reason and thus insist on doing textual code replacement in the middle of existing functions, you're abusing the language/environment for the purposes of maintainable anything, and you are truly screwed in multiple ways.
I've been programming for the Web for quite some time now, but have only just recently discovered a few new intricacies regarding the use of functions and the weird (or so I view them as) things you can do with them. However, they seem at this point only to be syntactically pretty things. I was hoping somebody might enlighten me as to how some of these newly discovered aspects could prove to be useful.
For example, the first time I ran this, I thought for sure it would not work:
<script>
function x(q)
{
q(x);
}
x(function(a)
{
alert(a);
}
);
</script>
But it did! Somehow, creating a named function which receives a different, anonymous function as its only parameter and then runs the function passed to it with itself passed as the parameter to it works just fine. This positively blew my mind and I'm almost certain there's a vast amount of practicality to it, but I just can't quite place it yet.
Ah, and another thing I was elated to discover: using a globally scoped variable to store a function, one can later in the execution use JavaScript's eval() function to modify that variable, thus changing the function's inner workings dynamically. An example:
<script>
var f = function()
{
alert('old text');
}
eval('f = ' + f.toString().replace('old text', 'new text'));
f();
</script>
Sure enough, that code alerts the "new text" string; when I saw that, my mind was once again blown, but also immediately intrigued as to the potential to create something incredible.
So... my burning question for Stack Overflow: how can such seemingly abstract coding principles be used in any positive way?
What you're basically asking is How can I use functions as first-class objects?
The biggest and most common usage is closures (or anonymous functions) for event handling. However, just because you can be clever, it doesn't mean you should. Write clear, readable code just as you would in any other language.
Oh, and flog yourself for typing eval and never think about doing it again
The first one, closures, are very common in javascript. If you want some more advanced examples, here's a nice interactive playground you can mess with: http://ejohn.org/apps/learn/.
Here's my window.onload function I use when whatever I'm working on doesn't require a full blown library.
//add events to occur on page load
window.addOnload = function(fn) {
if (window.onload) {
var old = window.onload;
window.onload = function() {
old();
fn();
}
} else {
window.onload = fn;
}
}
Then whenever I need something to happen onload, I can just use an anonymous function. Here's an example from a recent maintenance project of mine.
//make all menu items have a hover property
window.addOnload(function(){
var cells = document.getElementsByTagName('td');
for (var i=0; i < cells.length; i++) {
if (cells[i].className != 'NavMenuItem') continue;
(function(cell){
cell.onmouseover = function() {
cell.className = 'NavMenuItemHighlight';
}
cell.onmouseout = function() {
cell.className = 'NavMenuItem';
}
})(cells[i])
}
});
As for your second 'discovery', just pretend you never found out about it.
Well, the first one is typically how you prove that the Halting Problem is undecidable...
Whether or not you consider that "useful" is entirely up to you, I guess B-)
A few days ago, I asked a question regarding dynamically modifying a function's code midway through the outerlying script's execution and I was told to completely forget ever coming upon the notion. I'm not sure I understand why that is. Let me give an example:
<script>
var display = function(msg)
{
alert(msg);
}
// Now, at the moment, the display() function
// is receiving a single parameter and alerting
// it to the user. I'm now going to use eval()
// to modify the display() function.
eval('display = ' + display.toString().replace('alert(', 'document.write('));
// Now, the display() function writes its parameter
// to the document as opposed to alerting it.
</script>
I realize this is a rather trivial example, but there must surely be some use that can be derived from being able to dynamically modify a function, something so useful by itself.
Although this may do what you need it to do, 6 months from now you (or the person maintaining your code) will be going "WTF?!"
If your use case is to alert or write based on some condition, why don't you write two different functions? Or have your function take another parameter that decides the output mode. Or pass in a function as a parameter that performs the actual output. Something, you know, a little more on the sane side. ;-)
There are cases where it could be useful to change a function's behavior, but there are better ways to do it. In your example, you could create new instances of the function that handle the output differently, by passing a function as an argument (similar to the strategy pattern):
function makeDisplay(displayStrategy) {
return function(msg) {
// I'm assuming you would do some additional processing here...
displayStrategy(msg);
}
}
var display = makeDisplay(alert);
// now modify display to use document.write
display = makeDisplay(function(msg) { document.write(msg); });
Well, using eval might be a security concern but modifying a function in real-time is ok. How else you can make memoization anyway?
Although, come to think of it, changing method signature isn't a great idea, other people won't know how to call this function after this, since it would depend on execution order and it's not easy to track usually.
I have found myself needing to do this in situations where I don't have the source code for a particular piece of vendor javascript; so that could be a legitimate use case. I agree that if you have another option, it's better to do it in a more organised way, editing the original function to be more flexible.