Im doing a project right now where certain elements of the page change depending on the mouse positioning and made some code basing myself off an explanation I saw in Mozilla. I understand most of it, but there is still one part that is bothering me, which is the function parameter. Throughout my learning of basic Javascript, I have never understood parameters despite the countless explanations. What does a parameter do? How does the page know its purpose? To give an example here is the code:
<!doctype html>
<html>
<head>
<title>Change</title>
</head>
<body>
<p id="hurb"></p>
<script>
document.addEventListener('mousemove', movee);
function movee(a) {
var eub = a.clientX;
document.getElementById("hurb").innerHTML = eub;
}
</script>
</body>
</html>
What does a do here? How does the page know what it does?
Can someone please explain this in a way that can be understandable for a beginner? All the other explanations in pages dont really help me out.
Thanks!
The parameter, as its name suggests, is something upon which usually the function's return value depends. Hence, your function can have a parameter that is not used throughout the function. Here is an example:
function foo() {
console.log("foo");
}
function bar(par1, par2, par3) {
console.log("bar");
}
foo(); // foo
bar(); // bar
bar(45,100); // bar
Note that however you call bar() it logs "bar", since the parameter is never used inside the function and hence never contributes to the return value of the function.
In your case, the function is an event handler function, i.e. is called when some event (mousemove in your case) is fired. When an event is fired, the browser passes an Event object (particularly a MouseEvent object in your case) to the event handler function. This event object is a typical JS object, with properties such as clientX, clientY, pageX, pageY, etc.... By defining your function with a parameter, that parameter is going to take the value of the Event object. To access the Event object's properties, you do not need to define a parameter for your function. Hence, this function:
function movee(a) {
var eub = a.clientX;
document.getElementById("hurb").innerHTML = eub;
}
and this one:
function movee() {
var a = event;
var eub = a.clientX;
document.getElementById("hurb").innerHTML = eub;
}
are typical of each other.
How does the page know its purpose?
The page doesn't. All the page does is that it executes your function. If it encounters the parameter, it uses its value. Otherwise, it just continues execution.
Related
Here is the app I'm referring to:
I am trying to fundamentally understand the bind method in Javascript.
My understanding when I play around with it in the console is that bind returns a copy of the function, with "this" bound to whatever you pass into bind.
function logThis(){
console.log(this)
}
logThis.bind({today: 'Tuesday'})
//Will return a copy of the logThis function, with 'this' set to the
{today:'Tuesday'} object. The code does not run right away though.
var explicitlyLogThis = logThis.bind({today: 'Tuesday'});
explicitlyLogThis(); //This will run the code and display the {today: 'Tuesday'} object to the console.
This is my understanding so far. I understand that to actually run this new function that has 'this' explicitly bound using the bind method, you need to set it to a variable and then run it.
I see a contradiction when I look at the app in the above link. If you look at the bindEvents method on line 56, we have .on('keyup', this.create.bind(this)). I understand that we have to set 'this' to App when we run the create method because jQuery defaults to setting 'this' to the jQuery object itself. So this line is actually the same as: $('#new-todo').on('keyup', App.create.bind(App)).
That isn't where my confusion is. My question is:
How exactly are these copies of the functions with 'this' set to App actually being called? The app does not set them to a variable and then call that variable the way I had to when I was working in the console.
It just invokes the bound functions directly as soon as an event occurs on one of the jQuery elements. But I thought writing it this way would just return a copy of the function, and not run the function itself, if I am basing my assumptions on what I have figured out in the code I wrote above. I thought in order to invoke the function immediately, you would need to use call or apply.
I also realize that the app runs the bindEvents method when it starts (see line 46). So I understand that when you start the app, copies of the various functions are created with the correct 'this' bound to the functions. But...when/how do they actually get invoked without assigning them to variables? How are these copies accessed?
I think I have a flawed understanding of the bind method, so I would love some help. Thanks!
It sounds like you understand bind well enough. Perhaps there is some confusion with passing anonymous functions. As you know calling bind returns a new function and this can optionally be stored as a variable or passed as a function argument.
In the example below btn1 accepts a bound function as you've seen. This could also be written in a more long hand fashion with btn2. They're identical. btn3 doesn't receive a bound function, when its clicked its context is the button element, this looses all visibility of MagicalApp fucntions.
<button id="example1">button one bound</button>
<button id="example2">button one bound</button>
<button id="example3">button two unbound</button>
<script>
class MagicalApp {
add() {
console.log('this could do addition');
}
}
const app = new MagicalApp();
function contextOfEvent(event) {
console.log('contextSensitive', this.add)
}
const btn1 = document.querySelector("#example1");
btn1.addEventListener('click', contextOfEvent.bind(app));
const btn2 = document.querySelector("#example2");
const btn2ClickHandler = contextOfEvent.bind(app)
btn2.addEventListener('click', btn2ClickHandler);
const btn3 = document.querySelector("#example3");
btn3.addEventListener('click', contextOfEvent);
</script>
Coming from a C++ background, trying to work with an OO language that doesn't have explicit typing is a little more than a headache.
So I have dynamic elements for a webpage that are "controlled" by objects since there are tons of stuff I need to manage on each for it to work. The element is just the visual output of the data inside of the object itself, that's all I really need it for.
Except that I need the object to perform an internal function when it's clicked. That seems to be the biggest source of my headache thus far.
Javascript:
function onClick(file) //The external onClick function I use to try to get it to call from.
{
file.state = INUSE;
file.checkState();
}
function fileObject () { //The file object itself
this.element;
this.newElement();
//initialize stuff for the object
}
fileObject.prototype.newElement = function() { //creates a new element and sets its event listener
this.element.click(function() {onClick(this)});
}
fileObject.prototype.checkState = function() {/*does stuff*/} //apparently this is "not a function"
The error I get exactly is "file.checkState is not a function" from Firefox's console panel.
I'm still new to javascript, but after doing some debugging, I've come to find out that it's explicitly the onClick(this) function that is causing all of the errors. When used with something else, the onClick function works perfectly, but for some reason, the this keyword doesn't appear to actually be sending the reference to the fileObject since all checks show file being undefined when inside of the onClick scope.
Is there something fundamentally wrong about the way I'm trying to do this or am I just missing a step (or adding something that I don't need) that will help get this snippet working.
So you know, your initial problem isn't actually handling the action, but listening to it. click will trigger a synthetic click event, rather than liste for one.
You want ... .element.addEventListener("click", callback); that said, you face a second problem, immediately thereafter.
I will leave my example code as you've written it to not confuse the matter...
But when you see click( ) know that I mean subscribing with addEventListener, if element really does mean a browser DOM element. If it's not a standard browser element, and your own API, then ignore the previous portion, and carry on.
this is dynamically bound at the invocation time of the function (not at definition time).
The nearest function, scoped above, is your callback function that you are passing into .click( ... ).
Which is entirely different than the this which you mean outside of the callback.
Whatever is on the left-hand side of the dot is the this context for the duration of that particular invocation.
Needless to say, click() doesn't know enough to bind the this you mean, to the left-hand side of your callback.
The solution (or one of many) is to use lexical scoping and/or closure to retain the value of the object you mean.
// easy but messier
var fileObject = this;
... .click(function () { onClick(fileObject); });
// Cleaner with thunks:
function clickHandler (onClick, obj) {
return function () { onClick(obj); };
}
... .click(clickHandler(this));
Coming from c++ the way Javascript handles this will seem a little crazy, it looks like here you need to tell the function you've defined what this is - like so:
this.element.click(function() {onClick(this)}.bind(this));
I don't understand some parts of JavaScript code regarding parameters. I found this example on W3schools:
<!DOCTYPE html>
<html>
<body>
<a id="myAnchor" href="http://w3schools.com/">Go to W3Schools.com</a>
<p>The preventDefault() method will prevent the link above from following the URL.</p>
<script>
document.getElementById("myAnchor").addEventListener("click", function(event){
event.preventDefault()
});
</script>
</body>
</html>
I am confused with event parameter inside function. This code works although event parameter didn't become an argument, that is, it doesn't have any value. How can this "empty" parameter be used with a method. Why this code works? I am new to JavaScript so any simple answer would be appreciate.
Slit,
The function which is being called on "click" event is a "call-back" function. Once the event "click" raises then the anonymous "call-back" function which is "function(event){" is being called immediately with 1 parameter which is "event". In order to determine the parameters which will the anonymous function called with you should refer to documentation.
After you find the parameters, you may use and work with them inside this function, for example add "event.preventDefault(); alert('test')" and nothing will happen when you click on element, only popup window with "test" will arise.
Don't hesitate to ask any questions so I can improve my answer.. Just tried to explain in high level.
This function is also known as a callback. A callback is when you pass one function as an argument to another.
Try testing this code and then click anywhere on the page:
window.addEventListener("click", click);
function click() {
console.log(arguments);
}
If you open the console you should see [MouseEvent]. The special arguments object returns all the arguments received by the function. The click function received only one argument MouseEvent because the window method addEventListener sends an event to the event handler.
Here's a similar example:
init("abc", logArgs); //--> "abc"
init("abc", logDog); //--> "dog"
function logArgs(x) {
console.log(x);
}
function logDog(x) {
console.log("dog");
}
function init(x, callback) {
callback(x);
}
The confusing part about your example is that you can send a function an anonymous function. An anonymous function is one that is not named. Using the above example, you could do this:
init("abc", function(y) { //the y parameter comes from the init function
console.log(y); //"abc"
});
function init(x, callback) {
callback(x); //send the first argument to the anonymous function
}
I've been reading just about every article I can get my hands on about JavaScript scope to better understand it. I'd like to perfectly understand it by the end. I'm currently reading this article: http://www.digital-web.com/articles/scope_in_javascript/ and I've just finished reading the "Complications" section (a little more than halfway down) and thought it was very helpful, but not quite clear enough.
It uses the following code and considers the onclick behavior of the_button:
function BigComputer(answer) {
this.the_answer = answer;
this.ask_question = function () {
alert(this.the_answer);
}
}
function addhandler() {
var deep_thought = new BigComputer(42),
the_button = document.getElementById('thebutton');
the_button.onclick = deep_thought.ask_question;
}
window.onload = addhandler;
The article states ... an event handler[,] runs in a different context than when it’s executed as an object method. So, if I'm to understand correctly, then the call to the ask_question method in context of the script's object method is deep_thought.ask_question, making this deep_thought. But when an event in the DOM is triggered, then the call chain changes to DOMelement.eventHandler.deep_thought.ask_question making this DOMelement?
That is correct! 'this' in event handlers is the element you bound to. In this case it would be the_button. The alert would be 'undefined' as the_button has no the_answer property.
You can see an example at: http://jsfiddle.net/zG7KR/
See what this outputs:
this.ask_question = function () {
alert(this.the_answer);
};
The question
In Javascript, how can an event handler function refer to members of its parent? i.e. can you define an event handler function part of a larger object and have that function "know about" its parent?
(Note that someone else posted a nearly identical question Accessing variables of parent function in Javascript event handlers . It hadn't been answered. Hence the repost )
Erroneous Presuppositions
I had thought that at "function definition" time you could capture a copy of "this" for later re-use, (e.g. copy to "self"). Evidently I was wrong: after I bind the function to the event ("click()" below), "self" subsequently refers to the html anchor tag ('');
The general context :
trying to use encapsuation/object-orientedness for code-re-use in javascript.
Example
Here's a simple example (cribbed from elsewhere and modified).
The function succeeds when called during page load, but fails when the user preses "click"
MY LINK
<script type="text/javascript">
var Construct = function() {
var self = this;
this.attr1 = 3;
this.attr2 = 2;
this.childObj = {
method1: function () {
// this function fails if called from an event handler
// edited this function to "do something", i.e. provide a visual cue upon execute
var foo = self.attr1 * self.attr2;
alert ('value is ' + foo);
return foo;
}
}
}
var obj = new Construct();
// this call succeeds
alert (obj.childObj.method1());
//this call fails as soon as the event handler refers to "self"
$("#myLink").click(obj.childObj.method1);
</script>
</body>
</html>
Update/Edit
-Updated the example to give a 'visual cue' when it runs
-added this section.
My error. As pointed out below, the example works fine. My original, non-working code used this:
this.self = this
instead of
var self = this
I didn't realize the distinction (in Java they would be identical) and missed the fact that my example actually worked, (whereas my code failed).
Your code works fine. self refers to the object as it is supposed to. That's how the lexical scoping of javascript is defined.
The problem is your handler does nothing. method1 simply returns 6 but you never tell it do anything with that value. If you want to prove it to yourself, the line before the return, add an alert: alert(self.attr1 * self.attr2);
Working Example