i have a question, there is a problem with a function in a program that i was doing in javascript.
The function is supposed to work when you click on a paragraph, but when i click, the javascript console throws this: "Uncaught ReferenceError: donethingy is not defined
Line: 1".
JS:
window.onload = function(){
var thy = document.getElementById("thy");
var commanderIssue = document.getElementById("commanderIssue");
var listado = document.getElementById("thaCosa");
var thyLy = document.getElementsByTagName("p");
var nli;
var thyText;
var inserting = "a";
var commander = "b";
thy.onclick = function(){
inserting = "* " + prompt("Create a new item");
nli = document.createElement("p");
thyText = document.createTextNode(inserting);
nli.appendChild(thyText);
listado.appendChild(nli);
thyLy = document.getElementsByTagName("p");
}
thyLy.onclick = function donethingy(){
// thyLy.textDecoration.overline;
alert("done");
}
commanderIssue.onclick = function(){
alert("this thing is");
}
}
With the syntax you've used, the name donethingy doesn't actually become the name of the function because you are assigning the funciton's code directly to the onclick property of thyLy.
You could do this:
// This is a function declaration that associates a name with the function
function donethingy(){
// thyLy.textDecoration.overline;
alert("done");
}
// Then the function can be referred to or invoked by name
thyLy.onclick = donethingy;
But, when you create and assign the function in one statement, the function effectively becomes anonymous as it is stored and accessible via the property you assigned it to.
The decision to create a function declaration or an anonymous function requires you taking the following into account:
Anonymous functions can't easily be reused.
Anonymous functions can't easily be unit tested.
Named functions may require more memory, but can be reused and can be
easily unit tested.
You do not set variables or onclick properties to functions defined as:
obj.onclick = function <name>() {}
You set to anonymous functions, like you did for commanderIssue.onclick.
Just remove the name of the function to make it anonymous:
thyLy.onclick = function() {
alert("done");
}
It's good to remember that there are two ways of defining functions:
Declarations, which are executed when you invoke them:
function donethingy() { ... }
Expressions, which are executed when variable statements are executed:
thyLy.onclick = function() { ... }
Related
I'm trying to understand the difference between 2 different function declarations in JavaScript.
Consider the following code snippet:
function SomeFunction(){
this.func1 = function(){
}
function func2(){
}
}
What is the difference between the declarations of func1 and func2 above?
In simple language,
fun1 is a property of SomeFunction class holding a reference of anonymous function where func2 is named function.
Property
Here fun1 is property of that SomeFunction class, it means when you create instance of SomeFunction class using new keyword, then only you can access it from outside.
Private Method
Here fun2 will work as private method of class SomeFunction, and will be accessible inside that class only.
Sample
function SomeFunction() {
this.func1 = function() { console.log("in func1") }
function func2() { console.log("in func2") }
}
var obj = new SomeFunction();
obj.func1(); //Accessible
obj.func2(); //Not accessible
This way of declaring functions is called Function Expression. This kind of functions can be called only after definition of the function. Function expressions load only when the interpreter reaches that line of code.
var func1 = function() {
// Code here
}
This way of declaring functions is called Function Declaration. Function declarations load before any code is executed. So it can be called anywhere in the program before it's definition. For reason, read about Hoisting in Javascript
func1 () {
// Code here
}
When defining these inside another function, Function Expression acts as the property of the function and can be accessed using the object of the parent function. Whereas, the scope of Function Declaration is inside the parent function, so it is not accessible from outside the parent function. This is a very important property in Javascript using which we can simulate the Object Oriented Nature.
In brief, Function declaration acts as Private method of a class and Function Expression as Public method.
Here is the working example below to understand more about it.
function SomeFunction(){
this.func1 = function() {
console.log('Public function.')
}
function func2() {
console.log('Private function.')
}
this.func3 = function() {
func2();
}
}
var obj = new SomeFunction();
obj.func1(); // Public Function.
// Can be accessed as it is a Public function
obj.func3(); // Private Function.
// Can be used to access a private function.
obj.func2(); // Error: Uncaught TypeError
// Private function
Hope this helps! :)
function SomeFunction() {
// Function Expression
this.func1 = function() {
}
// Function Declaration
function func2() {
}
}
Update:
Based in your question: What is the best way to declare functions within a Javascript class?
In OOP programming a Class has attributes and methods.
In the following sample code, the Person class contains:
(2) Attributes:
name
country
(1) Method:
showPerson1()
function Person(name, country) {
// Attributes of Person class.
this.name = name;
this.country = country;
// Function Expression:
this.showPerson1 = function() {
var personMessage = "Hi, my name is ";
personMessage += this.name;
personMessage += ". I'm from ";
personMessage += this.country;
personMessage += ".";
return personMessage;
};
// Function Declaration:
function showPerson2() {
var personMessage = "Hi, my name is ";
personMessage += this.name;
personMessage += ". I'm from ";
personMessage += this.country;
personMessage += ".";
return personMessage;
}
}
var person1 = new Person("John", "United States");
console.log(person1.showPerson1()); // Prints: Hi, my name is John. I'm from United States.
console.log(person1.showPerson2()); // Throws an error.
As you can see, you can execute the showPerson1() method because is reference to the Person class by using this keyword and using the Function Expression style.
However, you can't execute showPerson2() method because this function was not created like a reference to the Person class.
You can find more information here.
As far as I know your question revolves around scope. Let's say for a second that you had a main class that called upon functions from other classes. Maybe these other classes have a function called func1 that you needed to use. But wait, you want to use the name func1 in your main class as well without mentioning the global function from the other class. Using this.func1 would allow you to access it as a local function, since .this refers to a local scope.
Basically, it allows him to store the result of the function without declaring a separate variable, which is nice since it's only probably going to be used temporarily and in the context of the function in which it was declared.
Additional Reading (Or in case my analogy falls flat):
http://javascriptissexy.com/understand-javascripts-this-with-clarity-and-master-it/
https://www.w3schools.com/js/js_function_invocation.asp
The func1 is actually a property on SomeFunction so essentially you can do
const someClass = new SomeFunction();
someClass.func1()
But you cannot do
const someClass = new SomeFunction();
someClass.func2()
because it is not attached to that class. However, you can still use the func2 internally in your class SomeFunction but not outside the class.
ES6 provides more clean syntax to understand this.
class SomeClass{
func1(){
//function body
}
}
Hope this helps
Background
I want a function keeping track of its own state:
var myObject = {
myFunction: function () {
var myself = this.myFunction;
var firstTime = Boolean(!myself.lastRetry);
if (firstTime) {
myself.lastRetry = Date.now();
return true;
}
// some more code
}
}
The problem with the above code is that the value of this will depend on the site of the function call. I want the function to be able to refer to itself without using:
myObject.myFunction
.bind()
.apply()
.call()
Question
Is it possible to give a function this kind of self awareness independent of its call site and without any help from external references to it?
If you want to store that state on the function instance, give the function a name, and use that name within it:
var myObject = {
myFunction: function theFunctionName() {
// ^^^^^^^^^^^^^^^--------------------- name
var firstTime = Boolean(!theFunctionName.lastRetry);
// ^--------------------------- using it
if (firstTime) {
theFunctionName.lastRetry = Date.now();
// ^------------------------------------------------ using it
return true;
}
// some more code
}
};
You'd do that whenever you want to use a function recursively as well. When you give a name to a function that way (putting the name after function and before (), that name is in-scope within the function's own code. (It's not in-scope for the code containing the function if it's a function expression, but it is if it's a function declaration. Yours is an expression.)
That's a named function expression (where previously you had an anonymous function expression). You may hear warnings about NFEs, but the issues various JavaScript implementations had with them are essentially in the past. (IE8 still handles them incorrectly, though: More in this post on my blog.)
You might consider keeping that state somewhere private, though, via an IIFE:
var myObject = (function(){
var lastRetry = null;
return {
myFunction: function() {
var firstTime = Boolean(!lastRetry);
if (firstTime) {
lastRetry = Date.now();
return true;
}
// some more code
}
};
})();
Now, nothing outside that outer anonymous function can see lastRetry at all. (And you don't have to worry about IE8, if you're supporting stubborn XP users. :-) )
Side note: The unary ! operator always returns a boolean, so your
var firstTime = Boolean(!theFunctionName.lastRetry);
...is exactly equivalent to:
var firstTime = !theFunctionName.lastRetry;
...but with an extra unnecessary function call. (Not that it hurts anything.)
Of course you can, simply give your function an internal named representation and it can refer to itself from there. For example...
var obj = {
doThings:function doThingsInternal(arg1, arg2) {
console.log(arg1, arg2);
for (var arg in doThingsInternal.arguments) {
console.log(arg);
}
}
};
obj.doThings('John', 'Doe');
You could use a simple Closure, if you are not too bent on keeping state existence knowledge within the function. But I guess you don't want that. Another way to do this could be changing the function itself on the first call. Benefits, no/less state variables needed and no costly checks on subsequent calls! -
var myObject = {
myFunction: function () {
// Whatever you wanna do on the first call...
// ...
// And then...
this.myFunction = function(){
// Change the definition to whatever it should do
// in the subsequent calls.
}
// return the first call value.
}
};
You can extend this model to any states by changing the function definition per your state.
I'm trying to learn some OOP, so bear with me. I need to use a variable I defined in one function, elsewhere. Here is my example code (I want INTERCEPT!! to be logged, but it returns undefined):
function Talk() {
var greeting;
var pleaseStop; // declare it
this.A = function () {
greeting = 'hello';
console.log(greeting);
var intercept = function () {
pleaseStop = 'INTERCEPT!';
}
}
this.B = function () {
greeting = 'goodbye';
console.log(pleaseStop); // this returns undefined!
console.log(greeting);
}
}
var activateTalk = new Talk();
activateTalk.A();
activateTalk.B();
This whole code logs the following:
hello
undefined
goodbye
I have also tried intercept.pleaseStop() but it still returns undefined. Would anyone know of a solution?
EDIT:
I've removed the var the second time, but it still returns undefined:
http://jsfiddle.net/d654H/2/
var pleaseStop = 'INTERCEPT!';
You're declaring a new, function-local variable here; drop the var to assign to the existing variable in scope.
Then, you need to actually call intercept; at the moment you only define it.
It's your choice as to when you call that function; in this live example I simply do so immediately after the definition, for the purposes of exposition.
Remove var in front of the assignment to pleaseStop.
This assigns a new value to the pleaseStop declared inside the constructor, which is visible also from inside B:
var intercept = function () {
pleaseStop = 'INTERCEPT!';
}
This declares a new local variable pleaseStop, completely unrelated to the other pleaseStop, that is not visible outside intercept:
var intercept = function () {
var pleaseStop = 'INTERCEPT!';
}
If you do the latter instead of the former, you end up changing the value of another variable than the one you intended.
Your problem is you never set pleaseStop. You have declared intercept as a function, but you never called it. Therefore, pleaseStop is undefined.
Firstly you have't called intercept() anywhere and also u did something
var pleaseStop = 'INTERCEPT!';
which will create new variable instead of initializing global variable
You can do something like this
function Talk() {
var greeting;
var pleaseStop; // declare it
this.A = function () {
greeting = 'hello';
console.log(greeting);
var intercept = function () {
pleaseStop = 'INTERCEPT!';//changed
}
intercept(); //..Added
}
this.B = function () {
greeting = 'goodbye';
console.log(pleaseStop); // this returns undefined!
console.log(greeting);
}
}
var activateTalk = new Talk();
activateTalk.A();
activateTalk.B();
Without var keyword.
var pleaseStop = "A";
function foo(){
pleaseStop = "B"; // overwriting to "B"
}
foo();
alert(pleaseStop); // shows "B"
With var keyword.
var pleaseStop = "A";
function foo(){
var pleaseStop = "B"
// This defines a new variable 'pleaseStop'
// in the scope of function foo(){}.
}
foo();
alert(pleaseStop); // shows "A"
Variable Scope
JavaScript has function-level scope. In most languages which have block-level variable scope, variable are accessible whithin their block surrounded by curly brackets ({and}). But JavaSciprt doesn't terminate scopes at the end of blocks, but terminate them at the end of functions.
I'm sure there are many articles and documents about it. I googled it and found an intresting introductory article.
http://javascriptissexy.com/javascript-variable-scope-and-hoisting-explained/
Hope this helps.
I am new to javascript and I have written a code like this
file myclass.js
//----------------------------------------------
function myclass () {
this.functionA = function (value) {
var _this = this;
_this.functionB ();
}
this.functionB = function () {
// here I am using the value passed to functionA when it is called.
alert(value);
}
}
//------------------------------------------------------------------
file main.js
//-----------------------------------------
mc = new myclass();
mc.functionA (45);
//-------------------------------------
Here I am totally confused that I am my main file I have called a functionA passed an argument and When I have called functionB in functionA I haven't passed the argument in functionB but still I am able to access it.
Can any one kindly explain that how is it possible ??
P.S value is not global and not used any where else
Thanks
I can't reproduce your behavior but I assume that you have another variable defined in the outer scope called value which is passed to functionA as a parameter. So what you see is not one but two variables with the same names and values.
Something like that:
function SomeConstructor() {
var value = 'Surprise'; // * VALUE_1
this.functionA = function (value) { // VALUE_2
var _this = this;
_this.functionB ();
}
this.functionB = function () {
// Here you're using the value from starred line above
// VALUE_1
alert(value);
}
// Here you also pass the same value and later assumes that
// functionB sees it as a parameter (VALUE_2)
functionA(value);
}
Notice that if you rename value parameter for functionA and the value variable in the outer scope all confusion goes away:
function SomeConstructor() {
var value1 = 'Surprise';
this.functionA = function (value2) {
var _this = this;
_this.functionB ();
}
this.functionB = function () {
// Here you're using the value from starred line above
alert(value1);
}
// Here it's clear that the parameter you're passing is not used at all
functionA(value1);
}
Check your code and see if that's the case.
Edit: After you've edited your question I still can't reproduce your case. Check if that's the only script on a page. Perhaps, you have some browser addons or extensions installed that add the code to your page. In Chrome Dev Tools I get:
"ReferenceError: value is not defined"
I understand the concept of variable scope in the following example, but can someone explain the function-wrapping syntax (...)();, e.g. how do you use it in actually day-to-day JavaScript programming? It's not something that I know from PHP/Java/C#.
window.onload = function() {
var i = 4;
console.log(i); //4
(function showIt() {
var i = 'whatever';
console.log(i); //whatever
})();
console.log(i); //4
};
There are several ways in which this form is useful. One is to lexically scope a segment of code so that its inner variables and methods stay separate from the larger body of code that contains it. In this way, it's JavaScript's way of doing block scoping. But the most common way I use this format is as an alternative to this:
var ret = {
depth:0,
initialized:false,
helper:function() { /*help with some stuff*/ },
initialize:function(){ /*do some initialization code*/ },
action:function(){/*do the thing you want*/}
destroy:function() { /*clean up*/ }
}
The thing that absolutely kills me about this format is it is extremely time consuming to find missing braces and commas. For example, the code above won't work because the's no comma at the end of the action declaration and unless I had pointed it out, you'd have had a hard time finding the problem because when the exception is thrown, it's thrown on the entire statement, not the section that's "causing the problem". This is such a predictable problem that I simply don't use this format any more if I can possibly avoid it. I refuse. Instead, the same can be written much more clearly as:
var ret = (function(){
var self = {},
initialized = false;
var helper = function() { /*help with some stuff*/ };
self.depth = 0;
self.initialize = function() {/*do some initialization*/};
self.action = function() {/*do the thing you want*/};
self.destroy = function() { /*clean up*/ };
return self;
}());
There are two big advantages for me. One, missing braces and commas can be found more easily (when the exception is thrown, the line number will be close to the area where it's missing). And two, you can choose to keep some variables and methods private and you retain all the benefits of the first block of code.
And the last plug I'll give for this format is that the code above (which is sort of like a Singleton) can be converted into a constructor by 1) removing the invocation braces on the outside, 2) changing self = {} to self = this, and 3) optionally removing the return self at the end:
var Ret = function(){
var self = this,
initialized = false;
var helper = function() { /*help with some stuff*/ };
self.depth = 0;
self.initialize = function() {/*do some initialization*/};
self.action = function() {/*do the thing you want*/};
self.destroy = function() { /*clean up*/ };
return self; // this is ignored by the compiler if used as a constructor
};
var ret = new Ret();
This is defining a function showIT (using function showIT() {...}) similar to what you're already familiar with. The () at the end directly invokes the function in the same line as it is defined. That's probably the part that is new to you. Just like you'd say showIT() to invoke the function, you can replace the name with the actual definition and it'll work in Javascript.
JavaScript has function literals. All it's doing is making a function literal, and calling the result of the expression. Is the name what's confusing you? All a name would be used for is referring to the function inside its own body, and it's optional. (Note that that's not compatible with IE 8 and earlier.)
Unlike in C where variable names have block scope, JavaScript (like Pico) has only function scope.
So if you want to create a new name scope you can't just use { ... } as you could in C, you have to use (function() { ... })();.