Adding a function to only a certain object - javascript

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.

Related

Is it completely impossible to reach into a JavaScript closure? [duplicate]

I was wondering if there is any way to access variables trapped by closure in a function from outside the function; e.g. if I have:
A = function(b) {
var c = function() {//some code using b};
foo: function() {
//do things with c;
}
}
is there any way to get access to c in an instance of A. Something like:
var a_inst = new A(123);
var my_c = somejavascriptmagic(a_inst);
A simple eval inside the closure scope can still access all the variables:
function Auth(username)
{
var password = "trustno1";
this.getUsername = function() { return username }
this.eval = function(name) { return eval(name) }
}
auth = new Auth("Mulder")
auth.eval("username") // will print "Mulder"
auth.eval("password") // will print "trustno1"
But you cannot directly overwrite a method, which is accessing closure scope (like getUsername()), you need a simple eval-trick also:
auth.eval("this.getUsername = " + function() {
return "Hacked " + username;
}.toSource());
auth.getUsername(); // will print "Hacked Mulder"
Variables within a closure aren't directly accessible from the outside by any means. However, closures within that closure that have the variable in scope can access them, and if you make those closures accessible from the outside, it's almost as good.
Here's an example:
var A = function(b) {
var c = b + 100;
this.access_c = function(value) {
// Function sets c if value is provided, but only returns c if no value
// is provided
if(arguments.length > 0)
c = value;
return c;
};
this.twain = function() {
return 2 * c;
};
};
var a_inst = new A(123);
var my_c = a_inst.access_c();
// my_c now contains 223
var my_2c = a_inst.twain();
// my_2c contains 446
a_inst.access_c(5);
// c in closure is now equal to 5
var newer_2c = a_inst.twain();
// newer_2c contains 10
Hopefully that's slightly useful to you...
Answers above are correct, but they also imply that you'll have to modify the function to see those closed variables.
Redefining the function with the getter methods will do the task.
You can do it dynamically.
See the example below
function alertMe() {
var message = "Hello world";
console.log(message);
}
//adding the getter for 'message'
var newFun = newFun.substring(0, newFun.lastIndexOf("}")) + ";" + "this.getMessage = function () {return message;};" + "}";
//redefining alertMe
eval(newFun);
var b = new alertMe();
now you can access message by calling b.getMesage()
Of course you'll have to deal with multiple calls to alertMe, but its just a simple piece of code proving that you can do it.
The whole point to that pattern is to prevent 'c' from being accessed externally. But you can access foo() as a method, so make it that it will see 'c' in its scope:
A = function(b) {
var c = function() {//some code using b};
this.foo = function() {
return c();
}
}
No, not without a getter function on A which returns c
If you only need access to certain variables and you can change the core code there's one easy answer that won't slowdown your code or reasons you made it a closure in any significant way. You just make a reference in the global scope to it basically.
(function($){
let myClosedOffObj = {
"you can't get me":"haha getting me would be useful but you can't cuz someone designed this wrong"
};
window.myClosedOffObj = myClosedOffObj;
})(jQuery);
myClosedOffObj["you can't get me"] = "Got you now sucker";
Proof of concept: https://jsfiddle.net/05dxjugo/
This will work with functions or "methods" too.
If none of the above is possible in your script, a very hacky solution is to store it in a hidden html-object:
// store inside of closure
html.innerHTML+='<div id="hiddenStore" style="display:none"></div>';
o=document.getElementById("hiddenStore")
o.innerHTML="store this in closure"
and outside you can read it with
document.getElementById("hiddenStore").innerHTML
You should be able to use an if statement and do something like:
if(VaraiableBeingPasses === "somethingUniqe") {
return theValueOfC;
}

Call function so this not needed

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

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.

Is it possible to modify a function itself when its property function is called?

Basically I want to do this:
someFunction() // do something
someFunction.somePropertyFunction()
someFunction() // Now someFunction is modified; it should now exhibit a different behaviour
Is this possible?
EDIT:
I'm not looking for what #Kolink was suggesting. Basically I want to augment a function's functionality by calling one of it's property function.
Specifically, I need to: 1. have access to the original function inside my property function (which is entirely doable using this), and 2. bind a new function to the original function's name (which I'm not sure if it's possible).
Just to be clear, I don't have access to the internal definition of the function that I want to augment. I want to attach a function to Function.prototype (so that it will be available as a property of the function that I want to augment), and then I will call func.augmentThis(), and then func should be augmented. But I'm not sure how, hence the question :P
Easily. Here's an example:
var derp = 123;
someFunction = function() {alert(derp);};
someFunction.somePropertyFunction = function() {derp = 456;};
someFunction(); // alerts 123
someFunction.somePropertyFunction();
someFunction(); // alerts 456
Okay, that's an oversimplified example, but yeah, it's entirely possible.
If your question is whether a function attached as a property to another function has a way to access the function to which it is attached, the answer is no. After all, the same function could be attached to any number of functions of objects.
So one alternative is to explicitly refer to the "mother" function within the function that is attached to it and intended to change its behavior:
function f (n) { alert (n + f.offset); }
f.offset = 0;
f.change_offset = function (i) { f.offset = i; };
f (1); //1
f.change_offset (100);
f (1); //101
Here, f is hard-wired into the definition of change_offset. If this bothers you, or you want something slightly more general, write a little routine to set a function as a property on another function, while binding its this to the function being attached to:
function set_func_as_func_prop ( propname, func_to_set, func_to_set_on ) {
func_to_set_on[propname] = func_to_set.bind(func_to_set_on);
}
Now you can write the function more generally
function change_offset (i) {
this.offset = i;
}
and set it on f or any other function.
set_func_as_func_prop ("change_offset", change_offset, f);
set_func_as_func_prop ("change_offset", change_offset, g);
Sort of:
function someFunction() {
return realFunction.apply(this, arguments);
}
function someFunctionA(name) {
return 'Hello, ' + name + '!';
}
function someFunctionB(name) {
return 'Goodbye, ' + name + '...';
}
var realFunction = someFunctionA;
someFunction.somePropertyFunction = function () {
realFunction = someFunctionB;
};
Sure it's possible. It's not recommended, but it's possible. For example:
function a() {
alert("a");
}
function b() {
alert("b");
}
function c() {
return c.f.apply(this, arguments);
}
c.f = a;
c.toggle = function () {
c.f = c.f === a ? b : a;
};
Now let's test it:
c(); // alerts "a"
c.toggle();
c(); // alerts "b"
See the demo: http://jsfiddle.net/LwKM3/
I want to attach a function to Function.prototype. Then I need to bind a new function to the original function's name (which I'm not sure if it's possible).
That indeed is impossible, you don't know what refers to the function. And you cannot change the internal representation of a function, which is immutable.
The only thing you can do is to create a new function and return that, to let the caller of your method use it somehow - specifically assigning it to the original variable:
somefunction = somefunction.augmentSomehow();
Your method for that will look like this:
Function.prototype.augmentSomehow = function() {
var origFn = this;
return function() {
// in here, do something special
// which might include invoking origFn() in a different way
};
};
Not sure if this helps, but I would implement described problem in following way:
// defined by somebody else - unknown to developer
var someFunction = function() {
alert("this is initial behavior");
}
someFunction(); // returns "this is initial behavior"
// defines parent object on which someFunction() is called
var parentObject = this; // returns window object (as called direclty in the
// browser)
// if you are calling someFunction from some object (object.someFunction())
// it would be:
// var parentObject = object;
// augumentThis definition
someFunction.augumentThis = function() {
var newFunction = function() {
alert("this is changed behavior");
};
parentObject.someFunction.somePropertyFunction = function() {
parentObject.someFunction = newFunction;
parentObject.someFunction();
};
};
someFunction.augumentThis(); // change function behavior
someFunction(); // "this is initial behavior"
someFunction.somePropertyFunction(); // "this is changed behavior"
someFunction(); // "this is changed behavior"

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