Is there any way to get something like the following to work in JavaScript?
function a (){
return{
x: function foo(){
......
}
y: function bar(){
.......
.......
foo() //Doesn't work
.....
}
}
}
Is there a way to reference foo() inside the function bar() both of which happen to be inside the same return block?
If bar will always/only be called as part of an expression looking it up on the object or in any other way that ensures this refers to the object during the call, e.g.:
theObject.y(); // Since you've called the property `y`
or
var b = theObject.y.bind(theObject);
b();
then you can use this.x() within bar to run foo (since you've used x rather than foo for the proprty name):
function a() {
return {
x: function foo(){
console.log("I'm foo");
},
y: function bar(){
console.log("I'm bar, calling foo");
this.x();
}
};
}
var obj = a();
obj.y();
When you do that, this will refer to the object within foo as well, which is handy if you need to refer to other object properties.
If bar may be called a different way, then you probably want to define the functions separately and then combine them in an object:
function a() {
function foo(){
// ......
}
function bar(){
// .......
// .......
foo();
// .....
}
return { x: foo, y: bar };
}
Example:
function a() {
function foo(){
console.log("I'm foo");
}
function bar(){
console.log("I'm bar, about to call foo");
foo();
}
return { x: foo, y: bar };
}
var obj = a();
obj.y();
When foo is called this way, this will be undefined (in strict mode) or a reference to the global object (in loose mode), not a reference to the object; if you need a reference to the object, there are various ways to do that, such as assigning it to a variable that both foo and bar close over.
Related
I've got a piece of code with a ReferenceError here
or below:
function foo() {
function bar() {
console.log('bar');
}
var x = new Function('bar();');
x();
}
foo(); // ReferenceError: bar is not defined
Is it possible to make this happen? I mean the bar function to exist inside the new Function
Functions created with the Function constructor do not create closures to their creation contexts; they always are created in the global scope. When running them, they will only be able to access their own local variables and global ones, not the ones from the scope in which the Function constructor was called.
— MDN
So no, it isn't while using that approach.
Don't use the function constructor. It is inefficient, and converting strings to code is fraught with problems.
function foo() {
function bar() {
alert('bar');
}
function x() {
bar();
}
x();
}
foo();
One possible approach is to use eval instead of new Function:
function foo() {
function bar() {
console.log('bar');
}
eval('x = function() { bar(); }');
x();
}
foo(); // works fine.
I'm trying to do something like this:
function foo() { alert(this.bar); }
foo.bar = "Hello world";
foo();
That doesn't work because I believe this refers to the global object (window) rather than foo. How do I make it work?
this refer to the object used to call the method. By default, it will be the window object.
In your case, you should get the parameter in the function object directly using the named function as it is available in the scope.
function foo() { alert(foo.bar); }
foo.bar = "Hello world";
foo();
You shouldn't use this as doing something like this:
foo.call({})
this will be equal to the empty object.
Possibly try using prototype:
function foo() {
alert(this.bar);
}
foo.prototype.bar = "Hello world";
new foo(); //new object
Recommended option:
function foo(bar) { //constructor argument
this.bar = bar;
}
foo.prototype.getBar = function() {
alert(this.bar);
};
new foo("Hello world").getBar();
I'd choose to do it this way, as it makes use of the prototype chain.
function Foo() { return (this===window) ? new Foo() : this; }
Foo.prototype.hi = function() { alert(this.bar) };
Foo.prototype.bar = "Hi!";
var tmp = new Foo();
tmp.hi();
Trying to understand the scope chain and execution context stack articles from David Shariff's Blog, I've tried to understand closures here
function foo() {
var a = 'private variable';
return function bar() {
alert(a);
}
}
var callAlert = foo();
callAlert(); // private variable
I just wanted to test if inner function has the variable object just from its parent or from the whole scope chain, so I added a nested function repeating the example:
function foo() {
var a = 'private variable';
return function bar() {
return function foobar() {
console.log(a);
};
};
}
var callAlert = foo();
callAlert(); //
And that is not giving any result. It seems the interpreter is not even entering the foobar() function. And the syntax is the same than its parent.
But it works if I divide the function declaration and execution.
function foo() {
var a = 'private variable';
return function bar() {
function ra() {
console.log(a);
};
return ra();
};
}
var callAlert = foo();
callAlert(); // private variable
And really I'm trying to guess why; where's the difference from bar() and foobar() functions.
PS - I'm testing on JSFiddle
function foo() {
var a = 'private variable';
return function bar() {
return function foobar() {
console.log(a);
};
};
}
Here you're returning a function that returns a function, so you need to call that new, doubly nested function
var callAlert = foo()();
DEMO
Or any variation on that theme
var getBar = foo();
var getFooBar = getBar();
getFooBar(); //private variable.
Updated demo
The second example works fine because you're still returning one function—a function that simple calls another function.
return function bar() {
function ra() {
console.log(a);
};
return ra();
};
Is there a way to do:
foo() // return string "foo"
foo.bar() // return string "bar"
?
I tried to experiment with functions and objects. But nothing happened.
function foo() {
return "foo";
}
foo.bar = function() {
return "bar";
};
Or, if you prefer:
var foo = function() {
return "foo";
};
foo.bar = function() {
return "bar";
}
JS functions are a type of object so you can assign properties/methods to them the same as for any other object.
You can call either a function or a class named foo but you can't have both as far as I know. Correct me if I'm wrong. Why would you want a class and a function with the same way anyway? I'm assuming that that's what you want as there is little info in your post
To define a function use this
function foo() {
console.log("foo");
}
And call it like in your example.
To define a class do it like this (here are some other ways to do it).
var foo = {
bar: function() {
console.log("bar");
}
}
And again, call it like you did in your example.
I have function-constructor. I want to control what function (object) can call it. Here'e the example:
function Bar() {
// foo can be created only here, when Bar is instantiated
var foo = new Foo();
}
function Foo() {
// I'd like to have something like this here:
if (caller != Bar) {
alert("Not allowed, the caller is not Bar");
return;
}
}
var bar = new Bar(); // this is correct, Foo can be created inside Bar
var foo = new Foo(); // prints "Not allowed, the caller is not Bar" and exits
Is it possible to implement in JS? Are there some functions for such kind of control?
What will be created from Foo if the creation will be aborted this way?
You can't reliably identify the caller in a constructor across browsers, particularly in the new strict mode.
Instead, you can define Foo() inside of Bar() or define them both inside of the same self executing function so that Foo() is not known outside the scope of Bar() and can thus only be created there.
Some examples:
// Bar() is only known within a single scope
var Foo;
(function(){
Foo = function() {
}
function Bar() {
}
})();
// Bar() is only known inside of Foo()'s constructor
function Foo() {
function Bar() {
}
}
You may find this article instructional which discusses various ways of making instance data truly private: http://www.crockford.com/javascript/private.html. It's not exactly the same as what you're asking here, but uses some of the same techniques (hiding private data in a closure).
You can try something like: (don't think this is cross browser solution however)
var caller = Foo.caller.name;
if (caller != "Bar") {
}
See this answer for more details.
Another option is to have a global variable that is false by default and you assign to true in the functions you want to allow and to a check in that function.
If you want to restrict the creation of the Foo object within Bar, then you can define the function with in Bar.
e.g:
function Bar() {
var Foo = function Foo() {
// I'd like to have something like this here:
if (caller != Bar) {
alert("Not allowed, the caller is not Bar");
return;
}
}
var foo = new Foo();
.
.
.
.
}
Now Foo is not visible outside the Bar scope.
You could simply not expose Foo:
(function() {
function Bar() {
var foo = new Foo();
}
function Foo() {
}
window.Bar = Bar; //Expose bar to global scope
})();
A function, when called as constructor returns the created object unless you explicitly return a non-primitive value. So having return; would still return the created object.