How to get caller function class name - javascript

I tried some thing following, it fullfils 80% of the need though not enough to use.
// Different file
function A(){}
A.prototype.ao = function(){
// Here I want ot know the fucntion caller class name, for that I used
arguments.callee.caller.prototype; // It retuens B.bo {} (object)
}
// Different file
function B(){}
B.prototype.bo = function(){
var a = new A();
a.ao();
}
How to retrieve the class name from caller prototype, as it is of type object.
I would be more helpful, if we able to get the caller function context.

How to retrive the class name from caller prototype
You can't*, for a couple of reasons:
Functions don't have a name property. They will in ES6, but they don't yet. (You could assign a property to B with the name, though.)
Although you can get a reference to the function that's on B.prototype.bo, there's no link from there back to B. The linkage is one-way. (Not least because the same function could be on multiple objects.)
Note that using arguments.callee is strongly discouraged, and disallowed in strict mode, and using caller is especially discouraged. There's almost always a better way to do what you're trying to do.
* On some engines, you might be able to figure it out from the call stack, e.g.:
A.prototype.ao = function(){
try {
throw new Error();
}
catch (e) {
// Examine e.stack here
}
};
You'd be relying on platform-specific naming and such.
But again, there's almost certainly a better option than trying to know who's calling you.
Re your comment:
Here my requirement is to track an API function usage, in order to achieve it I am following this way...And further I can't change the existed framework.
You probably can but don't realize it, because JavaScript is that powerful. :-)
For instance: Once whatever framework creates B is loaded on the page, here's code that will wrap every function on B.prototype with a version that tells you it's running:
function wrapFunctions(name, proto) {
Object.keys(proto).forEach(function(key) {
var original = proto[key];
if (typeof original === "function") {
proto[key] = function() {
var rv;
starting(name, key); // <=== Your function to tracking the start of a call
rv = original.apply(this, arguments);
stopping(name, key); // <=== Your function tracking the end of the call
return rv;
};
}
});
}
wrapFunctions("B", B.prototype);
That's the beginning of "instrumentation." But note that there are proper libraries out there for this that have solved the edge cases and such.
Live Example:
// The framework
function B() {}
B.prototype.f1 = function() {
snippet.log("Original functionality for f1");
};
B.prototype.f2 = function() {
snippet.log("Original functionality for f2");
};
B.prototype.f3 = function() {
snippet.log("Original functionality for f3 -- calling f2");
this.f2();
snippet.log("Original functionality for f3 -- done calling f2");
};
// Let's use f1 and f2 before we wrap them
snippet.log("Before wrapping:");
var b1 = new B();
b1.f1();
b1.f2();
b1.f3();
// Now your code runs and wraps them
wrapFunctions("B", B.prototype);
// Now let's use f1 and f2 again
snippet.log("After wrapping:");
var b2 = new B();
b2.f1();
b2.f2();
b1.f3();
// Our function to track that a call started
function starting(ctor, name) {
snippet.log(ctor + "#" + name + ": Started");
}
// Our function to track that a call stopped
function stopping(ctor, name) {
snippet.log(ctor + "#" + name + ": Stopped");
}
// Our function to wrap things
function wrapFunctions(name, proto) {
Object.keys(proto).forEach(function(key) {
var original = proto[key];
if (typeof original === "function") {
proto[key] = function() {
var rv;
starting(name, key); // <=== Your function to tracking the start of a call
rv = original.apply(this, arguments);
stopping(name, key); // <=== Your function tracking the end of the call
return rv;
};
}
});
}
<!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>

You can include a method in the object which returns its type. Another option is to use instanceof and check for all possible types.
function A() {
this.getType = function () {
return "A";
}
}
A.prototype.ao = function() {
// Here I want ot know the fucntion caller class name, for that I used
var type = this.getType();
args.callee.caller.prototype; // It retuens B.bo {} (object)
}
function B(){
this.getType = function () {
return "B";
}
}
B.prototype.bo = function(){
var a = new A();
a.ao.apply(this);
}
Here you will also have to redefine getType in all of your inherited types and return the correct type. You also need to invoke the desired method with apply(this) to provide the context of the current caller.

Related

Dynamically add argument to function in javascript

I'm testing my app, I have a dependency injection system that works like this (I paste here a very simplified version)
test.start = function(callback) {
// do stuff;
load(callback);
}
function load(callback) {
var args = ...// read callback's arguments
// args = ['moduleA', 'moduleB'];
var injectedArgs = args.map(function(a) {
return require('./lib/' + a);
});
// call function with deps injected
callback.apply(null, injectedArgs);
}
// test.js
test.start(function(moduleA, moduleB) {
moduleA.functionA();
moduleB.functionB();
});
What I need to do is an async job before calling the callback and start the test, in this particular case, that would be
test.start = function(callback) {
// do stuff;
load(function(moduleA, moduleB, moduleC) {
moduleC.resetData(function() {
return callback(moduleA, moduleB);
})
});
}
I need to make this dynamic, for all the test that have different modules as their callback arguments.
Requirements are
I don't want to change test definitions
I must call load only once per test
So basically I need to create the middle function that add moduleC argument, run the resetData function and call the original callback.
I can build the dynamically extended argument list using
var fn = new Function(newArgumentList, /*function body*/) but I can't attach the correct function body (using a string) because I lose the original callback context.
UPDATE
The DI library is modularity and it reads the callback definition to grab dependency. So basically, given the callback function(foo, bar) { ... } I need to create a new function(foo, bar, db) { db.resetData(function() { return callback(foo, bar) } )}
If load, itself, is something you can change (e.g., not part of the test definitions), you'll be glad to know this is quite easy to do: You use Function#apply:
function load(callback) {
var origCallback;
if (/*flag saying you need to do this*/) {
origCallback = callback;
callback = function() {
/*...do your injected work here...*/
return origCallback.apply(this, arguments); // `arguments` looks like pseudo-code, but it isn't; it's an identifier created in the function's scope (for non-arrow functions)
};
}
var args = ...// read callback's arguments
// args = ['moduleA', 'moduleB'];
var injectedArgs = args.map(function(a) {
return require('./lib/' + a);
});
// call function with deps injected
callback.apply(null, injectedArgs);
}
You can even do it if you can't change load, provided you can update the load symbol to make it point at a new function:
var oldload = load;
load = function() {
/*...do your reset work here...*/
return oldload.apply(this, arguments);
};
If you're curious, yes, you can update the symbols created by function declarations (and yes, that's per spec, not "tricky"). E.g., this is perfectly valid:
function foo() {
console.log("I'm foo");
}
var oldFoo = foo;
foo = function() {
console.log("I'm the new foo");
return oldFoo.apply(this, arguments);
};
foo(); // "I'm the new foo", then "I'm foo"
Example:
function foo() {
snippet.log("I'm foo");
}
var oldFoo = foo;
foo = function() {
snippet.log("I'm the new foo");
return oldFoo.apply(this, arguments);
};
foo(); // "I'm the new foo", then "I'm foo"
<!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="//tjcrowder.github.io/simple-snippets-console/snippet.js"></script>
I found out the solution at the end.
Since modularity supports angular-like injection like this
['modules/a', 'modules/b', function(moduleA, moduleB) {
// use modules here
}]
I could write my custom callback like this
var customCallback = function() {
var args = Array.prototype.slice.call(arguments);
var injectedDBModule = args.pop();
injectedDBModule.resetData(function() {
// call the original callback function
return originalCallback.apply(null, args);
}
}
var loadCallback = originalInjectedModules; // ['moduleA', 'moduleB']
loadCallback.push('db');
loadCallback.push(customCallback);
modularity.load(loadCallback);

Javascript, getting away from 'this' and using local scope

In a typical js class, all calls to member functions must be preceded by this. I was looking at a technique that would let me create a library of inter-dependent STATIC functions and relying on closure/scope to make things a bit easier.
Example:
var Singleton={
//main entry point
// call with fn name, args...
call:function(){
var args=[];
if (arguments.length==0) {
return;
}
// get the fn name
var fn=arguments[0];
var x;
// make args array
for (x=1;x<arguments.length;x++) {
args[args.length]=arguments[x];
}
// I want to get rid of this part
// See below for what I wish
// Here I have access to fns below due to hoisting in js
// so I put them in a map...
var fns={
test:test
// etc, more like this I do not want to type/maintain
}
// ... all so I can do this
// get my function.
var fun=fns[fn];
// instead of that, I would like to "override whitespace" and
// say something like:
// var fun=['fn_name'];
// so I can index into local scope and get a fn
//
// log error if not found
if (typeof fun=='undefined') {
loge('Singleton: function not found:'+fn);
return;
}
// ok, run the function
return fun.apply(window,args);
// the test fn accesses test2() without dot notation
function test(a){
// Note: here in test fn it can access test2()
// without using this.test2() syntax
// as you would in normal objects
var s=test2();
alert(s+' test:'+a);
};
function test2(){
return 'test2';
};
}
}
I was hoping someone more familiar with advances in javascript might have advice on how to emulate an "implied but unnecessary this", it always struck me as strange that this defaults to window, and wouldn't it be nice if this could be pointed to an anonymous object with the local scope attached.
I would love to say ['localObject'] to get something in scope.
Edit:
After seeing some of the responses, I will restate this in the form of a challenge:
What I am looking for is a syntax cheat, a way to, as #Varuna put it, "1. Access static methods without using this variable i.e. they will remain global to one another. 2. Do not want to maintain a local array for static methods and want to achieve with in the local scope itself."
Put differently, I need to have the declared functions Register themselves, but I don't want to state the function name more than once. I suppose #Varuna has a solution using eval to access the local scope.
The following approach wont work:
var o={};
o['fn']=function fn(){};
o['fn2']=function fn2(){};
...because you have to state the fn name twice, but closure is preserved.
And this:
var a=[
function fn(){}
,function fn2(){}
];
Register(a);
Will not work because, AFAIK, you lose closure, ie. fn2 cannot see fn. Which also makes the following declarative style a "this nightmare":
window.MINE={
fn:function fn(){
//this?
// want to say fn2(), not this.fn2(), nor MINE.fn2()
}
,fn2:function fn2(){
//this?
}
,deeper:{
//more
}
};
But something like this might work, if you created a weird property that does the registration on assignment:
var registar=new Registar();
registar.reg=function fn(){};
registar.reg=function fn2(){};
//then access
var fn=registar.getFn(n);
// or
var fn=registar._[n];
The above relies on js properties and having access to fn.name, which is not available in all cases AFAIK.
If I understand correctly, you want to create objects that:
have static members
... which can be accessed without using the this notation
The easiest solution (assuming I've properly understood your query), would be to simply use a closure to store your stratic fields, access them directly by name, then explicitly add them as object members.
Consider:
var myConstructor = (function(){
var foo = 'someStaticField';
var bar = function(){
alert('A static method returns ' + foo);
};
return function(){
return {
foo : foo,
bar : bar
};
};
})();
var myInstance = new myConstructor();
As per my understanding, you want to:
1. Access static methods without using this variable i.e. they will remain global to one another.
2. Do not want to maintain a local array for static methods and want to achieve with in the local scope itself.
You can check whether a method exist using eval.Check Here
Only drawback is that this will be using eval method.
Code will be:
var Singleton = {
//main entry point
// call with fn name, args...
call: function () {
var args = [];
if (arguments.length == 0) {
return;
}
// get the fn name
var fn = arguments[0];
var x;
// make args array
for (x = 1; x < arguments.length; x++) {
args[args.length] = arguments[x];
}
//check whether function exist in local scope and not in global scope
if (typeof eval(fn) !== 'undefined' && typeof window[fn] === 'undefined') {
// ok, run the function
return eval(fn).apply(window, args);
}
else{
// log error if not found
loge('Singleton: function not found:' + fn);
return;
}
// the test fn accesses test2() without dot notation
function test(a) {
// Note: here in test fn it can access test2()
// without using this.test2() syntax
// as you would in normal objects
var s = test2();
alert(s + ' test:' + a);
};
function test2() {
return 'test2';
};
}
}
How about declaring functions that can access each other in separate closure, and exporting them to main method by binding your call method to an object containing the functions? Something like previous post (modified slightly):
var Singleton = {
call: (function() {
// here 'call' is bound to object containig your test functions
// this: {test, test2}
if (0 == arguments.length) return;
// log error if not found
if ('function' != typeof this[arguments[0]]) {
console.warn('Singleton: function not found:' + arguments[0]);
return;
}
// '...index into local scope and get function
// ie. get the function by it's name
return this[arguments[0]].
apply(window, Array.prototype.slice.call(arguments, 1));
// --- or:
// you can explicitly introduce function names to current scope,
// by `eval`-ing them here (not very much preferred way in JavaScript world):
for (var fname in this)
if (this.hasOwnProperty(fname))
eval('var ' + fname + ' = ' + this[fname]);
// and you can reference them directly by using their names
var fn = eval(arguments[0]);
return fn.apply(window, Array.prototype.slice.call(arguments, 1));
}).bind(
(function() {
var _exports = {};
function test (a) {
var s = test2();
alert(s + ' test: ' + a);
}
function test2 () {
return 'test2';
}
_exports['test'] = test;
_exports['test2'] = test2;
return _exports;
})()
)};
Singleton.call('test', 'foo and stuff');
//
previous post:
You are talking about Function#bind functionality that enables 'customizing' function's context. .bind() your call method to required 'local context' like this:
var Singleton = {
//main entry point
// call with fn name, args...
call: (function() {
// here `this` (context) is object bound to `call` method
// not `global` object, which is default for 'unbound' functions
var locals = this; // {fns, shift, loge, isfunc}
var fn;
var fun;
var x;
if (arguments.length == 0)
return;
// get the fn name
fn = locals.shift(arguments);
// '...index into local scope and get a fn'
fun = locals.fns[fn];
// log error if not found
if (!locals.isfunc(fun)) {
locals.loge('Singleton: function not found:' + fn);
return;
}
// ok, run the function
return fun.apply(window, arguments);
// lock `call`'s context to provided object
// and use `this` to reference it inside `call`
}).bind({
fns: (function(_) {
// and you can '...create a library of inter-dependent STATIC functions'
// in this closure and invoke them in `call` method above
_.test = function (a) {
var s = _.test2();
alert(s + ' test: ' + a);
};
_.test2 = function() {
return 'test2';
};
return _;
})({}),
// and create couple of helper methods as well...
isfunc: (function(_getclass) {
_getclass.func = _getclass(_getclass);
return ('function' !== typeof(/foo/)) ?
function(node) {
return 'function' == typeof node;
} :
function(node) {
return _getclass.func === _getclass(node);
};
})(Function.prototype.call.bind(Object.prototype.toString)),
loge: console.warn,
shift: Function.prototype.call.bind(Array.prototype.shift)
}),
};
Singleton.call('test', 'foo and stuff');
// eof
Here's one 'in your face answer', because I really don't like what I see here.
I don't see why you need this kind of construct, you already have that as part of language core.
1. dynamic lookup
you are doing it in a rather 'unprecedented' kind of way,
hashes already do that for you, and it's lightning fast to do a hash search.
If you are eval()-ing random strings to do simple name lookup you really have to
step aside from a keybord for a while... (no offense please)
2. closures
you are saying about 'using closures' which you actualy don't use.
your call function redeclares test functions each time it gets called,
and looks the ('fresh version') functions in it's own variable scope table,
instead of lookig them up in parent scope chains (aka. closures)
outside it's lexical location
3. nfe vs. nfd
ie. named function expressions vs. named function declarations
...you cannot assign a function to a local var and have it retain closure.
It is a feature, you might not be aware of how it works (it tripped me up as well).
check this article out for clarification
4. exceptions
Singleton: function name not found... x4!
Just go ahead and call a function,
interpreter will throw for you anyway if it cannot find/execute
5. eval (aka. ^^)
Singleton.call.ctx.fun = eval(Singleton.call.ctx.fn);
eval takes any string here(#!), and gladly executes ones like:
'for(;;);', or 'while(1);'... forever.
You probably don't want to have any code running unless it was your stuff.
6. arguments handling
It is considered best practice out there to use single (Object) options parameter
to 'fine tune' any significant piece of bundled functionality,
instead of trying to figure that out by type checking provided argument list
Here's, in couple of simple lines, what I (and as I can see #Jimmy Breck-McKye) suggest you should do:
var Singleton.call = (function () {
var funcmap = {
'f_1': function () {},
// etc.
'f_N': function () {},
};
return function (options) {
// options members:
// context, (Object) context, (defaults to global if none is given)
// func, (String) function_name,
// args, (Array) arguments to pass into a function
// this line does everything your 100+ lines long snippet was trying to:
// look's up parent scope for a function, tries to run it
// passing provided data, throws if it gets stuck.
return funcmap[options.func].apply(options.context, options.args);
};
})();
//
Answering my own question here.
The core of the issue is that you cannot assign a function to a local var and have it retain closure.
Consider that when writing a function with global and window scope, this is not necessary to call another function with identical scope. Such is not the case with member functions.
Another way of saying this is that there is no space where your cursor can sit and as you declare a function it automatically gets attached to the current this.
function fn(){}// if we are in global scope, then window.fn becomes defined
// but if we are inside, say, a constructor, simple declaration will not attach
// it to this, but fn is available in scope.
Any assignment on function declaration BREAKS part of the expected closure:
var IdentifierAvailableToClosure=function Unavailable(){}
But assignment after declaration works:
function NowAvailable(){}
var SynonymAvailableToo=NowAvailable;
This is what I meant by not wanting to repeat the name twice to get the mechanism to work.
This fact made me abandon other methods and rely on eval as suggested. Here is a first draft:
// This object is an encapsulation mechanism for a group of
// inter-dependent, static-ish, functions that can call each other
// without a this pointer prefix.
// Calls take the form of:
// Singleton.call(functionName:String [,arg1]...)
// or
// Singleton.call(contextObject:Object, functionName:String [,arg1]...)
// If a context is not provided, window is used.
//
// This type of mechanism is useful when you have defined a group
// of functions in the window/global scope and they are not ready
// to be formalized into a set of classes, or you have no intention
// of doing that
//
// To illustrate the issue, consider that a function
// which is defined in window/global scope
// does not have to use the this pointer to call a function of
// identical scope -- yet in a class member function, the this pointer
// MUST be used
// Therefore, trying to package such functions requires injecting
// the this pointer into function bodies where calls to associater
// functions are made
//
// Usage is primarily for development where one has control over
// global namespace pollution and the mechanism is useful in
// refactoring prior to formalization of methods into classes
var Singleton={
// Main call point
call:function(){
// Bail with error if no args
if (arguments.length==0) {
throw('Singleton: need at least 1 arg');
}
// As all functions in the local scope library below
// have access to the local scope via closure, we want to reduce
// pollution here, so lets attach locals to this call
// function instead of declaring locals
//
// Prepare to call anon fn
Singleton.call.args=arguments;
// Make ctx have args, context object, and function name
Singleton.call.ctx=(function (){// return args,ctx,name
// out
var args=[];
//locals
var x, fn;
// collapse identifier
var a=Singleton.call.args;
// closure object avail to functions, default to window
that=window;
// first real function argument
var arg_start=1;
// first arg must be function name or object
if (typeof a[0]=='string') {// use window ctx
fn=a[0];
// if first arg is object, second is name
}else if (typeof a[0]=='object') {
// assign given context
that=a[0];
// check second arg for string, function name
if (typeof a[1]!='string') {
var err='Singleton: second argument needs to be a fn name'
+' when first arg is a context object';
throw(err)
return;
}
// ok, have a name
fn=a[1];
// args follow
arg_start=2;
}else{
// improper arg types
var err='Singleton: first argument needs to be a string or object';
throw(err)
}
// build args array for function
for (x=arg_start;x<a.length;x++) {
args[args.length]=a[x];
}
// return context
return {
args: args
,that:that
,fn:fn
};
})();
// using function library present in local scope, try to find specified function
try{
Singleton.call.ctx.fun=eval(Singleton.call.ctx.fn);
}catch (e){
console.error('Singleton: function name not found:' + Singleton.call.ctx.fn);
throw('Singleton: function name not found:' + Singleton.call.ctx.fn);
}
// it must be a function
if (typeof Singleton.call.ctx.fun !== 'function') {
console.error('Singleton: function name not found:' + Singleton.call.ctx.fn);
throw('Singleton: function name not found:' + Singleton.call.ctx.fn);
}
// library functions use that instead of this
// that is visible to them due to closure
var that=Singleton.call.ctx.that;
// Do the call!
return Singleton.call.ctx.fun.apply(that, Singleton.call.ctx.args);
//
// cool library of functions below,
// functions see each other through closure and not through this.fn
function test(s){
alert(test2()+' test:'+s);
}
function info_props(){
console.info(this_props());
}
function test2(){
return 'test2';
}
function this_props(){
var s='';
for (var i in that) {
s+=' '+i;
}
return s;
};
}
};

Specifics of javascript cosntructors

Say I have a pure constructor function (containing nothing but this.Bar = bar)
1) When I call it from another function, can I pass the caller function's arguments directly when I call or must I do var myBar=new bar, myBar.Bar=thebar, where the bar is a caller argument?
2) Will the constructor still instantiate even if it doesn't get all the args?
3) How can I check if one of the args is unique, IE no other instance of the object has this value for the property in question? Specifically, I want to assign each object a unique index at creation. Maybe array?
Many thanks in advance
Say I have a pure constructor function (containing nothing but this.Bar = bar)
I'm going to assume you mean:
function MyConstructor(bar) {
this.Bar = bar;
}
(Note: The overwhelming convention in JavaScript is that property names start with a lower-case letter. So this.bar, not this.Bar. Initially-capped identifiers are usually reserved for constructor functions.)
1) When I call it from another function, can I pass the caller function's arguments directly when I call or must I do var myBar=new bar, myBar.Bar=thebar, where the bar is a caller argument?
You can pass them directly:
function foo(a, b, c) {
var obj = new MyConstructor(b);
}
2) Will the constructor still instantiate even if it doesn't get all the args?
The number of arguments passed is not checked by the JavaScript engine. Any formal arguments that you don't pass will have the value undefined when the function is called:
function MyConstructor(bar) {
console.log(bar);
}
var obj = new MyConstructor(); // logs "undefined"
3) How can I check if one of the args is unique, IE no other instance of the object has this value for the property in question? Specifically, I want to assign each object a unique index at creation. Maybe array?
In general, that's usually not in-scope for a constructor. But yes, you could use an array, or an object, to do that.
var knownBars = [];
function MyConstructor(bar) {
if (knownBars.indexOf(bar) !== -1) {
// This bar is known
}
else {
// Remember this bar
knownBars.push(bar);
}
}
Of course, indexOf may not be what you want for searching, so you may need to use some other method of Array.prototype or your own loop.
Another way would be to use an object; this assumes that bar is a string or something that can usefully be turned into a string:
var knownBars = {};
function MyConstructor(bar) {
if (knownBars.indexOf(bar) !== -1) {
// This bar is known
}
else {
// Remember this bar
knownBars[bar] = 1;
}
}
When I call it from another function, can I pass the caller function's arguments directly
There wouldn't be much point in having this.Bar = bar in the constructor function if you could not.
Will the constructor still instantiate even if it doesn't get all the args?
Assuming nothing inside it throws an exception if the argument is missing, yes. Arguments just get a value of undefined.
How can I check if one of the args is unique, IE no other instance of the object has this value for the property in question?
You'd need to have a shared store of them that you check against.
For example:
var Constructor = (function () {
var unique_check_store = {};
function RealConstructor(bar) {
if (typeof bar == 'undefined') {
throw "You must specify bar";
}
if (unique_check_store.hasOwnProperty(bar)) {
throw "You have already created one of these called '" + bar + "'";
}
this.Bar = bar;
unique_check_store[bar] = true;
}
return RealConstructor;
})();
var a, b, c;
try {
a = new Constructor();
} catch (e) {
alert(e);
}
try {
b = new Constructor("thing");
} catch (e) {
alert(e);
}
try {
c = new Constructor("thing");
} catch (e) {
alert(e);
}
alert(a);
alert(b);
alert(c);
​

Refer to javascript function from within itself

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');

How to detect if a function is called as constructor?

Given a function:
function x(arg) { return 30; }
You can call it two ways:
result = x(4);
result = new x(4);
The first returns 30, the second returns an object.
How can you detect which way the function was called inside the function itself?
Whatever your solution is, it must work with the following invocation as well:
var Z = new x();
Z.lolol = x;
Z.lolol();
All the solutions currently think the Z.lolol() is calling it as a constructor.
As of ECMAScript 6, this is possible with new.target
new.target will be set as true if the function is called with new (or with Reflect.construct, which acts like new), otherwise it's undefined.
function Foo() {
if (new.target) {
console.log('called with new');
} else {
console.log('not called with new');
}
}
new Foo(); // "called with new"
Foo(); // "not called with new"
Foo.call({}); // "not called with new"
NOTE: This is now possible in ES2015 and later. See Daniel Weiner's answer.
I don't think what you want is possible [prior to ES2015]. There simply isn't enough information available within the function to make a reliable inference.
Looking at the ECMAScript 3rd edition spec, the steps taken when new x() is called are essentially:
Create a new object
Assign its internal [[Prototype]] property to the prototype property of x
Call x as normal, passing it the new object as this
If the call to x returned an object, return it, otherwise return the new object
Nothing useful about how the function was called is made available to the executing code, so the only thing it's possible to test inside x is the this value, which is what all the answers here are doing. As you've observed, a new instance of* x when calling x as a constructor is indistinguishable from a pre-existing instance of x passed as this when calling x as a function, unless you assign a property to every new object created by x as it is constructed:
function x(y) {
var isConstructor = false;
if (this instanceof x // <- You could use arguments.callee instead of x here,
// except in in EcmaScript 5 strict mode.
&& !this.__previouslyConstructedByX) {
isConstructor = true;
this.__previouslyConstructedByX = true;
}
alert(isConstructor);
}
Obviously this is not ideal, since you now have an extra useless property on every object constructed by x that could be overwritten, but I think it's the best you can do.
(*) "instance of" is an inaccurate term but is close enough, and more concise than "object that has been created by calling x as a constructor"
1) You can check this.constructor:
function x(y)
{
if (this.constructor == x)
alert('called with new');
else
alert('called as function');
}
2) Yes, the return value is just discarded when used in the new context
NOTE: This answer was written in 2008, when javascript was still in ES3 from 1999. A lot of new functionality has been added since then, so now better solutions exists. This answer is kept for historical reasons.
The benefit of the code below is that you don't need to specify the name of the function twice and it works for anonymous functions too.
function x() {
if ( (this instanceof arguments.callee) ) {
alert("called as constructor");
} else {
alert("called as function");
}
}
Update
As claudiu have pointed out in a comment below, the above code doesn't work if you assign the constructor to the same object it has created. I have never written code that does that and have newer seen anyone else do that eighter.
Claudius example:
var Z = new x();
Z.lolol = x;
Z.lolol();
By adding a property to the object, it's possible to detect if the object has been initialized.
function x() {
if ( (this instanceof arguments.callee && !this.hasOwnProperty("__ClaudiusCornerCase")) ) {
this.__ClaudiusCornerCase=1;
alert("called as constructor");
} else {
alert("called as function");
}
}
Even the code above will break if you delete the added property. You can however overwrite it with any value you like, including undefined, and it still works. But if you delete it, it will break.
There is at this time no native support in ecmascript for detecting if a function was called as a constructor. This is the closest thing I have come up with so far, and it should work unless you delete the property.
Two ways, essentially the same under the hood. You can test what the scope of this is or you can test what this.constructor is.
If you called a method as a constructor this will be a new instance of the class, if you call the method as a method this will be the methods' context object. Similarly the constructor of an object will be the method itself if called as new, and the system Object constructor otherwise. That's clear as mud, but this should help:
var a = {};
a.foo = function ()
{
if(this==a) //'a' because the context of foo is the parent 'a'
{
//method call
}
else
{
//constructor call
}
}
var bar = function ()
{
if(this==window) //and 'window' is the default context here
{
//method call
}
else
{
//constructor call
}
}
a.baz = function ()
{
if(this.constructor==a.baz); //or whatever chain you need to reference this method
{
//constructor call
}
else
{
//method call
}
}
Checking for the instance type of the [this] within the constructor is the way to go. The problem is that without any further ado this approach is error prone. There is a solution however.
Lets say that we are dealing with function ClassA(). The rudimentary approach is:
function ClassA() {
if (this instanceof arguments.callee) {
console.log("called as a constructor");
} else {
console.log("called as a function");
}
}
There are several means that the above mentioned solution will not work as expected. Consider just these two:
var instance = new ClassA;
instance.classAFunction = ClassA;
instance.classAFunction(); // <-- this will appear as constructor call
ClassA.apply(instance); //<-- this too
To overcome these, some suggest that either a) place some information in a field on the instance, like "ConstructorFinished" and check back on it or b) keep a track of your constructed objects in a list. I am uncomfortable with both, as altering every instance of ClassA is way too invasive and expensive for a type related feature to work. Collecting all objects in a list could provide garbage collection and resource issues if ClassA will have many instances.
The way to go is to be able to control the execution of your ClassA function. The simple approach is:
function createConstructor(typeFunction) {
return typeFunction.bind({});
}
var ClassA = createConstructor(
function ClassA() {
if (this instanceof arguments.callee) {
console.log("called as a function");
return;
}
console.log("called as a constructor");
});
var instance = new ClassA();
This will effectively prevent all attempts to trick with the [this] value. A bound function will always keep its original [this] context unless you call it with the new operator.
The advanced version gives back the ability to apply the constructor on arbitrary objects. Some uses could be using the constructor as a typeconverter or providing an callable chain of base class constructors in inheritance scenarios.
function createConstructor(typeFunction) {
var result = typeFunction.bind({});
result.apply = function (ths, args) {
try {
typeFunction.inApplyMode = true;
typeFunction.apply(ths, args);
} finally {
delete typeFunction.inApplyMode;
}
};
return result;
}
var ClassA = createConstructor(
function ClassA() {
if (this instanceof arguments.callee && !arguments.callee.inApplyMode) {
console.log("called as a constructor");
} else {
console.log("called as a function");
}
});
actually the solution is very possible and simple... don't understand why so many words been written for such a tiny thing
UPDATE: thanks to TwilightSun the solution is now completed, even for the test Claudiu suggested! thank you guys!!!
function Something()
{
this.constructed;
if (Something.prototype.isPrototypeOf(this) && !this.constructed)
{
console.log("called as a c'tor"); this.constructed = true;
}
else
{
console.log("called as a function");
}
}
Something(); //"called as a function"
new Something(); //"called as a c'tor"
demonstrated here: https://jsfiddle.net/9cqtppuf/
Extending Gregs solution, this one works perfectly with the test cases you provided:
function x(y) {
if( this.constructor == arguments.callee && !this._constructed ) {
this._constructed = true;
alert('called with new');
} else {
alert('called as function');
}
}
EDIT: adding some test cases
x(4); // OK, function
var X = new x(4); // OK, new
var Z = new x(); // OK, new
Z.lolol = x;
Z.lolol(); // OK, function
var Y = x;
Y(); // OK, function
var y = new Y(); // OK, new
y.lolol = Y;
y.lolol(); // OK, function
There is no reliable way to distinguish how a function is called in JavaScript code.1
However, a function call will have this assigned to the global object, while a constructor will have this assigned to a new object. This new object cannot ever be the global object, because even if an implementation allows you to set the global object, you still haven't had the chance to do it.
You can get the global object by having a function called as a function (heh) returning this.
My intuition is that in the specification of ECMAScript 1.3, constructors that have a defined behavior for when called as a function are supposed to distinguish how they were called using this comparison:
function MyClass () {
if ( this === (function () { return this; })() ) {
// called as a function
}
else {
// called as a constructor
}
}
Anyway, anyone can just use a function's or constructor's call or apply and set this to anything. But this way, you can avoid "initializing" the global object:
function MyClass () {
if ( this === (function () { return this; })() ) {
// Maybe the caller forgot the "new" keyword
return new MyClass();
}
else {
// initialize
}
}
1. The host (aka implementation) may be able to tell the difference, if it implements the equivalent to the internal properties [[Call]] and [[Construct]]. The former is invoked for function or method expressions, while the latter is invoked for new expressions.
In my testing for http://packagesinjavascript.wordpress.com/ I found the test if (this == window) to be working cross-browser in all cases, so that's the one I ended up using.
-Stijn
Until I saw this thread I never considered that the constructor might be a property of an instance, but I think the following code covers that rare scenario.
// Store instances in a variable to compare against the current this
// Based on Tim Down's solution where instances are tracked
var Klass = (function () {
// Store references to each instance in a "class"-level closure
var instances = [];
// The actual constructor function
return function () {
if (this instanceof Klass && instances.indexOf(this) === -1) {
instances.push(this);
console.log("constructor");
} else {
console.log("not constructor");
}
};
}());
var instance = new Klass(); // "constructor"
instance.klass = Klass;
instance.klass(); // "not constructor"
For most cases I'll probably just check instanceof.
From John Resig:
function makecls() {
return function(args) {
if( this instanceof arguments.callee) {
if ( typeof this.init == "function")
this.init.apply(this, args.callee ? args : arguments)
}else{
return new arguments.callee(args);
}
};
}
var User = makecls();
User.prototype.init = function(first, last){
this.name = first + last;
};
var user = User("John", "Resig");
user.name
If you're going hackish, then instanceof is the minimum solution after new.target as by other answers. But using the instanceof solution it would fail with this example:
let inst = new x;
x.call(inst);
Combining with #TimDown solution, you can use ES6's WeakSet if you want compatibility with older ECMAScript versions to prevent putting properties inside instances. Well, WeakSet will be used in order to allow unused objects be garbage collected. new.target won't be compatible in the same source code, as it is a ES6's syntax feature. ECMAScript specifies identifiers cannot be one of the reserved words, and new is not an object, anyways.
(function factory()
{
'use strict';
var log = console.log;
function x()
{
log(isConstructing(this) ?
'Constructing' :
'Not constructing'
);
}
var isConstructing, tracks;
var hasOwnProperty = {}.hasOwnProperty;
if (typeof WeakMap === 'function')
{
tracks = new WeakSet;
isConstructing = function(inst)
{
if (inst instanceof x)
{
return tracks.has(inst) ?
false : !!tracks.add(inst);
}
return false;
}
} else {
isConstructing = function(inst)
{
return inst._constructed ?
false : inst._constructed = true;
};
}
var z = new x; // Constructing
x.call(z) // Not constructing
})();
ECMAScript 3's instanceof operator of is specified as:
11.8.6 The instanceof operator
--- The production RelationalExpression: RelationalExpression instanceof ShiftExpression is evaluated
as follows:
--- 1. Evaluate RelationalExpression.
--- 2. Call GetValue(Result(1)).
--- 3. Evaluate ShiftExpression.
--- 4. Call GetValue(Result(3)).
--- 5. If Result(4) is not an object, throw a TypeError exception.
--- 6. If Result(4) does not have a [[HasInstance]] method, throw a TypeError exception.
--- 7. Call the [[HasInstance]] method of Result(4) with parameter Result(2).
--- 8. Return Result(7).
15.3.5.3 [[HasInstance]] (V)
--- Assume F is a Function object.
--- When the [[HasInstance]] method of F is called with value V, the following steps are taken:
--- 1. If V is not an object, return false.
--- 2. Call the [[Get]] method of F with property name "prototype".
--- 3. Let O be Result(2).
--- 4. If O is not an object, throw a TypeError exception.
--- 5. Let V be the value of the [[Prototype]] property of V.
--- 6. If V is **null**, return false.
--- 7. If O and V refer to the same object or if they refer to objects joined to each other (13.1.2), return true.
--- 8. Go to step 5.
And that means it'll be recursing the left hand side value after going to its prototype until it is not an object or until it is equal to the prototype of the right hand side object with the specified [[HasInstance]] method. What means it'll check if left hand side is an instance of the right hand side, consuming all internal prototypes of the left hand side though.
function x() {
if (this instanceof x) {
/* Probably invoked as constructor */
} else return 30;
}
maybe I`m wrong but (at the cost of a parasite) the following code seems like a solution:
function x(arg) {
//console.debug('_' in this ? 'function' : 'constructor'); //WRONG!!!
//
// RIGHT(as accepted)
console.debug((this instanceof x && !('_' in this)) ? 'function' : 'constructor');
this._ = 1;
return 30;
}
var result1 = x(4), // function
result2 = new x(4), // constructor
Z = new x(); // constructor
Z.lolol = x;
Z.lolol(); // function
Although this thread is ancient, I'm surprised that nobody has mentioned that under strict mode ('use strict') a function's default this value is undefined, instead of set to global/window as before, so to check if new is not used simply test for falsey value of !this
- EG:
function ctor() { 'use strict';
if (typeof this === 'undefined')
console.log('Function called under strict mode (this == undefined)');
else if (this == (window || global))
console.log('Function called normally (this == window)');
else if (this instanceof ctor)
console.log('Function called with new (this == instance)');
return this;
}
If you test that function as-is, you will get undefined as this value, due to the 'use strict' directive at the start of the function. Of course, if already has strict mode on then it won't change if you remove the 'use strict' directive, but otherwise if you remove it the this value will be set to window or global.
If you use new to call the function then the this value will match the instanceof check (although if you checked the other things, then instance is last option so this check is not needed, and to be avoided if you want to inherit instances anyway)
function ctor() { 'use strict';
if (!this) return ctor.apply(Object.create(ctor.prototype), arguments);
console.log([this].concat([].slice.call(arguments)));
return this;
}
This will log the this value and any arguments you pass to the function to console, and return the this value. If the this value is falsey then it creates a new instance using Object.create(ctor.prototype) and uses Function.apply() to re-call the constructor with the same params but with correct instance as this. If the this value is anything other than falsey then it is assumed to be a valid instance and returned.
I believe the solution is to turn your Constructor function into a wrapper of the real Constructor function and its prototype Constructor if required. This method will work in ES5 from 2009 and also work in strict mode. In the code window below I have an example using the module pattern, to hold the real constructor and its prototype's constructor, in a closure, which is accessible through scope within the constructor(wrapper). This works because no property is added to the "this" keyword within the Constructor(wrapper) and the Constructor(wrapper).prototype is not set, so is Object by default; thus the array returned from Object.getpropertyNames will have a length equal to 0, if the new keyword has been used with the Constructor(wrapper). If true then return new Vector.
var Vector = (function() {
var Vector__proto__ = function Vector() {
// Vector methods go here
}
var vector__proto__ = new Vector__proto__();;
var Vector = function(size) {
// vector properties and values go here
this.x = 0;
this.y = 0;
this.x = 0;
this.maxLen = size === undefined? -1 : size;
};
Vector.prototype = vector__proto__;
return function(size){
if ( Object.getOwnPropertyNames(this).length === 0 ) {
// the new keyword WAS USED with the wrapper constructor
return new Vector(size);
} else {
// the new keyword was NOT USED with the wrapper constructor
return;
};
};
})();
Tim Down I think is correct. I think that once you get to the point where you think you need to be able to distinguish between the two calling modes, then you should not use the "this" keyword. this is unreliable, and it could be the global object, or it could be some completely different object. the fact is, that having a function with these different modes of activation, some of which work as you intended, others do something totally wild, is undesirable. I think maybe you're trying to figure this out because of that.
There is an idiomatic way to create a constructor function that behaves the same no matter how it's called. whether it's like Thing(), new Thing(), or foo.Thing(). It goes like this:
function Thing () {
var that = Object.create(Thing.prototype);
that.foo="bar";
that.bar="baz";
return that;
}
where Object.create is a new ecmascript 5 standard method which can be implemented in regular javascript like this:
if(!Object.create) {
Object.create = function(Function){
// WebReflection Revision
return function(Object){
Function.prototype = Object;
return new Function;
}}(function(){});
}
Object.create will take an object as a parameter, and return a new object with that passed in object as its prototype.
If however, you really are trying to make a function behave differently depending on how it's called, then you are a bad person and you shouldn't write javascript code.
If you don't want to put a __previouslyConstructedByX property in the object - because it pollutes the object's public interface and could easily be overwritten - just don't return an instance of x:
function x() {
if(this instanceof x) {
console.log("You invoked the new keyword!");
return that;
}
else {
console.log("No new keyword");
return undefined;
}
}
x();
var Z = new x();
Z.lolol = x;
Z.lolol();
new Z.lolol();
Now the x function never returns an object of type x, so (I think) this instanceof x only evaluates to true when the function is invoked with the new keyword.
The downside is this effectively screws up the behaviour of instanceof - but depending on how much you use it (I don't tend to) that may not be a problem.
If you're goal is for both cases to return 30, you could return an instance of Number instead of an instance of x:
function x() {
if(this instanceof x) {
console.log("You invoked the new keyword!");
var that = {};
return new Number(30);
}
else {
console.log("No new");
return 30;
}
}
console.log(x());
var Z = new x();
console.log(Z);
Z.lolol = x;
console.log(Z.lolol());
console.log(new Z.lolol());
I had this same problem when I tried to implement a function that returns a string instead of an object.
It seems to be enough to check for the existence of "this" in the beginning of your function:
function RGB(red, green, blue) {
if (this) {
throw new Error("RGB can't be instantiated");
}
var result = "#";
result += toHex(red);
result += toHex(green);
result += toHex(blue);
function toHex(dec) {
var result = dec.toString(16);
if (result.length < 2) {
result = "0" + result;
}
return result;
}
return result;
}
Anyway, in the end I just decided to turn my RGB() pseudoclass into an rgb() function, so I just won't try to instantiate it, thus needing no safety check at all. But that would depend on what you're trying to do.
function createConstructor(func) {
return func.bind(Object.create(null));
}
var myClass = createConstructor(function myClass() {
if (this instanceof myClass) {
console.log('You used the "new" keyword');
} else {
console.log('You did NOT use the "new" keyword');
return;
}
// constructor logic here
// ...
});
On the top of the question, below code will auto-fix the issue in case function is called without new.
function Car() {
if (!(this instanceof Car)) return new Car();
this.a = 1;
console.log("Called as Constructor");
}
let c1 = new Car();
console.log(c1);
This can achieved without using ES6 new.target. You can run your code in strict mode and in this case value of this will be undefined if called without new otherwise it will be empty object.
Example::
"use strict"
function Name(){
console.log(this)
if(this){
alert("called by new")
}
else
alert("did not called using new")
}
new Name()
Use this instanceof arguments.callee (optionally replacing arguments.callee with the function it's in, which improves performance) to check if something is called as a constructor. Do not use this.constructor as that can be easily changed.

Categories