I'm trying to create a generic function ('displayFuncName()' for example) that I could call in different function definitions (for example 'foo()'), so it will console.log the function name ('foo' in this example).
something like:
var displayFuncName = function(){
console.log("caller function name: " + some parameter);
}
var foo = function(){
displayFuncName(); // should console log "caller function name: foo
}
I know it was asked in different ways in the past, but it seems like there was some deprecated option, and some of them just shows the 'displayFuncName' function name, which is of course not what I want.
Since arguments.callee throws an error in strict mode and arguments.caller is no longer supported, maybe something like that will be a better option for you:
Function.prototype.logName = function() {
var fn = this;
return function() {
console.log(fn.name);
return fn.apply(this, arguments);
}
}
var f = function named() {}.logName();
f(); // logs `named`
In this way, you can call the logName for every function you want to log name for when it's called.
console.log("caller is " + arguments.callee.caller.name);
Wouldn't it be easier to have the function name (or the function itself if you are to use theCallerFunction.name)?
This will give you the exact same results, just in a much easier way. It's also much less likely that .name will be depreciated.
var displayFuncName = function(callerFunc){
console.log("caller function name: " + callerFunc.name);
}
var function = foo(){
displayFuncName(foo);
}
"arguments.callee.caller.name" is depreciated I believe.
Instead of calling a generic function from every method, you can use something like
arguments.callee.caller.name
This will give you the name of the function who called your function.
If you use this in your generic method, then that will give you the name of the function in which you want to know the caller. But, if you have a common assumption that you want to know the caller of your caller, the you can use something like this.
firstFunction();
function firstFunction(){
secondFunction();
}
function secondFunction(){
whoCalled();
}
function whoCalled(){
alert("caller is " + arguments.callee.caller.arguments.callee.caller.name);
}
var displayFuncName = function(){
console.log("caller function name: " + arguments.callee.caller.name );
}
function foo(){
displayFuncName(); // should console log "caller function name: foo
}
foo();
or else if you want the whole function then you can use
var displayFuncName = function(){
console.log("caller function name: " + arguments.callee.caller.toString());
}
var foo = function(){
displayFuncName(); // should console log "caller function name: foo
}
foo();
Whichever suits your requirement.
One solution would be this:
var displayFuncName = function(o) {
console.log(o.name);
}
var foo = function(){
displayFuncName(foo);
console.log(foo.name); // also possible
}
foo();
But you can find way more solutions.
See here.
Related
I'm pretty sure this is n00b question, but I'm completely new to javascript. I'm wondering why this code only prints "hello" but when I comment out the first function, that's when I get the second function to print the other two words. How does this make sense?
var function1 = createFunction();
function createFunction()
{
console.log("hello");
}
function1();
function createFunctionPrinter(word)
{
console.log(word);
}
var printSample = createFunctionPrinter('sample');
var printNoo = createFunctionPrinter('noo');
printSample(); //should console.log('sample');
printNoo(); //should console.log('noo');
function1 is the return value of calling createFunction which is undefined because createFunction has no return statement.
undefined is not a function, so calling function1() raises an exception and execution halts.
If you want to refer to an method, you should leave the (), as the function call return undefined.
See this example
function createFunction()
{
console.log("hello");
}
var function1 = createFunction;
function1();
function createFunctionPrinter(word)
{
console.log(word);
}
var printSample = createFunctionPrinter;
var printNoo = createFunctionPrinter;
printSample('sample'); //should console.log('sample');
printNoo('noo'); //should console.log('noo');
Fixing function1 and createFunction() should be easy, provided the fact no arguments are needed for this. Simply set var function1 = createFunction without () and you it will effectively make function1 call createFunction as if that was the function's name.
createFunctionPrinter() is a bit different. My preferred approach is the use of a prototype, which will take an argument (word) when called, and then when you call its print() method, it will essentially print your text. The assignment of printSample and printNoo is similar, but you have to use the new keyword. Finally, to make the functions print, use something like printSample.print().
function createFunction() {
console.log("hello");
}
function createFunctionPrinter(word) {
this.word = word;
this.print = function() {
console.log(word);
}
}
var function1 = createFunction;
function1();
var printSample = new createFunctionPrinter('sample');
var printNoo = new createFunctionPrinter('noo');
printSample.print();
printNoo.print();
P.S.: This might not the intended use of prototypes, but I believe it will make your life easier to use them in this case.
var function1 = createFunction();
function createFunction()
{
// return a function that prints a message
return function() {
console.log("hello");
}
}
function1();
I'm new to Javascript's Object Oriented programming (from C++ area).
I want to know the best practice of calling member function from constructor.
Following is a working piece of code:
Obviously the "initialize" is declared ahead of the invocation "this.initialize();"
function Foo() {
this.initialize = function() {
alert("initialize");
};
this.hello = function() {
alert("helloWorld");
this.initialize();
};
this.initialize();
};
var f = new Foo();
f.hello();
If I change the code as following, it will fail at "this.initialize();".
Question 1 Why is that? Won't the Javascript Engine firstly read in all member function declarations of an object?
function Foo() {
this.initialize(); //failed here
this.initialize = function() {
alert("initialize");
};
this.hello = function() {
alert("helloWorld");
this.initialize();
};
};
var f = new Foo();
f.hello();
Then I made the change like this.
The function "initialize" is executed on construction, however, the calling for "this.initialize()" in function "hello" failed.
function Foo() {
this.initialize = function() {
alert("initialize");
}();
this.hello = function() {
alert("helloWorld");
this.initialize(); //failed here
};
};
var f = new Foo();
f.hello();
Question 2: is the first piece of code the only way of calling member function from the constructor?
Update:
if I have to define a function before using it, Question 3: why following code works?
function Foo() {
this.hello = function() {
alert("helloWorld");
this.initialize();
};
this.initialize();
};
Foo.prototype.initialize = function() {
alert("initialize");
};
var f = new Foo();
f.hello();
Question 4:
Why following code succeeded? (considering the "future" function is defined after calling)
alert("The future says: " + future());
function future() {
return "We STILL have no flying cars.";
}
In the first case, you are calling initialize before it is defined (on the next line).
In the second case, you are assigning the return value of the function (undefined in this case) to this.initialize, so when you try to invoke it as a function later, you get your error.
You may want to look further into the prototype pattern for making class-like structures - Douglas Crockford wrote a lot of useful stuff on this and it's useful for introductory learning: http://javascript.crockford.com/prototypal.html is a good start.
My answers inline (kind of)
Question 1 Why is that? Won't the Javascript Engine firstly read in all member function declarations of an object?
No, if they are defined as in your example, they will be executed in order, as the method doesn't exist yet, it will throw.
This way would be a different case (not OO, but to ilustrate):
function Foo(){
initialize(); //This would work
function initialize(){ ... } //Parser defines its function first
}
In this case, the parser does define the function declarations first, it's a different case.
The function "initialize" is executed on construction, however, the calling for this.initialize() in function "hello" failed.
this.initialize = function() {
alert("initialize");
}(); //This executes the function!
The problem with the above code is that you're not assigning the function to this.initialize, you're assigning the result of its execution, in this case undefined (because there is no return inside the function)
for example, if the code were:
this.initialize = function() {
return 2;
}();
then this.initialize would be... 2 !! (not a function).
Hope this helps. Cheers
Calling a method from constructor :
var f = new Foo();
function Foo() {
this.initialize(); //failed here
};
Foo.prototype.initialize = function() {
alert("initialize");
};
Execution Process:
1) All functions are created (that are defined at the root)
2) Code is executed in order
3) When Foo is created/constructed it executes the code.
It try's to run Initialize() but it doesn't find it,
it throws an internal exception that is caught and
then creates the Prototype method and executes it.
4) If the Foo.Prototype.initialize line came BEFORE the,
"var f = new Foo()" then the initialize function would have existed.
This process occurs for every line of execution.
This is related to a question I asked previously here: How to implement chained method calls like jQuery?
I have been using the method from the check answer from some time there, and it works well. But I would like to alter the syntax for my toolkit even further.
foo(firstarg).bar(secondarg); // should function as the question above.
foo(onlyarg).bar // a function with one argument
foo.bar(onlyarg); // should also work, when a first argument is not appropriate.
foo.bar; // a function without an argument, or returns a static value.
I would like all 4 syntaxs to work off the same foo object, but lack the OOP understanding to do so. I have tried a few things, and so far I can get 1 & 2 to work, and 3 & 4 to work, but not to all work together. It also would be nice if chaining remained an option by having each function return the root object.
Edit: I clearly need to be more specific, here is what I have now:
var main = function(obj){ this.obj = obj; };
var tool = function(obj){ return new main(obj); };
main.prototype = {
alertThisPlus : function(plus){
alert(this.obj + ' ' + plus);
},
alertJustThis : function(){
return alert(this.obj);
}
};
usage
tool('hello').alertThisPlus('world'); // returns alert('hello world')
tool().alertJustThis('hello world'); // returns alert('hello world');
what I would like is to do this:
tool('hello').alertThisPlus('world'); // returns alert('hello world') no change
tool.alertJustThis('hello world'); // returns alert('hello world') does not work
Functions are just objects so you can add functions to 'tool'. You can do this manually:
tool.foobar = function() {};
Or if your classes are structured suitably you could use a mix-in approach. Something like this:
function Tool(prefix) {
this.prefix = prefix;
}
Tool.prototype.alertThisPlus = function(suffix) {
alert((typeof this.prefix != 'undefined' ? this.prefix + ' ' : '') + suffix);
};
Tool.prototype.alertJustThis = function(msg) {
alert(msg);
};
function tool(prefix) {
return new Tool(prefix);
}
// Mix-in the methods from a static instance of Tool onto the 'tool' function.
// This makes both tool.alertThisPlus() and tool.alertJustThis() available,
// both will be called in the context of 'staticTool'.
(function() {
var staticTool = new Tool();
for (var o in staticTool) {
if (typeof staticTool[o] == 'function') {
tool[o] = staticTool[o].bind(staticTool);
}
}
})();
tool('hello').alertThisPlus('world'); // returns alert('hello world')
tool().alertJustThis('hello world'); // returns alert('hello world')
tool.alertJustThis('hello world'); // returns alert('hello world')
The only way I can think of that would allow you to execute a function without parenthesis is if you are a) passing it as a callback param, or b) having it self execute.
var foo = (function() {
alert('foo called');
})();
Taking that a step further, lets say you've use some closures to return values.
var foo = (function() {
return {
bar: "arf arf said the dog"
}
})();
Now you can use:
foo.bar;
Consider this piece of code
var crazy = function() {
console.log(this);
console.log(this.isCrazy); // wrong.
}
crazy.isCrazy = 'totally';
crazy();
// ouput =>
// DOMWindow
// undefined
From inside crazy() 'this' refers to the window, which I guess makes sense because normally you'd want this to refer to the object the function is attached to, but how can I get the function to refer to itself, and access a property set on itself?
Answer:
Don't use arguments.callee, just use a named function.
"Note: You should avoid using arguments.callee() and just give every function (expression) a name." via MDN article on arguments.callee
I think you are asking for arguments.callee, but it's deprecated now.
https://developer.mozilla.org/en/JavaScript/Reference/Functions_and_function_scope/arguments/callee
var crazy = function() {
console.log(this);
console.log(arguments.callee.isCrazy); // right.
}
crazy.isCrazy = 'totally';
crazy();
// ouput =>
// DOMWindow
// totally
As rfw said, this is the most straight forward way to go if the function has one single name:
var crazy = function() {
console.log(crazy);
console.log(crazy.isCrazy);
};
crazy.isCrazy = 'totally';
crazy();
In case it may have different names, or you wanted to pass it around, it must be wrapped in a closure:
var crazy = (function(){
var that = function() {
console.log(that);
console.log(that.isCrazy);
};
return that;
})();
crazy.isCrazy = 'totally';
crazy();
Bind the function to itself (taking a hint from answers by #ArunPJohny and #BudgieInWA):
crazy = crazy.bind(crazy);
This will give you access from the function to its properties via this.
> crazy()
function () {
console.log(this);
console.log(this.isCrazy); // works now
}
This seems like a better solution than the accepted answer, which uses the callee feature which is deprecated and doesn't work in strict mode.
You could also now have the function call itself recursively with this() were you so inclined.
We will call this self-thisifying. Write a little utility function:
function selfthisify(fn) { return fn.bind(fn); }
crazy = selfthisify(crazy);
crazy();
Or, if you prefer more "semantic" names, you could call it accessOwnProps.
If you're a syntactic sugar type of person, you could add a selfthisify property to the Function prototype:
Object.defineProperty(Function.prototype, 'selfthisify', {
get: function() { return this.bind(this); }
});
Now you can say
crazy.selfthisify();
You have to give it its own name, so:
var crazy = function() {
console.log(crazy);
console.log(crazy.isCrazy);
}
crazy.isCrazy = 'totally';
crazy();
The variable this is only applicable in the scope of an object, for instance, if you invoked your version of the crazy function with crazy.call(crazy), it will call the function in the context of the function crazy and all would be well.
This has to deal with the scope of the function crazy. If can pass any scope to a function using the function call().
Instead of
crazy();
Use
crazy.call(crazy);
For details refer
http://odetocode.com/blogs/scott/archive/2007/07/05/function-apply-and-function-call-in-javascript.aspxhttps://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Function/Callhttp://devlicio.us/blogs/sergio_pereira/archive/2009/02/09/javascript-5-ways-to-call-a-function.aspx
You can use the call method
var crazy = function() {
console.log(this);
console.log(this.isCrazy);
}
crazy.isCrazy = 'totally';
crazy.call(crazy);
// calls crazy using crazy as the target, instead of window:
// functionToCall.call(objectToUseForThis);
Though if your function only ever has one name, you can do this:
var crazy = function() {
console.log(crazy);
console.log(crazy.isCrazy);
}
crazy.isCrazy = 'totally';
crazy();
Easiest way to make the function itself available in its body is to do
var crazy = function crazy2() { crazy2(); }, it's okay for crazy and crazy2 to have the same name since the first occurrence is the name in the outer scope and the second is the name in the function body.
Or simply do function crazy() { crazy(); } which will define crazy in both scopes.
how can I get the function to refer to
itself?
The idea of 'itself' does not exist with functions. What you need is an object and not just a function. An object has knowledge of itself available through the keyword 'this'. Within a function, 'this' points to the global object - in this case the window object. But if you use your function as a constructor function to create an object (using the new operator) then the object's 'this' pointer will point to the object itself.
i.e this points to the object if you write:
var anObject = new crazy();
So you can re-write your code as follows:
var crazy = function() {
this.printMe = function(){
console.log(this);
console.log(this.isCrazy);
}
}
var anObject = new crazy(); //create an object
anObject.isCrazy = 'totally'; //add a new property to the object
anObject.printMe(); //now print
In case you wish to add the property before the object is created, then you have to add the property to the function's prototype as follows:
var crazy = function() {
console.log(this);
console.log(this.isCrazy);
}
crazy.prototype.isCrazy = 'totally'; //add the property to the function's prototype
var anObject = new crazy(); //invoke the constructor
See more on my blog for a detailed explanation of these concepts with code-samples.
Are you actually trying to create an object 'class'?
function crazy(crazyState) {
this.isCrazy = crazyState;
console.log(this);
console.log(this.isCrazy);
}
crazy.prototype.alertMe = function() { alert('I am '+ this.isCrazy +' crazy.'); }
var crazyObj = new crazy('totally');
crazyObj.alertMe();
crazyObj.isCrazy = 'not';
crazyObj.alertMe();
Funny that you should ask, mate. I just went through this same issue for a different purpose. The quick version of the final code is:
$a = function() {};
$ = function() {
if (!(this instanceof $)) {
return new $();
}
this.name = "levi";
return this;
};
//helper function
var log = function(message) {
document.write((message ? message : '') + "<br/>");
};
log("$().name == window.name: " + ($().name == window.name)); //false
log("$().name: " + $().name); //levi
log("window.name: " + window.name); //result
log();
log("$a instanceof $: " + ($a instanceof $)); //false
log("typeof $a: " + (typeof $a)); //function
log("typeof $: " + (typeof $)); //function
The critical piece:
if (!(this instanceof $)) {
return new $();
}
If this isn't pointing to an object of the right type, then it makes a new one, which will properly scope this. The rest of the code is just there for verification that it does indeed work as intended.
In order to make you code to work follow below
function crazy_object (crazy) {
this.isCrazy = crazy
}
var create_crazy = new crazy_object('hello') //creating object
console.log(create_crazy); //=> { isCrazy = 'hello' }
var crazy = function() {
console.log(this); //=> { isCrazy = 'totally' }
console.log(this.isCrazy); //=> 'totally'
}
create_crazy.isCrazy = 'totally'; //=> isCrazy = 'totally'
//below we pass the created object in function crazy.
//And doing that we can use the keywork `this` and refer to the object
crazy.call(create_crazy, null);
Using the call and apply method we can pass to a function a
property,and in that function we can use the property with the keyword this
For example:
function speak (message) {
console.log(`A person with name ${this.name} say ${message}`);
}
speak.call({ name: 'Roland' }, 'Javascript is awesome');
To use it with property:
function speak (message) {
console.log(`A person with name ${this.name} say ${message}`);
}
var name = 'Roland'
speak.call({ name }, 'Javascript is awesome');
In the following JavaScript code main() is called.
My question is why the second constructor is called rather than the first one ?
What am I missing here ?
Thanks !!
function AllInputs() {
alert("cons 1");
this.radioInputs = [];
alert(this);
}
function AllInputs(radioElement) {
alert("cons 2");
this.radioInputs = [radioElement];
alert(this);
}
AllInputs.prototype.toString = function() {
return "[object AllInputs: radioInputs: " + this.radioInputs.length + "]";
}
function main() {
var result = new AllInputs();
}
Javascript does not support overloaded functions.
When you define the same function twice, the second definition replaces the first one.
Instead, you should make a single function, and check arguments.length to see how many arguments were passed.
For example:
function AllInputs(radioElement) {
this.radioInputs = arguments.length ? [radioElement] : [];
alert(this);
}
In JavaScript, the last definition of an identifier is used:
function foo() { return "bar"; }
var foo = "foo";
alert(foo);
In that case, foo was a variable with the value "foo". Had foo been a function, it would have simply said that foo was a function. If you don't believe it, try using alert(foo()) instead of just alert(foo). You'll most likely get an error in your console log with no visible output like you had with alert(foo) (the variable...not the function call).
function foo() { ... }
is really just shorthand for
var foo = function () { ... }
Hence, the second time you're declaring the function, you're overwriting the variable AllInputs with a different function. There ain't no such thing as two functions with the same name in Javascript, since all functions are really variables.