How do I determine object that function is a method of? - javascript

var A = {
x : function () { }
};
var b = function (method) {
//want to know method's "parent" here
};
b(A.x);
I want to know that x is defined in A when I call the b(A.x). Is this possible?

There's no nice built-in way to do this, because actually there are no methods in Javascript. They are independent Function objects that just happen to be assigned somewhere.
If you create new instance of function every time (e.g. closure) [thanks Matthew Crumley for pointing that out], then you can modify the function object to explicitly associate it with its parent:
x.parent = A;
and then you can call it properly as if it was a method:
x.call(x.parent);
Otherwise you will have to pass both function and its parent object.

This question makes little sense from the perspective of the language as a function may exist on many objects.
var a = { name : 'a' },
b = { name : 'b' },
c = { name : 'c' };
a.x = function () { alert( this.name ); };
c.x = b.x = a.x; // a, b, and c all reference the same function
You may call the x function with any context you want:
a.x(); // alerts "a" because "this" is object a
b.x(); // alerts "b" because "this" is object b
a.x.call( b ); // alerts "b" because "this" is object b (via parameter)
You can manipulate this behavior to work for you:
var b = function ( method ) {
// parent = this;
};
b.call( A, A.x );
There isn't however any way of knowing from inside a function what object it is assigned to as this isn't necessarily a single place.

Even adding a parent property won't work in all cases, because if the function is in the object's prototype, there is only one copy of the function object, so there's no way to tell which instance it came from. Here's an example to show the problem:
function MyClass() {
// Create a MyClass object
}
MyClass.prototype.x = function() { return 42; };
var a = new MyClass();
a.x.parent = a; // Set the parent to a
var b = new MyClass();
b.x.parent = b; // b.x and a.x both reference the same function from MyClass.prototype
Now, a.x.parent and b.x.parent are both set to b.
#porneL's method will work as long as each object gets its own copy of the function.
It's probably better to modify the function to take a parent object and a method so it will work with any function.

Every function in JavaScript is actually a Function object.
<html>
<body>
<script>
var A = {
x: function (a_a, a_b) { alert(a_a + a_b); }
};
var b = function (a_method) {
alert(a_method.toString());
a_method.call(this, 1, 2);
};
b(A.x);
</script>

Related

How to refer itself in a function regardless of extenal variable changes?

I have a function which has other functions defined:
var A = function(n) {
console.log(n + A.num());
}
A.num = function() {
return 5;
}
I want to change the name to B and delete A:
var B = A;
A = undefined;
But, when I do B(), It gives an error throws: "Cannot read property 'num' of undefined", which is completely normal and expected.
How do I handle this?
PS: Anyone who thinks that changing A.num() with this.num(), It will not work
You can always refer to the current function using its explicit name (if it has one).
So, change the definition, to name the function, and refer to it using that:
var A = function currentFunction(n) {
console.log(n + currentFunction.num());
}
A.num = function() {
return 5;
}
var B = A;
A = undefined;
B(10); //15
console.log(typeof currentFunction) //undefined, function name is local
Note: the abovementioned approach won't work if the function is named implicitly, but will continue to work if the function is renamed via fn.name
Alternatively, if the function isn't an arrow function, you can also use arguments.callee, that will work even with anonymous functions, but its use isn't recommended:
var A = function (n) {
console.log(n + arguments.callee.num());
}
A.num = function() {
return 5;
}
var B = A;
A = undefined;
B(10); //15
Unfortunately, none of the above will work with arrow functions, if you want to refer to itself, use a named bound function expression instead.
actually that's normal, because in js you can't really copy object
// Define object bar
var bar = {
x : 'Hi'
}
console.log(bar.x); //Hi
// Assign it to foo
var foo = bar;
console.log(foo.x); //Hi
//But
foo.x = 'Hello!! Im foo.';
console.log(foo.x); //Hello!! Im foo.
console.log(bar.x); //Hello!! Im foo.
bar.x = "Nice to meet you foo!!";
console.log(foo.x); //Nice to meet you foo!!
console.log(bar.x); //Nice to meet you foo!!
you have to return a new one with the same value as the last
var foo = {...bar};
and this is not working because B is always calling 'num' from A that doesn't exist, One way to sever the parity would be stringify the initial function, then use a function constructor to create the clone after replacing the 'A' by 'B'
but tell me more why are you facing this problem ?
var A = function(n) {
if(!this.num){
console.log("This is not available coz obj is not created");
console.log("Below error is for testing purpose");
}
let a=this.num(n);
console.log(a);
}
//use prototype here
//A.num = function() {
A.prototype.num=function(n){
return n+5;
}
//use new to create object
new A(5);
var B = A;
A = undefined;
//use new to create object
new B(6);
B(5);//lets try without using new keyword
.as-console-wrapper { max-height: 100% !important; top: 0; }

Scope Inside The Object Constructor Function

I am defining the consctructor function Foo as:
function Foo () {
var a= 0;
this.b = 1;
this.f1= function () { return a; };
this.f2= function () { return b; };
}
and I am creating the object as:
var bar= new Foo();
return b does not work, I have to use return this.b instead. But it work fine with the a variable. Why?
When your function
f1
is invoked, it asks it's environment/context "Excuse me, do you have any idea what [a] is please?". It responds with "Not here, but let me ask my own environment/context whether or not it knows what [a] is... ah hah, it says it knows what [a] is, and it's value is 0.".
When your function
f2
is invoked, it asks it asks the same question of [b] as f1 did for [z]... the difference is, the environment/context it is looking in for [b] does not include the instance of Foo to which [b] has been attached.
'this' in JavaScript is a tricky subject, and is covered in great detail in this free online book which is part of the series "You don't know JS", by Kyle Simpson. A very good series.
It doesn't return because b is not declared.
function Foo () {
var a = 0;
this.b = 1;
var b = this.b;
this.f1= function () { return a; };
this.f2= function () { return b; };
}
should work fine.
Or you can bind f2 method to "this" and return it:
function Foo () {
var a= 0;
this.b = 1;
this.f1= function () { return a; };
this.f2= (function () { return this.b; }).bind(this);
}
Your function declares two types of constructs. var a is a normal variable that is scoped to the function and it is private within the function. It can be used any way the function needs to, so returning it is no problem at all. Most importantly, its value will not change from one instance of Foo to the next.
b, f1 and f2 aren't being declared as variables. They are being declared as "instance properties", meaning that their data will change from one instance of the object to another. If you want to return an instance property value, you must use this to return the value associated with that particular instance.
After all, if you wrote:
var obj1 = new Foo();
obj1.b = 10;
var obj2 = new Foo();
obj1.b = 20;
How would you be able to keep the two b values separate from each other? The answer is that you have two instances of a Foo object and the obj1 and obj2 variables each store a reference to their own instance.
When you write obj1.b, you need access to the b property that belongs to the obj1 object instance. The this keyword does this for you.
Read on for more details:
The this object binding is volatile in JavaScript...that is, it doesn't always point to the same object and its binding can change from one line of code to the very next. How you invoke the code that contains the word this determines what object it will bind to.
Here's a checklist that you can follow to know what this will bind to...
If the code that contains this is invoked:
As a method or property of an object instance (through an instance variable):
var o = new Object();
// "this" will be bound to the "o" object instance
// while "someProperty" and "someMethod" code executes
o.someProperty = someValue;
o.someMethod();
Via a .call(), .apply(), .bind() or Array.prototype.fn invocation:
// "this" will be bound to the object suppled as the "thisObjectBinding"
someFunction.call(thisObjectBinding, arg, arg);
someFunction.apply(thisObjectBinding, [arg, arg]);
var newFunc = someFunction.bind(thisObjectBinding, arg, arg);
Additionally, several Array.prototype methods allow for a thisObject to be passed which will alter the binding for the duration of the method call:
Array.prototype.every( callbackfn [ , thisArg ] )
Array.prototype.some( callbackfn [ , thisArg ] )
Array.prototype.forEach( callbackfn [ , thisArg ] )
Array.prototype.map( callbackfn [ , thisArg ] )
Array.prototype.filter( callbackfn [ , thisArg ] )
If none of the other scenarios apply, Default binding occurs.
3a. With "use strict" in effect: this is undefined
3b. Without "use strict" in effect: this binds to the Global object
** NOTE: this binding can also be affected by using eval(), but as a general best practice, the use of eval() should be avoided.

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"

Is this proper javascript for making a namespace that encapsulates various methods into different objects?

var namespaced = {
A: function(){
function r(){
//do some stuff
return something;
}
var someProperty = 5;
function j(){
//do some more stuff
return something;
}
},
B: function(){
//can I call A and C?
A.r();
C.d();
},
C: function(){
function d() {
//do stuff we like
}
}
}
Then I could do...
namespaced.A.j();
namespaced.C.d();
something = namespaced.A.someProperty;
right?
Would I need to do this too?
var something = new namespaced.A()?
If so does A() have a constructor? I'm really confused here :{
I'm trying to encapsulate my javascript so it's easy to maintain
Then I could do...
namespaced.A.j();
namespaced.C.d();
something = namespaced.A.someProperty;
No you couldn't. The function j and someProperty are only local to A and are not propagated to the outside. If you want to access them from the outside, you have to make them a property of the function, using this:
var namespaced = {
A: function(){
this.r = function(){
//do some stuff
return something;
};
this.someProperty = 5;
this.j = function(){
//do some more stuff
return something;
};
}
}
But you would still need to call var a = new namespaced.A() in order to access the functions.
If you want to call namespaced.A.j() directly, you would have to declare A as object, not as function:
var namespaced = {
A: {
r: function(){
//do some stuff
return something;
},
someProperty: 5,
j: function(){
//do some more stuff
return something;
}
}
}
So it depends on what you want to achieve eventually... to get a better insight into these methods, I recommend JavaScript Patterns.
This is what you need to understand about JavaScript:
When you write
var obj = { A: a, B: b, C: c };
you are creating (and assigning to obj) an object with properties called A, B and C mapping to values a, b and c respectively. These values may very well be functions, so when you have
var obj = { A: function(){...} };
you are creating an object with a property called "A" which is a function. You can refer to it with obj.A and call with obj.A().
When you call obj.A(), the keyword this inside the body of function A will refer to obj. You can use it to assign new properties to obj:
var obj = {
A: function() { this.prop = "Hello!"; }
};
obj.A();
alert( obj.prop ); // alerts "Hello!"
So, inside namespaced.A.j() the this keyword will point to namespace.A (it's what is to the left of the last dot).
You can apply a function to an object like so: func.apply(obj) or like so: func.call(obj). In this case, the this keyword will refer to obj instead. This isn't relevant to your case, but if func takes parameters (let's say param1 and param2), you can apply the function like so: func.apply(obj, [val1, val2]) or like so: func.call(obj, val1, val2).
All variables declared inside a function live only inside that function. They are not visible outside. And when you write function doStuff(){} it's (I'm simplifying here) as good as if you wrote var doStuff = function(){}; So nested functions live and can be used only inside the surrounding function; that is, unless you assign them to something accessible from outside.
When you call something like new Cons() what happens is the creation of a new empty object followed by the application of Cons() on that object. In other words, it's the same as
var obj = {};
Cons.apply(obj);
or if you prefer:
var obj = {};
obj.Cons = Cons;
obj.Cons();
// obj's Cons property then mysteriously disappears
// unless it was explicitly set inside Cons() (oh my, how confusing! :)
So you can have this:
function Duck(name){
this.myName = name;
this.quack = function(){
alert(this.myName + " quacks!");
}
};
donald = new Duck('Donald');
donald.quack();
With all the preceding in mind, a way to write namespaced code is like this:
// The following syntax, confusing to someone who hasn't seen it before,
// is defining a new anonymous function and immediately using it
// as a constructor applied to a new empty object.
//
// Alternatively, you can use this syntax:
// var namespaced = {};
// (function(){
// ....
// }).apply(namespaced);
//
var namespaced = new (function(){
// This creates a new variable named "namespaced"
// which is visible only inside this anonymous function.
// This variable points to the still-empty object created by
// 'new'. This object will, once we're done with this anonymous function,
// be assigned to a variable, outside, which by "coincidence" is
// also named "namespaced".
var namespaced = this;
// You could alternatively not create the variable "namespaced"
// and use 'this' directly inside this anonymous function. But,
// the 'this' keyword may point to different objects inside the
// nested functions that follow, so we create it to avoid confusion.
// This assigns a new object to variable 'A', which isn't visible outside.
// Use a constructor function defined inline.
var A = new (function(){
var A = this; // 'this' now refers to the empty object created just above
this.someProperty = 5; // Two different ways of
A.anotherProperty = 7; // doing mostly the same thing
this.j = function(){
//do some more stuff
// 'this' will point to j, here
return something;
}
// Function r isn't visible outside of A's constructor like this!
function r(){
//do some stuff
return something;
}
// Make 'r' visible outside by assigning it to a property of 'A'.
// Look, it's also called "r". What fun!
A.r = r;
})();
// Make the object in variable 'A' visible outside of
// 'namespaced's constructor, by making it a property of 'namespaced'
namespaced.A = A;
// Create a new object as before.
// This time we won't make it visible outside
// of "namespaced"'s constructor.
var C = new (function(){
this.d = function (){
//do stuff we like
}
})();
// Give "namespaced" a property 'B'.
// This time it's a function instead of a nested object.
namespaced.B = function(){
// It's cool to make these function calls here, because
// (a) nested functions can see the variables ('A' & 'C')
// of surrounding functions, even if they terminate in the meantime;
// and (b) 'r' & 'd' are properties of 'A' and 'C'.
A.r();
C.d();
};
// You could return 'this' or 'namespaced' from this constructor,
// but the 'new' keyword will make sure the "namespaced" variable
// outside will get the no-longer-empty object it created,
// so you can just not return anything.
})();
// Now you can do
five = namespaced.A.someProperty;
seven = namespaced.A.anotherProperty;
something = namespaced.A.j();
namespaced.B(); // Calls A.r() and C.d()
// But you can't do
namespaced.C.d(); // WRONG: "namespaced" doesn't have a property named "C"
I hope this helps more than it confuses.

Declaring variables with this or var?

What is the difference between declaring a variable with this or var ?
var foo = 'bar'
or
this.foo = 'bar'
When do you use this and when var?
edit: is there a simple question i can ask my self when deciding if i want to use var or this
If it is global code (the code is not part of any function), then you are creating a property on the global object with the two snippets, since this in global code points to the global object.
The difference in this case is that when the var statement is used, that property cannot be deleted, for example:
var foo = 'bar';
delete foo; // false
typeof foo; // "string"
this.bar = 'baz';
delete bar; // true
typeof bar; "undefined"
(Note: The above snippet will behave differently in the Firebug console, since it runs code with eval, and the code executed in the Eval Code execution context permits the deletion of identifiers created with var, try it here)
If the code is part of a function you should know that the this keyword has nothing to do with the function scope, is a reserved word that is set implicitly, depending how a function is called, for example:
1 - When a function is called as a method (the function is invoked as member of an object):
obj.method(); // 'this' inside method will refer to obj
2 - A normal function call:
myFunction(); // 'this' inside the function will refer to the Global object
// or
(function () {})();
3 - When the new operator is used:
var obj = new Constructor(); // 'this' will refer to a newly created object.
And you can even set the this value explicitly, using the call and apply methods, for example:
function test () {
alert(this);
}
test.call("hello!"); //alerts hello!
You should know also that JavaScript has function scope only, and variables declared with the var statement will be reachable only within the same function or any inner functions defined below.
Edit: Looking the code you posted to the #David's answer, let me comment:
var test1 = 'test'; // two globals, with the difference I talk
this.test2 = 'test'; // about in the beginning of this answer
//...
function test4(){
var test5 = 'test in function with var'; // <-- test5 is locally scoped!!!
this.test6 = 'test in function with this'; // global property, see below
}
test4(); // <--- test4 will be called with `this` pointing to the global object
// see #2 above, a call to an identifier that is not an property of an
// object causes it
alert(typeof test5); // "undefined" since it's a local variable of `test4`
alert(test6); // "test in function with this"
You can't access the test5 variable outside the function because is locally scoped, and it exists only withing the scope of that function.
Edit: In response to your comment
For declaring variables I encourage you to always use var, it's what is made for.
The concept of the this value, will get useful when you start working with constructor functions, objects and methods.
If you use var, the variable is scoped to the current function.
If you use this, then you are assigning a value to a property on whatever this is (which is either the object the method is being called on or (if the new keyword has been used) the object being created.
You use var when you want to define a simple local variable as you would in a typical function:-
function doAdd(a, b)
{
var c = a + b;
return c;
}
var result = doAdd(a, b);
alert(result);
However this has special meaning when call is used on a function.
function doAdd(a, b)
{
this.c = a + b;
}
var o = new Object();
doAdd.call(o, a, b);
alert(o.c);
You note the first parameter when using call on doAdd is the object created before. Inside that execution of doAdd this will refer to that object. Hence it creates a c property on the object.
Typically though a function is assigned to a property of an object like this:-
function doAdd(a, b)
{
this.c = a + b;
}
var o = new Object();
o.doAdd = doAdd;
Now the function can be execute using the . notation:-
o.doAdd(a, b);
alert(o.c);
Effectively o.doAdd(a, b) is o.doAdd.call(o, a, b)
var foo = 'bar'
This will scope the foo variable to the function wrapping it, or the global scope.
this.foo = 'bar'
This will scope the foo variable to the this object, it exactly like doing this:
window.foo = 'bar';
or
someObj.foo = 'bar';
The second part of your question seems to be what is the this object, and that is something that is determined by what context the function is running in. You can change what this is by using the apply method that all functions have. You can also make the default of the this variable an object other than the global object, by:
someObj.foo = function(){
// 'this' is 'someObj'
};
or
function someObj(x){
this.x=x;
}
someObj.prototype.getX = function(){
return this.x;
}
var myX = (new someObj(1)).getX(); // myX == 1
In a constructor, you can use var to simulate private members and this to simulate public members:
function Obj() {
this.pub = 'public';
var priv = 'private';
}
var o = new Obj();
o.pub; // 'public'
o.priv; // error
Example for this and var explained below:
function Car() {
this.speed = 0;
var speedUp = function() {
var speed = 10; // default
this.speed = this.speed + speed; // see how this and var are used
};
speedUp();
}
var foo = 'bar'; // 'var can be only used inside a function
and
this.foo = 'bar' // 'this' can be used globally inside an object

Categories

Resources