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"
Related
I am developing a widget inside a framework so that I would need to log variable "a" using a pattern like the one below. How do I "call" this function log_a so it can access the variable declared in the execution context it is called from? i.e. Have the console output "a value", instead of the current error of not able to find variable "a".
(function(global) {
global.log_a = function() {
console.log(a);
};
}(window));
var anotherFunction = function() {
var a = 'a value';
log_a();
};
anotherFunction();
edit:
I tried to make the example simple to make the question easier to follow but I now see it led to confusion. Update with more clarifications:
The first part of the code is trying to emulate my effort of moving large functions to a different file for cleaner code.
I am using a library where one input is a function and it will always pass one parameter to it, so I have no option of adding extra arguments (i.e. the answers suggesting to put "a" as an argument).
The trick of declaring "a" as global works and it is what I am currently using, but I thought this wasn't the best practice.
So my questions is (I am guessing the answer is "it is not possible") if there is some way to call log_a so it behaves like if the code was like this:
var anotherFunction = function() {
var a = 'a value';
var log_a = function() {
console.log(a);
};
};
anotherFunction();
You can use function arguments to pass the value of a to your log_a method. The issue that you are currently happening is that var a = 'a value' is unknown to the log_a as it is defined within another function. This is because a variable declared with var in a function scope cannot be accessed outside that function scope. Thus, you are better of doing something such as the following:
(function(global) {
global.log_a = function(a) { // retrieve 'a' as an argument in the log_a method
console.log(a); // print the argument passed through
};
}(window));
var anotherFunction = function() {
var a = 'a value';
log_a(a); // pass through 'a' into the `log_a` method
};
anotherFunction();
You can pass variable a value from that function so log_a() function can access that variable value.
(function(global) {
global.log_a = function(a){
console.log(a);
};
}(window));
var anotherFunction = function() {
var a = 'a value';
log_a(a);
};
anotherFunction();
Variable a exists only in the scope of function anotherFunction;
(function(global) {
global.log_a = function() {
console.log(a);
};
}(window));
var anotherFunction = function() {
// var a exists only here, inside this function
var a = 'a value';
// log_a is another function, it has its own scope,
// and it doesn't know about var a
log_a();
};
anotherFunction();
You can either pass the variable a as an argument to log_a, like log_a(a) inside anotherFunction, or make the variable a available to both anotherFunction and log_a functions:
var a = 'a value';
(function(global) {
global.log_a = function() {
console.log(a);
};
}(window));
var anotherFunction = function() {
log_a();
};
anotherFunction();
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() { ... }
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 had (approximately) this situation: I was trying to declare func1() function and add couple of static methods to it in one go by running it through _init() function providing a hash with properties to attach to it, not being aware of that it didn't remain declared in current scope after _init() function did it's job. It just got temporarily defined, and gc-ed after _init() run (as far as I'm aware). Here's the code sample:
//
// #_init
// merge src{} into target{}, overwriting
//
var _init = (function (target, src) {
var _ = this;
if (_.isobj(target))
_.keys(src).forEach(_.pass, {
src : src,
target : target
});
return target;
}).bind({
isobj : (function (node) {
return node === this(node);
}).bind(Object),
keys : (function (node) {
return this.keys(this(node));
}).bind(Object),
pass : function (field) {
this.target[field] = this.src[field];
}
});
, and I was hoping to 'batch-init' it here adding static methods at the same time:
_init(function func1 (e) {
var _api = func1.pop(arguments);
var node = this;
// and stuff...
}, {
pop: Function.prototype.call.bind(Array.prototype.pop),
// ...etc
});
When trying to reference it later I got error:
x = func1();
// ReferenceError: func1 is not defined
// x = func1()
Assigning the output of _init() to var func2 does the job, I can reference and use the function. Thing that confuses me is when console.log()-ing the func2 logs 'func1()', but trying to refernce func1 directly throws ReferenceError:
//
// #func2
//
var func2 = _init(function func1 () {
return func1.pop(arguments);
}, {
pop: Function.prototype.call.bind(Array.prototype.pop)
});
console.log(typeof func2, func2, func2(1,2,3));
// function func1() 3
console.log(func1(1,2,3));
// ReferenceError: func1 is not defined
// console.log(func1(1,2,3));
//
Could someone explain to me why the func1 reference didn't get created, but (strangely) was availble to func2 (it obviously was able to use it...)?
Could someone explain to me why the func1 reference didn't get created, but (strangely) was availble to func2 (it obviously was able to use it...)?
That's just how named function expressions work. Their name (func1) is available inside the function body as an identifier, but not outside. What happens to the result of the expression (passing the created function to _init, then assigning it to func2) is a different and completely unrelated thing.
I was trying to declare func1() function and add couple of static methods to it
You shouldn't, unless those static methods are really supposed to be public and not just simple helper methods. Use the revealing XY pattern (IEFE) and just get your utility functions in the closure scope:
var _init = (function() {
function isobj(node) {
return node === Object(node);
}
function pass(field) {
this.target[field] = this.src[field];
}
var keys = Object.keys;
return function (target, src) {
if (isobj(target))
keys(src).forEach(_.pass, {
src : src,
target : target
});
return target;
};
});
var func2 = (function() {
var pop = Function.prototype.call.bind(Array.prototype.pop);
return function func1 () {
return pop(arguments);
};
});
Basically I want to do this:
someFunction() // do something
someFunction.somePropertyFunction()
someFunction() // Now someFunction is modified; it should now exhibit a different behaviour
Is this possible?
EDIT:
I'm not looking for what #Kolink was suggesting. Basically I want to augment a function's functionality by calling one of it's property function.
Specifically, I need to: 1. have access to the original function inside my property function (which is entirely doable using this), and 2. bind a new function to the original function's name (which I'm not sure if it's possible).
Just to be clear, I don't have access to the internal definition of the function that I want to augment. I want to attach a function to Function.prototype (so that it will be available as a property of the function that I want to augment), and then I will call func.augmentThis(), and then func should be augmented. But I'm not sure how, hence the question :P
Easily. Here's an example:
var derp = 123;
someFunction = function() {alert(derp);};
someFunction.somePropertyFunction = function() {derp = 456;};
someFunction(); // alerts 123
someFunction.somePropertyFunction();
someFunction(); // alerts 456
Okay, that's an oversimplified example, but yeah, it's entirely possible.
If your question is whether a function attached as a property to another function has a way to access the function to which it is attached, the answer is no. After all, the same function could be attached to any number of functions of objects.
So one alternative is to explicitly refer to the "mother" function within the function that is attached to it and intended to change its behavior:
function f (n) { alert (n + f.offset); }
f.offset = 0;
f.change_offset = function (i) { f.offset = i; };
f (1); //1
f.change_offset (100);
f (1); //101
Here, f is hard-wired into the definition of change_offset. If this bothers you, or you want something slightly more general, write a little routine to set a function as a property on another function, while binding its this to the function being attached to:
function set_func_as_func_prop ( propname, func_to_set, func_to_set_on ) {
func_to_set_on[propname] = func_to_set.bind(func_to_set_on);
}
Now you can write the function more generally
function change_offset (i) {
this.offset = i;
}
and set it on f or any other function.
set_func_as_func_prop ("change_offset", change_offset, f);
set_func_as_func_prop ("change_offset", change_offset, g);
Sort of:
function someFunction() {
return realFunction.apply(this, arguments);
}
function someFunctionA(name) {
return 'Hello, ' + name + '!';
}
function someFunctionB(name) {
return 'Goodbye, ' + name + '...';
}
var realFunction = someFunctionA;
someFunction.somePropertyFunction = function () {
realFunction = someFunctionB;
};
Sure it's possible. It's not recommended, but it's possible. For example:
function a() {
alert("a");
}
function b() {
alert("b");
}
function c() {
return c.f.apply(this, arguments);
}
c.f = a;
c.toggle = function () {
c.f = c.f === a ? b : a;
};
Now let's test it:
c(); // alerts "a"
c.toggle();
c(); // alerts "b"
See the demo: http://jsfiddle.net/LwKM3/
I want to attach a function to Function.prototype. Then I need to bind a new function to the original function's name (which I'm not sure if it's possible).
That indeed is impossible, you don't know what refers to the function. And you cannot change the internal representation of a function, which is immutable.
The only thing you can do is to create a new function and return that, to let the caller of your method use it somehow - specifically assigning it to the original variable:
somefunction = somefunction.augmentSomehow();
Your method for that will look like this:
Function.prototype.augmentSomehow = function() {
var origFn = this;
return function() {
// in here, do something special
// which might include invoking origFn() in a different way
};
};
Not sure if this helps, but I would implement described problem in following way:
// defined by somebody else - unknown to developer
var someFunction = function() {
alert("this is initial behavior");
}
someFunction(); // returns "this is initial behavior"
// defines parent object on which someFunction() is called
var parentObject = this; // returns window object (as called direclty in the
// browser)
// if you are calling someFunction from some object (object.someFunction())
// it would be:
// var parentObject = object;
// augumentThis definition
someFunction.augumentThis = function() {
var newFunction = function() {
alert("this is changed behavior");
};
parentObject.someFunction.somePropertyFunction = function() {
parentObject.someFunction = newFunction;
parentObject.someFunction();
};
};
someFunction.augumentThis(); // change function behavior
someFunction(); // "this is initial behavior"
someFunction.somePropertyFunction(); // "this is changed behavior"
someFunction(); // "this is changed behavior"