Call function so this not needed - javascript

I have an application that uses the v8 javascript engine, and within that I add functions to namespace objects that execute lines of code from the database. The contents of these functions need to not have this added before every function call. Following is some example code of my problem
var obj = {};
obj.method = function(a) { return a; }
obj.executor = function() { return method(5); }
obj.executor()
ReferenceError: method is not defined
var caller = function() { return method(5); }
caller.call(obj)
ReferenceError: method is not defined
As you can see, neither way allows me to call method without first adding this. Is there some way of executing a function so that it's context is set in such a way that this does not need to be added?
EDIT
This did work in a previous version of the v8 engine, but it seems the most recent one is not allowing it now.

"The client's write rules which are the strings loaded from the database, and it was a requirement (who knows why) that they only need to write the function names and the application sorts out the scoping."
If you're not running in strict mode, you can use a with statement.
var obj = {};
obj.method = function(a) { return a; };
obj.executor = function() {
with (this) {
return method(5);
}
};
obj.executor();
var caller = function() {
with (this) {
return method(5);
}
};
caller.call(obj);
Not saying this is a great solution, but it'll work if those are the requirements given.
I don't know your other requirements, but you can achieve this via a closure as well.
var obj = {};
(function() {
var method = obj.method = function(a) { return a; };
obj.executor = function() {
return method(5);
};
}();
obj.executor();

Related

Is it possible to make a function self aware without external input

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.

Having trouble extending a Javascript function with more functions

I'm trying to override a Javascript function that is included in a .js file that I cannot modify(it is served from a server our applications aren't deployed on). The function contains functions and variables within it. There is one sub-function that I need to change the behavior of but it is called by another, I can't call it directly. Here it is:
Simplistic version of included file that I can't change:
com.company.topLevelFunc = function () {
var a = null;
var b = null;
var doSomething = function() {
a = foo;
b = bar;
};
var get = function(cfg) {
//do stuff
};
return {
//other vars and functions here
getValue : function (cfg) {
cfg.url=a + b;
get(cfg);
}
};
}();
The function I need to override is the get(cfg). However, I can't call it directly, I need to go through the getValue(cfg) method and preserve all the other stuff that goes on in the top level function. So I've been trying to override both as follows:
My JS that I full control over, and doesn't work, it errors on the apply saying that 'missing : after property id". Am I doing this correct, not sure how to get the apply to work correctly?
var topLevel = com.company.topLevelFunc;
myTopLevel = function() {
var myGet = function(cfg) {
//do simliar but different stuff from the original get function
};
return {
topLevel.apply(this, arguments);
getMyValue : function (cfg) {
cfg.c= a + b +"some other string";
//do something
myGet(cfg);
}
};
}();
Unfortunately for you, the get method is private. It only exists inside the body of a an anonymous function nobody has access to. Aside from some very clever hacks and unrecommended programming, there is nothing you can do to change it.
What you should do in this case is change the getValue property of com.company.topLevelFunc. The way you are attempting to do that is slightly wrong and i will explain why.
a = function() { // this is not a
var c = function() { return 3; };
return { // this object is a
b : c;
}
}(); // called immediately
In this construct, a is not a function. The function you see there is invoked immediately and a is assigned the return value of that invocation. In fact this is almost equivalent:
a = { b : function() { return 3; } };
Why you would use the first construct instead of the second is a question asked many times here. A short answer is that the first allows you to have private stuff that nobody else can access (like your get method).
So a is an object with a property who's value is a function that returns 3. If you want a to return 4, you need to do something like this:
a.b = function() { return 4; }
This keeps the other properties of a intact (if it had any) and only changes the property you are interested in.
If you want b to access some private properties defined in the anonymous function above, it simply cannot be done.

prototype on single instances of functions

If I know that I only will create one instance of the MyClass function below, which of my two snippets below would you prefer? Should I stick with the latter, even though I know that I'll only create one instance of the function?
I know that prototype is useful from a performance perspective when sharing methods across all instances of a function, but in this case I would like to hear your input.
var MyClass = (function () {
var cls = function () { };
cls.prototype = {
init: function(data){
}
};
return cls;
})();
vs
var MyClass = (function () {
var cls = function () {
this.init = function(data){
}
};
return cls;
})();
Your second code snippet is a syntax error, you're trying to put a property initializer where a statement is expected. (Not anymore)
If you're only going to have a single object that you need the init function on, then:
var MyObject = {
init: function(data) {
// ...
}
};
Then you don't even need to call a function to create it, it's already there.
If you want to have truly private variables and such (which I assume is the reason for your outer anonymous functions), then:
var MyObject = (function() {
var trulyPrivateDataHere;
return {
init: function(data) {
// ...
}
};
})();
I prefer this because it's clear and direct: You're creating the actual object. I don't see any need for a constructor function if you're only ever going to create a single instance.
But if it has to be a constructor function, I guess I'd very marginally prefer your second option, because it's simpler, and simple is good barring the need for complexity.

Adding a function to only a certain object

I need a function to work for only the given object. I'm not sure if its possible, but I tried something like:
var a = {
b: function(a) {
return display(a)
}
}
a.prototype.display = function(a) {
return a;
}
alert(a.b('Hi'))​//This is suppose to work
alert(display(a))//This isn't suppose to work
This doesn't work though, not sure why. I'm kinda new to prototype. I used it with String.prototype for example but all the other stuff I still need to learn. Thanks for the help.
You need a private method in your object. The only way to achieve this in javascript is to keep the function in closure and execute it in the context of current object.
var a = (function () {
var display = function (a) {
return a;
};
return {
b : function(a) {
// display exist in closure scope of b;
//executing display in the context of current object
return display.apply(this, arguments);
}
};
})();
Here display is not accessible outside.
alert(a.b("hi")); //will return hi
a.display("hi"); is not accessible.

Javascript: How to get a reference to the parent object when "this" has been overwritten with "call"?

Okay, I'm hating Javascript right now, and I hope someone can help me.
I have code which is set up like the following:
function Obj1() {
var me = this;
this.something = "yay";
this.getThis = function(){
return me;
}
}
Obj1.prototype.method = function() {
return this.something;
};
function Obj2() {
this.something = "nay";
}
Obj2.prototype.method = function() {
return this.something;
};
var o1 = new Obj1();
var o2 = new Obj2();
document.write(o1.method()); // Returns yay
document.write(o1.method.call(o2)); // Returns nay, but I need "yay" here
(JSFiddle # http://jsfiddle.net/A9u9K/)
My Problem is, that I need to call Obj1.method in the second case, but I am absolutely unable to get a reference to the object :(
How can I work around this?
Edit: Sorry, I got my example code pretty wrong :( Updated it. I took most of the code from a previous answer, because it is much nicer and still illustrates my problem.
Updated Answer:
document.write(o1.method.call(o2)); // Returns nay, but I need "yay" here
You've said you've got it sorted now, but as the answer to that isn't actually shown here on SO, I figured I may as well update to show it.
If it's method you want to have access me, even if it's been called with a different this value, you have to define it like getThis, as a closure over me:
function Obj1() {
var me = this;
this.something = "yay";
this.method = function() {
return me.something;
};
this.getThis = function(){
return me;
};
}
function Obj2() {
this.something = "nay";
}
Obj2.prototype.method = function() {
return this.something;
};
...or of course, if you don't need the "something" to be a property on the object, just make it a var within the constructor (a private variable, like me):
function Obj1() {
var me = this;
var something = "yay";
this.method = function() {
return something;
};
this.getThis = function(){
return me;
};
}
function Obj2() {
this.something = "nay";
}
Obj2.prototype.method = function() {
return this.something;
};
Original Answer: (To Revision 1 of the question, which didn't have me.)
but I thought that, when creating a closure (as I do in 4) Javascript should preserve "this".
this is set entirely by how a function is called, not where it's defined; more about that here and here. But the way you've defined your getThis function, you can use the fact it closes over the constructor call to solve this (no pun) without using this:
function Obj1() {
var me = this; // <== Use a variable to remember `this`
this.something = "yay";
this.method = function() {
return this.something;
};
this.getThis = function(){
return me; // <== Return it
};
}
Live example
More about closures and the plumbing that makes the me thing work here.
There is a cost involved in this, and just generally in your pattern of defining functions within the constructor function: Each individual object created by Obj1 and Obj2 gets its own copy of each function. This can have memory implications if there are lots of these objects running around (but unless you have lots, you needn't worry and you get benefits like the me thing and other private variables). In constrast, if you use a function assigned to the prototype, all instances will share a single, common copy of the function.
In your sample code, only the getThis function really needs to be duplicated for every instance (because you're relying on the closure), so you can do this to avoid unnecessary function proliferation:
function Obj1() {
var me = this;
this.something = "yay";
this.getThis = function(){
return me;
};
}
Obj1.prototype.method = function() {
return this.something;
};
function Obj2() {
this.something = "nay";
}
Obj2.prototype.method = function() {
return this.something;
};
see it here http://jsfiddle.net/2Jhwv/5/
The issue is with the reference changing for the this object with scope.
Instead if using a this directly in closure use a local variable equated to this, i.e, change your Obj1 toL
function Obj1() {
this.something = "yay";
var that = this;
this.method = function() {
return that.something;
}
this.getThis = function(){
return that;
}
}
The only way to solve this is to another place holder to hold the value of this in Obj1 and use it in the function method() and getThis().
function Obj1() {
var instance = this;
this.something = "yay";
this.method = function() {
return instance.something;
}
this.getThis = function(){
return instance;
}
}
But what I cannot under stand is why you are doing it(obj1.getThis.call(obj2).method())?
This explicitly says that you want to change the scope of the method getThis() to something else, then you are trying to solve the problem which was created by this usage.
Can you tell why you want something like this?

Categories

Resources