I have an object litrel that has 2 anonymous functions defined as such:
obj = {
funcA : function(){
var a = 'a';
},
funcB : function(){
// but how do you access the scope in 'funcA' to access variable 'a'?
console.log(a)
}
}
I do not want to pass any variables just the scope of 'funcA' - thoughts?
JavaScript scope doesn't work like that because it has (only) function scope (except when using the let keyword).
What you could do is...
obj = {
a: 0,
funcA: function() {
this.a = 'a';
},
funcB: function() {
console.log(this.a);
}
};
jsFiddle.
You can use the a closure with the module pattern to get access to variables in an outer scope. More than one function can accesses the variable:
var obj = (function() {
var a;
return {
setA: function(value) {
a = value;
return a;
},
getA: function(value) {
return a;
},
multiplyA: function(value) {
a = a * value;
return a;
}
};
}());
alert( obj.setA(5) ); // 5
alert( obj.multiplyA(2) ); // 10
alert( obj.getA() ); // 10
See Douglas Crockford's article on Private Members in JavaScript. In this way, functions can share a common variable object on their scope chain. You still can't reference it or pass it to another function, but you might be able to get the functionality you want.
Does this code do what you want? If not, I'm really curious as to why.
obj = {
funcA : function(){
this.a = 'a';
alert(this.a);
},
funcB : function(){
// but how do you access the scope in 'funcA' to access variable 'a'?
alert(this.a);
}
}
obj.funcA();
obj.funcB();
What is the difference between accessing the actual scope of a separate function and setting members on the parent object as I have done?
Also, since there isn't a way of passing scope, are you just going to use something similar to this code instead?
Related
Can you please help me to find the error in the code? I need to pass one method's scope to another method.
var obj = {
doIt: function() {
var a = 10;
this.doThat.call(this);
},
doThat: function() {
console.log(a);
}
};
obj.doIt();
If you want to access a in the scope of context, you can try this.
var obj = {
doIt: function() {
this.a = 10;
this.doThat.call(this);
},
doThat: function() {
console.log(this.a);
}
};
obj.doIt();
You do pass the "context" (aka this) around. a however, is not part of the current context, but of the current scope. So you either move a into the context:
var obj = {
doIt: function() {
this.a = 10;
this.doThat();
},
doThat: function() {
console.log(this.a);
}
};
Or you directly pass the value of a into doThat:
//...
this.doThat(a);
doThat(a) { /*...*/ }
You need to understand that there is difference between context and scope. scope is going to be something which will dictate which variables are accessible from a particular site whereas context is what will be the value of this at particular site or inside a function.
so if you want to use value of a in function doThat you need to bind value of a with this which is context in function doIt like: this.a = 10; and then access it using console.log(this.a) inside function doThat
I have 2 objects: myObject1 and myObject2.
I am trying to call a private variable from myObject1 using my0bject2 method called increment, but console.log says NaN.
Is there any way to call myObject1 variable directly from myObject2 method? Maybe extend it somehow?
var myObject1 = function() {
var x = 0;
return{}
}();
var myObject2 = function() {
return{
increment: function() {
myObject1.x +=1;
console.log(myObject1.x);
}
}
}();
myObject2.increment();
When you specify var x within myObject1 you are declaring that variable as private. The only thing that has access to that variable are methods within myObject1. As you noted, this variable is private.
You didn't make it clear if you wanted to keep it private or not so I will assume you just want to access it. You could do a couple of things here.
You could attach the variable as an object property of myObject1 via this. this refers to the current scope (myObject1) so by saying this.x within myObject1 you are saying myObject1.x. From that function, you will need to return this so that instances of it can access all of its public properties.
var myObject1 = function() {
this.x = 0;
return this;
}();
var myObject2 = function() {
return {
increment: function() {
myObject1.x +=1;
console.log(myObject1.x);
}
}
}();
myObject2.increment();
You could also just return the properties that you want, in this case x. You have more control over what is returned in this case and you get the same result as above.
var myObject1 = function() {
var x = 0;
return {
x: x,
};
}();
var myObject2 = function() {
return {
increment: function() {
myObject1.x +=1;
console.log(myObject1.x);
}
}
}();
myObject2.increment();
Either way, these methods both expose the x property of myObject1 making it public.
Its because you have to create an instance of the function myObject before you can access its properties,
/* Create an object called myObject which can be instantiated using the new keyword */
var myObject = function() {
/* use 'this.x' to define an internal variable for x */
this.x = 0
};
/* this is where you create a new instance of myObject which will have the 'x' property */
var myObject1 = new myObject();
var myObject2 = function() {
return {
increment: function() {
myObject1.x += 1;
console.log(myObject1.x);
}
}
}();
myObject2.increment();
EDIT: Added comments to the code to explain the important modifications
myObject1 returns an object in which x is its own property. So now you're incrementing one of the property of the object. Earlier, with var x you were assuming to increment property of myObject1 but in fact it was just a local variable for that function which returned your object, i.e. declaring var x in function has no effect whatsoever.
var myObject1 = function() {
return{
x: 0
}
}();
var myObject2 = function() {
return{
increment: function() {
myObject1.x +=1;
console.log(myObject1.x);
}
}
}();
myObject2.increment();
In javascript, there is function scope, that is anything you define with var keyword is accessible within that function body.
Here you are implementing the module pattern. Your functions behave as constructors (or a factory) in your case (returning the object constructed). myObject2 cannot access x as it is defined in another scope and it is not included in the object generated by your first function.
You can return the x variable inside the return object;
var myObject1 = function() {
return{
x: 0
}
}();
That makes it a property on the returned object (that is assigned to myObject1) and you can access it.
You should study "function scope" and "module pattern" in more detail.
You're defining a variable in your functions scope. Instead, you should assign a variable to your current object (this) and of course return that object instead of an empty one.
var myObject1 = function() {
this.x = 0;
return this;
}();
Given the following Javascript example:
var obj = function() {
var _c = function() {
console.log("c")
}
return {
a: function() {
b();
},
b: function() {
console.log("b");
},
c: function() {
_c();
}
}
}();
calling obj.a() gives an error that b is not defined. This error can be solved by changing b() to this.b(). Can anyone help explain why this is necessary while c can access _c?
_c is a local variable that is in scope when _c() is executed. b is not; it is only found on the object itself, so it can be found by this.b.
This confusion is indicative of transplanting object-oriented concepts from other languages to JavaScript. There are no private and public members in JS, and you can't call methods on the same object by leaving the object prefix. There's just local variables (v when var v or let v), global variables (v when no var v or let v) and object properties (obj.prop). A method is object property that contains a function; no more, no less.
Need to use this.b because you are returning an object and 'b' in this context is the property of that object. you need to explicitly stated that using this
While _c is a local function defined inside the closure, you can access access it directly in the return object and does not refer to the return object.
You should not call b() directly.
var obj = function() {
var _c = function() {
console.log("c")
}
return {
b: function() {
console.log("b");
},
a: function() {
this.b();
},
c: function() {
_c();
}
}
}();
obj.a();
Explanation added :
You are calling b() inside a function where b() is defined on the object. So to call the function b() inside any other function, you should call b with reference to the object like
this.b();
I decided to create a funcB function that I call from funcA. I want all variables from funcA to be available in the funcB so func B can change that variables.
How to modify the code below so it meets my requirements? I doubt passing all variables it the only possible and the best way.
function funcB(){
alert(var1);//how to make it alert 5
alert(var20);//how to make it alert 50
}
function funcA(){
var var1=5;
...
var var20=50;
funcB();
}
var obj = {
one : "A",
two : "B",
fnA : function() {
this.fnB(); // without fnB method result will be displayed as A B, with fnB as C D
console.log(this.one + " " + this.two);
},
fnB : function() {
this.one = "C";
this.two = "D";
}
};
obj.fnA();
this keyword refers to obj object
You can define object with properties and methods inside it. With methods all the variables can be manipulated as you wish, from this example with fnB I'm changing values of properties which are displayed from fnA method
JSFiddle
One way is to drop the var keyword:
function funcB(){
alert(var1);//how to make it alert 5
alert(var20);//how to make it alert 50
}
function funcA(){
var1 = 5;
var20 = 50;
funcB();
}
This will expose them to the global scope so funcB can access them. Notice you can also create the varaibles in the global scope itself, with the var keyword, but both methods will ultimately have the same effect.
Note:
This may not work if there is already a var1 or var20 in the global scope. In such case, it will modify the global value and may result in unwanted errors.
This method is not preferred for official code, and is bad practice Reason
This is not possible as when you declare a variable with the var keyword, they are scoped to the function in which they are declared.
If you avoid the var keyword, they are instead defined as a global variable. This is deemed very bad practice.
I would recommend you read up on javascript coding patterns, particularly the module pattern.
For example:
var myNamespace = (function () {
var foo, bar;
return {
func1: function() {
foo = "baz";
console.log(foo);
},
func2: function (input) {
foo = input;
console.log(foo);
}
};
})();
Usage:
myNamespace.func1();
// "baz"
myNamespace.func2("hello");
// "hello"
I am having a JavaScript namespace say
A={
CA: function() {
this.B();
},
B: function() {
var test='test';
var result='t1';
C: function() {
this.test='test1';
.....
.....
return 'test1';
}
result=this.C();
return result;
}
}
Now when I am executing such code it is giving that TypeError: this.C is not a function. Can somebody tell me why it is so. I know it is something related with lexical scoping but am unable to understand this.
You have to be careful when you use this to identify anything in Javascript because each time you change scope "this" changes.
Assigning the 'this' reference to it's own variable helps get around this.
var a = new function() {
var self = this;
self.method = function() { alert('hiya'); };
var b = function() {
this.method(); // this isn't 'a' anymore?
self.method(); // but 'self' is still referring to 'a'
};
};
I think the problem is that when this.C() is executed inside the function referred to by B, this refers to the object that contains B, that is, object A. (This assumes B() is called within the context of A)
The problem is, C does not exist on the object A, since it's defined within B. If you want to call a local function C() within B, just use C().
EDIT:
Also, I'm not sure what you've posted is valid JavaScript. Specifically, B should be defined this way, since you can't use the object:property syntax within a function.
B: function()
{
var test='test';
var result='t1';
var C = function()
{
this.test='test1';
return 'test1';
}
result=C();
return result;
}
I am actually surprised that your code doesn't give you error on the 'C:' line.
Anyway, your syntax to define a function is not correct. Define it using the var keyword. Also, notice that I created the 'closure' so that the function C can access 'this'. See the code below:
A={
CA: function()
{
this.B();
},
B: function()
{
var test='test';
var result='t1';
var self = this;
var C = function()
{
self.test='test1';
.....
.....
return 'test1';
}
result=C();
return result;
}
}
If you want to assign C to 'this' object, you can also do:
A={
CA: function()
{
this.B();
},
B: function()
{
var test='test';
var result='t1';
var self = this;
this.C = function()
{
self.test='test1';
.....
.....
return 'test1';
};
result= this.C();
return result;
}
}
Solution for calling methods from another method. (Essentially the pointer "this" must be assigned to a variable and the new variable used in place of this.)
function myfunction(){
var me = this;
me.method1 = function(msg){ alert(msg); }
me.method2 = function(){
me.method1("method1 called from method2");
}
}
var f as new myfunction();
f.method2();
This example shows how one can call a method from within another method or from outside using an instance of the function.