I am using arguments.callee.caller.name to get the name of the function where this function is called.
for example:
class B {
a = 0;
called_from = false;
setA = (asume)=>{
this.a = assume;
this.called_from = arguments.callee.caller.name;
console.log(this.called_from);
};
callA = ()=>{
this.setA();
};
}
Now I want to get the callA name in the logs.
Using info from Accessing line number in V8 JavaScript (Chrome & Node.js)
you can add some prototypes to provide access to this info from V8;
Object.defineProperty(global, '__stack', {
get: function() {
var orig = Error.prepareStackTrace;
Error.prepareStackTrace = function(_, stack) {
return stack;
};
var err = new Error;
Error.captureStackTrace(err, arguments.callee);
var stack = err.stack;
Error.prepareStackTrace = orig;
return stack;
}
});
Object.defineProperty(global, '__line', {
get: function() {
return __stack[1].getLineNumber();
}
});
Object.defineProperty(global, '__function', {
get: function() {
return __stack[1].getFunctionName();
}
});
function foo() {
console.log(__line);
console.log(__function);
}
foo()
Related
So i have this code:
function Class1() {
this.i = 1;
var that=this;
function nn() {
return 21;
}
this.aa = function() {
nn();
};
this.bb = function() {
this.aa();
};
this.cc = function() {
this.bb();
};
}
var o = new Class1();
var b=o.cc();
alert(b); //undefined
But when the alert is fired, I get an undefined error and not 21, Does the private method can not use a return? Thanks!
When using the function() {} syntax to define a function, you always explicitly need to return the value, i.e. not only from nn, but from all intermediate functions as well.
function Class1() {
this.i = 1;
var that = this;
function nn() {
return 21;
}
this.aa = function() {
return nn();
}
this.bb = function() {
return this.aa();
}
this.cc = function() {
return this.bb();
}
}
var o = new Class1();
var b = o.cc();
alert(b); // "21"
Apart from the answer above, the 'this' context seems weird in your functions. Maybe you are better of with arrow functions if you dont want to bind the this context to each function. I also think that it is better to actually separate private and public functions when using a 'class' like this.
function Class1() {
var _nn = function () {
return 21;
}
var _aa = function () {
return _nn();
}
var _bb = function () {
return _aa();
}
var cc = function () {
return _bb();
};
return {
cc
};
}
var o = new Class1();
var a = o.cc();
console.log(a);
Much easier to understand that it is only cc that is a public function.
So with arrow function it would instead look like this, and you can use the Class1 this context inside of your private functions without doing
var that = this; or using bind.
function Class1() {
this.privateThing = 'private';
var _nn = () => { return this.privateThing; };
var _aa = () => { return _nn(); };
var _bb = () => { return _aa(); };
var cc = () => { return _bb(); };
return {
cc
};
}
I'm studying Javascript and learning how to use call. I created this script and I don't know why I can't have access to this variable Time.
var MyObject;
(function(MyObject) {
var Runner = (function() {
function Runner(time) {
this.time = time;
}
var myFunctionArray = [];
Runner.prototype.execute = function() {
myFunctionArray[0]();
}
Runner.prototype.newTest = function(index, execute) {
var test = function() {
return execute.call(this);
}
myFunctionArray.push(test);
}
return Runner;
})();
MyObject.Runner = Runner;
})(MyObject || (MyObject = {});
var myNewObj = new MyObject.Runner(1000); myNewObj.newTest('1', function() {
console.log(this.time) //output: undefined
});
So how can I get time value inside newTest function?
Issue is in newTest function
Runner.prototype.newTest = function(index, execute) {
var test = function() {
return execute.call(this);
}
myFunctionArray.push(test);
}
Here this is pointing to test and not Runner. You will have to save context in a variable and then set it in call.
Runner.prototype.newTest = function(index, execute) {
var self = this;
var test = function() {
return execute.call(self);
}
myFunctionArray.push(test);
}
.call + self
var MyObject;
(function(MyObject) {
var Runner = (function() {
function Runner(time) {
this.time = time;
}
var myFunctionArray = [];
Runner.prototype.execute = function() {
myFunctionArray[0]();
}
Runner.prototype.newTest = function(index, execute) {
var self = this;
var test = function() {
return execute.call(self);
}
myFunctionArray.push(test);
}
return Runner;
})();
MyObject.Runner = Runner;
})(MyObject || (MyObject = {}));
var myNewObj = new MyObject.Runner(1000);
myNewObj.newTest('1', function() {
console.log(this, this.time) //output: undefined
});
myNewObj.execute()
.bind
As commented, you can even use .bind
var MyObject;
(function(MyObject) {
var Runner = (function() {
function Runner(time) {
this.time = time;
}
var myFunctionArray = [];
Runner.prototype.execute = function() {
myFunctionArray[0]();
}
Runner.prototype.newTest = function(index, execute) {
myFunctionArray.push(execute.bind(this));
}
return Runner;
})();
MyObject.Runner = Runner;
})(MyObject || (MyObject = {}));
var myNewObj = new MyObject.Runner(1000);
myNewObj.newTest('1', function() {
console.log(this, this.time) //output: undefined
});
myNewObj.execute()
When you declare your Runner function, you've actually declared a function that takes no arguments that then itself declares a function called Runner that takes one argument.
Actually In this code snippet :
Runner.prototype.newTest = function(index, execute) {
var test = function() {
return execute.call(this);
}
myFunctionArray.push(test);
}
this will reference to test variable (as per constructor invocation pattern)
So, to pass right variable cache the value of this in another variable and then pass that to function.
I would like to override some functions (for logging some informations)
I'm trying to do something like:
function universe() {
return 42;
}
universe = universe.override(function(){
console.log("Calling universe");
return this.$super();
});
Full sample:
Function.prototype.override = function (fn) {
var $super = this;
var f = function overrided() {
var context = this || $super || {};
context.$super = $super;
return fn.apply(context, arguments);
};
f.$super = $super;
return f;
};
Function.prototype.unoverride = function () {
if (this.$super) {
return this.$super;
}
return this;
};
function universe() {
return 42;
}
function mulBy10() {
console.warn("calling overrided function");
return this.$super() * 10;
}
console.log("---------");
console.log("original:", universe());
universe = universe.override(mulBy10);
console.log("new one:", universe());
universe = universe.unoverride();
console.log("reverted:", universe());
console.log("--With Object");
var MyObject = function() {
this.value = 42;
}
MyObject.prototype = {
constructor: MyObject,
getValue: function() {
return this.value;
}
};
var o1 = new MyObject();
console.log("MyObject original:", o1.getValue());
o1.getValue = o1.getValue.override(mulBy10);
console.log("MyObject new one:", o1.getValue());
o1.getValue = o1.getValue.unoverride();
console.log("MyObject reverted:", o1.getValue());
console.log("--With Object prototype");
o2 = new MyObject();
MyObject.prototype.getValue = MyObject.prototype.getValue.override(mulBy10);
console.log("MyObject.proto new one:", o2.getValue());
MyObject.prototype.getValue = MyObject.prototype.getValue.unoverride();
console.log("MyObject.proto reverted:", o2.getValue());
console.log("--With recursive");
function recur(it, max) {
console.log("it:", it, "max:", max);
if( it >= max ) {
console.log("finished");
return;
}
recur(it + 1, max);
}
recur = recur.override(function(it, max){
console.warn("Overrided recur");
return this.$super(it, max);
});
recur(0, 4);
This works fine with function, object functions.
But it doesn't work when i try to override CasperJs "require" function.
I did:
require = require.override(function(file){
console.log("require(" + file + ")");
return this.$super(file);
});
So i was wondering, in which case, override function will not work ?
Did i missed something in CasperJS require function ?
I have a name of a private function in JavaScript as a string, how do I call that function?
var test = function () {
this.callFunction = function(index) {
return this["func" + index]();
}
function func1() { }
function func2() { }
...
function funcN() { }
}
var obj = new test();
obj.callFunction(1);
func1 and friends are local variables, not members of the object. You can't call them like that (at least not in any sane way).
Define them with function expressions (instead of function declarations) and store them in an array.
var test = function () {
this.callFunction = function(index) {
return funcs[index]();
}
var funcs = [
function () {},
function () {},
function () {}
];
}
var obj = new test();
obj.callFunction(0);
As your code stands, the functions are not present as properties of the instance. What you need to do is create them as properties of the context.
var test = function () {
this.callFunction = function(index) {
return this["func" + index];
}
this.func1 = function() { }
this.func2 = function() { }
...
}
var obj = new test();
obj.callFunction(1)();
you can use eval
var test = function () {
this.callFunction = function(index) {
return eval("func" + index + '()');
}
function func1() {
return 1;
}
function func2() {
return 2;
}
function funcN() { }
};
var obj = new test();
obj.callFunction(2);
eval is evil
You can use a private array of functions:
var test = function() {
var func = [
function() { return "one" },
function() { return "two"; }
]
this.callFunction = function(index) {
return func[index]();
}
}
var obj = new test();
var ret = obj.callFunction(1);
console.log(ret);
http://jsfiddle.net/V8FaJ/
Is there a way to specify something similar to the following in javascript?
var c = {};
c.a = function() { }
c.__call__ = function (function_name, args) {
c[function_name] = function () { }; //it doesn't have to capture c... we can also have the obj passed in
return c[function_name](args);
}
c.a(); //calls c.a() directly
c.b(); //goes into c.__call__ because c.b() doesn't exist
Mozilla implements noSuchMethod but otherwise...no.
No, not really. There are some alternatives - though not as nice or convenient as your example.
For example:
function MethodManager(object) {
var methods = {};
this.defineMethod = function (methodName, func) {
methods[methodName] = func;
};
this.call = function (methodName, args, thisp) {
var method = methods[methodName] = methods[methodName] || function () {};
return methods[methodName].apply(thisp || object, args);
};
}
var obj = new MethodManager({});
obj.defineMethod('hello', function (name) { console.log("hello " + name); });
obj.call('hello', ['world']);
// "hello world"
obj.call('dne');
Almost 6 years later and there's finally a way, using Proxy:
const c = new Proxy({}, {
get (target, key) {
if (key in target) return target[key];
return function () {
console.log(`invoked ${key}() from proxy`);
};
}
});
c.a = function () {
console.log('invoked a()');
};
c.a();
c.b();
No.