How come this doesn't alert "http://127.0.0.1/sendRequest"? (Available at http://jsfiddle.net/Gq8Wd/52/)
var foo = {
sendRequest: function() {
alert(bar.getUrl());
}
};
var bar = {
getUrl: function() {
return 'http://127.0.0.1/' + arguments.callee.caller.name;
}
};
foo.sendRequest();
Putting a value in an object literal, as you're doing, doesn't affect the value at all.
var foo = {
sendRequest: ...
The function value is only affected by the function expression, which doesn't contain a name.
... function() {
alert(bar.getUrl());
}
You need to include the name you want in the function expression itself [fiddle].
var foo = {
sendRequest: function sendRequest() {
If you do this:
var foo = {
sendRequest: function() {
alert(bar.getUrl());
}
};
var bar = {
getUrl: function() {
return arguments.callee;
}
};
foo.sendRequest();
You will notice that the function doesn't have name which is true:
function() {
This is anonymous function.
You can name you method : sendRequest: function myMethodName() {
Although the function is stored under the object property foo.sendRequest, and thus can be invoked via foo.sendRequest(), that function itself doesn't actually have a name. That's why arguments.callee.caller.name is empty.
Because the function that is calling the function being called is an anonymous function (and hence, has no name).
Try:
function sendRequest() {
alert(bar.getUrl());
}
var foo = {
sendRequest: sendRequest
};
var bar = {
getUrl: function() {
return 'http://127.0.0.1/' + arguments.callee.caller.name;
}
};
foo.sendRequest();
Related
my problem seems to be that my object function is not visible if i call it from within an object of functions. Example Code:
function foo()
{
this.bar = function()
{
alert("hit me!");
}
this.sna = {
fu: function ()
{
this.bar();
}
};
}
this seems to refer to sna instead of foo. How do i adress foo? this.parent does not work.
Use a variable to refer to this(Foo). See this - JavaScript | MDN
function Foo() {
this.bar = function() {
console.log("hit me!");
};
var that = this;
this.sna = {
fu: function() {
that.bar();
}
};
}
var foo = new Foo();
foo.bar();
foo.sna.fu();
One option is to add a reference to this:
function foo() {
var _t = this;
this.bar = function() { };
this.child = {
this.foo = function() {
_t.bar():
};
};
}
I've an object looks like this:
var obj ={
property : '',
myfunction1 : function(parameter){
//do stuff here
}
}
I need to set some private properties and functions, which can not be accessed/seen from outside of the object. It is not working with
var property:, or var myFunction1
Next question is, if I call a function within or outside the object, I always have to do this with obj.myfunction(). I would like to asign "this" to a variable. Like self : this. and call inside the object my functions and variables with self.property and self.myfunction.
How? :)
There are many ways to do this. In short: If dou define a function inside another function, your inner function will be private, as long as you will not provide any reference to if.
(function obj(){
var privateMethod = function() {};
var publicMethod = function() {
privateMethod();
...
};
return {
pubMethod: publicMethod
}
}());
var obj = (function() {
var privateProperty;
var privateFunction = function(value) {
if (value === void 0) {
return privateProperty;
} else {
privateProperty = value;
}
};
var publicMethod = function(value) {
return privateFunction(value);
}
return {
getPrivateProperty: function() {
return privateFunction();
},
setPrivateProperty: function(value) {
privateFunction(value);
}
}
})();
obj.setPrivateProperty(3);
console.log(obj.getPrivateProperty());
// => 3
console.log(obj.privateProperty);
// => undefined
obj.privateFunction();
// => TypeError: undefined is not a function
Use closures. JavaScript has function scope, so you have to use a function.
var obj = function () {
var privateVariable = "test";
function privateFunction() {
return privateVariable;
}
return {
publicFunction: function() { return privateFunction(); }
};
}();
this is my code:
window.myApp= window.myApp|| {};
myApp.jira = (function () {
var getId = function () {
return ...;
}
var init = function() {
var id = myApp.jira.getId();
}
})();
$(document).ready(function () {
myApp.jira.init(); // here jira is null and getting undefined
});
when the page is loaded it says jira is undefined.
Try this:
window.myApp= window.myApp|| {};
// Function here is being immediately invoked. No "return" statement
// in your code is equivalent to "return undefined;".
myApp.jira = (function () {
var getId = function () {
return ...;
}
var init = function() {
var id = myApp.jira.getId();
// Bonus note: you can simplify this:
// var id = getId();
}
// If we return an object with functions we want
// to expose (to be public), it'll work,
return {
init: init,
getId: getId
};
})(); // <-- here you'll invoking this function, so you need return.
$(document).ready(function () {
// Without 'return' above, myApp.jira evaluated to undefined.
myApp.jira.init();
});
Working DEMO
Or you can use object literal pattern instead:
var myApp = {};
myApp.jira = {
getId: function () {
return ...;
},
init: function() {
var id = this.getId();
}
};
I spent the better part of the day reading about the module pattern and its 'this' scope. Eventually I found a work-around for my problem, although with a feeling there's a better way of doing things.
The actual code is >200 lines, but I've boiled it down to the following:
objA has a method (publicA) that objB wants invoke by callback. The detail that complicates things is that publicA needs help from publicA_helper to do its job. (http://jsfiddle.net/qwNb6/2/)
var objA = function () {
var privateA = "found";
return {
publicA: function () {
console.log("privateA is " + this.publicA_helper());
},
publicA_helper: function () {
return privateA;
}
};
}();
var objB = function () {
return {
callback: function (callback) {
callback();
}
}
}();
objA.publicA(); // privateA is found
objB.callback(objA.publicA); // TypeError: Object [object global]
Fair enough – I've grasped that the caller's context tends to influence the value of 'this'. So I add measures to retain 'this' inside objA, of which none seems to work. I've tried the
var objA = (){}.call({}) thingy, setting var self = this; (calling self.publicA_helper() accordingly). No luck.
Eventually, I added a private variable var self;, along with a public method:
init: function() {self = this;},
...and by making sure I call objA.init(); before passing objA.publicA to objB.callback, things actually work.
I cannot stress the immensity of the feeling that there's a better way of doing this. What am I missing?
The generalized solution is extremely simple.
Write all the module's methods as private, then expose those that need to be public.
I write all my modules this way :
var objA = function () {
var privateA = "found";
var A = function () {
console.log("privateA is " + A_helper());
},
var A_helper = function () {
return privateA;
}
return {
publicA: A
//A_helper need not be exposed
};
}();
Thus, all methods are in the same scope, each one having direct access to all other methods in the same module, and the ambiguous this prefix is avoided.
objB.callback(objA.publicA); will now work as expected.
See fiddle
I've tried the var objA = (){}.call({}) thingy,
How? You want to use call on the callback that you want to invoke with a custom this, not on your module closure. It should be
var objB = {
callback: function (callback, context) {
callback.call(context);
}
};
objB.callback(objA.publicA, objA);
I've tried setting var self = this;
The self variable is supposed to be in a closure and point to the object on the methods are stored. That is only this when your module IEFE would be invoked on your module - it's not. Or if it was a constructor - it's not. You could change that with call as above:
var objA = function () {
var privateA = "found",
self = this;
this.publicA = function () {
console.log("privateA is " + self.publicA_helper());
};
this.publicA_helper = function () {
return privateA;
};
return this;
}.call({});
But that's ugly. In your case, the self variable simply needs to point to the object literal which you're returning as your module:
var objA = function () {
var privateA = "found",
self;
return self = {
publicA: function () {
console.log("privateA is " + self.publicA_helper());
},
publicA_helper: function () {
return privateA;
}
};
}();
Btw, since you're creating a singleton you don't need an explicit self, you could just reference the variable that contains your module (as long as that doesn't change):
var objA = function () {
var privateA = "found";
return {
publicA: function () {
console.log("privateA is " + objA.publicA_helper());
},
publicA_helper: function () {
return privateA;
}
};
}();
Another method would be to simply make all functions private and then expose some of them - by referencing them local-scoped you will have no troubles.
var objA = function () {
var privateA = "found";
function publicA() {
console.log("privateA is " + helper());
}
function helper() {
return privateA;
}
return self = {
publicA: publicA,
publicA_helper: helper // remove that line if you don't need to expose it
};
}();
The reason is that the context is getting changed when you are invoking the callback. Not a generalized solution, but shows that the code works by specifying the context while invoking callback.
var objA = function () {
var privateA = "found";
return {
publicA: function () {
console.log("privateA is " + this.publicA_helper());
},
publicA_helper: function () {
return privateA;
}
};
}();
var objB = function () {
return {
callback: function (callback) {
callback.call(objA);
}
}
}();
objA.publicA(); // privateA is found
objB.callback(objA.publicA); // privateA is found
I've got an enclosed function in JavaScript like so:
var myFunction = function (options) {
function blah() {
var blahString = options.blahString;
//more blah
}
function blah2() {
//blah2
}
return {
blah : function { return blah(); },
blah2 : function { return blah2(); }
}
};
When I'm in my HTML, I'm trying to call myFunction.blah() and it's telling me the object has no method 'blah'.
How do I access the returned functions in the global scope?
Thanks!
This just explains why it doesn't work and how to make it work. For learning things this would be enough. Actually you should explain what you are trying to achieve so that others can guide you in the right direction.
// A scope of a function is activated ONLY when it is invoked
// Let us define a function
var myFunction = function (options) {
function blah() {
alert("I am blah");
}
function blah2() {
//blah2
}
alert("I am active now and I am returning an object");
return {
blah: function () {
return blah();
},
blah2: function () {
return blah2();
}
};
};
myFunction.blah3 = function () {
alert("I am blah3");
};
// myFunction is not invoked, but justed used as an identifier.
// It doesn't have a method blah and gives error
myFunction.blah();
// blah3 is a static method of myFunction and can be accessed direclty using myFunction
myFunction.blah3();
// myFunction is invoked, which returns an object
// it contains the function blah
myFunction().blah();
// or
var myObject = myFunction();
myObject.blah();
myObject.blah2();
var myFunction = (function (options) {
function blah() {
return options.a;
}
function blah2() {
//blah2
}
return {
blah: function() { return blah(); },
blah2: function() { return blah2(); }
};
});
alert(myFunction({a:1, b:2}).blah());
This works fine. Note blah: function <-- needs ()
see http://jsfiddle.net/kw6fJ/1