Call a function of object literal from itself - javascript

I tried execute this code:
var system = new Object();
(function($) {
$.init = function() {
var o = {
message: function(arg) {
return arg.val;
},
alert: this.message({
val: "Hello, world."
})
};
return o.alert;
};
})(system);
alert(system.init());
but, when I execute it I get error message which tells me that this.message is not a function. Obviously, this not refers to object o itself, and I want to know why.
I found few solutions on stackoverflow where this is always inside function body, but why this can not be outside? Thanks.

Change your code to:
var system = new Object();
(function($) {
$.init = function() {
var o = {
message: function(arg) {
return arg.val;
}
};
o.alert = o.message({
val: "Hello, world."
});
return o.alert;
};
})(system);
system.init()
Yields:
"Hello, world."
In your code this would refer to window in that context. If you want to create an object and refer to it as this - use constructor function, i.e.:
var o = new function(){
...
<here: this == o>
...
}

You can use an anonymous constructor function instead of object literal syntax if you want to reference the object during instantiation.
(function($) {
$.init = function() {
// -----vvv---vvv---constructor function
var o = new function() {
this.message = function(arg) {
return arg.val;
},
this.alert = this.message({
val: "Hello, world."
})
};
return o.alert;
};
})(system);
Because the value of this is only defined within a function when the function is invoked, object literal syntax never changes its value.
So instead we create a function, and invoke it using new so that the value of this in the function is a reference to the new object we're building.
And of course it doesn't need to be anonymous, but if you're only going to use it once, there's no need for a name.

Related

JS closure to return object instance as interface

I have the following code.
function Test() {
this.funct_1 = function() {
alert('funct_1');
}
this.funct_2 = function() {
alert('funct_2');
}
return this;}
function getTestObj() {
var testObj;
if (!testObj) {
testObj = new Test();
}
return function() {
return testObj;
}}
What I'm trying to accomplish is the following. I want to have a class Test which is not singleton. Then in some other places in my application I need to have a function which could return the same instance per script execution. I figured that I could use closure for that getTestObj.
However, when I try to use it
getTestObj().funct_1();
I'm getting the following error, saying the funct_1() is not found.
Cannot find function funct_1 in object function () {...}.
Clearly, I'm making some kind of mistake here, but I'm not able to find any solution over the net which could help me. Would appreciate any comments.
NOTE: I'm forced to use ECMA5
testObj is wrapped inside a function
So, either call it
getTestObj()().funct_1(); //notice two ()()
Save the value of getTestObj() in a variable
var singleTon = getTestObj();
var testObj = singleTon();
testObj.funct_1();
Or, simply return testObj (in case singleTon isn't required)
function getTestObj()
{
var testObj;
if (!testObj) {
testObj = new Test();
}
return testObj;
}
And invoke it as
getTestObj().funct_1(); //notice single ()
getTestObj() is returning a function i.e. :
function() {
return testObj;
}
So you have to call it again getTestObj()(), this will return the Test's object and now you can access it's properties.
getTestObj()().funct_1();
OR
You can change your getTestObj function as :
function getTestObj() {
var testObj;
if (!testObj) {
testObj = new Test();
}
return (function() {
return testObj;
}());
}

UnCaught TypeError - Nested objects in Javascript? Why is this not allowed? Object literal notation works

Playing around with some JS tests and I'm trying to instantiate some nested objects in my v namespace. As you'll see below, ClassA and ClassB work as expected. When I try and nest some objects under another property (myCustomProperty) I start running into issues! Could someone explain?
Below is the original code:
var v = (v) ? v : {};
v.someClassA = (function() {
this.hello = function() {
console.log("Class A Hello!");
}
});
v.someClassB = (function() {
this.hello = function() {
console.log("Class B Hello!");
}
});
// this all works!
var myClassA = new v.someClassA();
var myClassB = new v.someClassB();
v.myCustomProperty = (function() {
function someClassC() {
this.hello = function() {
console.log('C');
}
}
function someClassD() {
this.hello = function() {
console.log('D');
}
}
return {
someClassC: someClassC,
someClassD: someClassD
}
});
// Uncaught TypeError: v.myCustomProperty.someClassC is not a function! Why?
var myClassC = new v.myCustomProperty.someClassC();
var myClassD = new v.myCustomProperty.someClassD();
myClassA.hello();
myClassB.hello();
myClassC.hello();
myClassD.hello();
If I change my declaration of v.myCustomProperty to use object literal notation, then it ALL WORKS! :
v.myCustomProperty = {
someClassC: function() {
this.hello = function() {
console.log('C');
}
},
someClassD: function() {
this.hello = function() {
console.log('D');
}
}
}
I guess my question really is how would I make this work using the notation in my original snippet? Possible? Horrible practice to do it that way?
Thanks!
v.myCustomProperty is a function that returns an object. You have to call the function first:
new (v.myCustomProperty().someClassC)();
// ^^
Otherwise, v.myCustomProperty.someClassC() tries to access the property someClassC of the function, and we all know (hopefully) that functions don't have such a property.
Or maybe you intended to execute the function immediately and assign the object to myCustomProperty?
v.myCustomProperty = (function() {
// ...
}()); // <- call function

Function calling error

Hey guys i am new to javascript app development ..i have did some javascript code but unfortunately it throws some error
The code which i have used is
var c = ( function() { this.name = function() { console.log('yay'); } }());
When i called the instance of the function c it throws error like Uncaught TypeError: undefined is not a function
Why cant i create the instance of function c ??...How can i call the function c so that i can call the inside function name().
Thanx for your help..
Seems you've misunderstood the concept of IIFE. You would need Object
var c = {
name: function() {
console.log('yay');
}
};
c.name(); // yay
But, if you need to go with function, then you would need a Constructor function, which would then be called with a new operator.
Use thisss
var c = function() {
this.name = function() {
console.log('yay');
}
};
newFunction=new c();
newFunction.name()
Since, it is closure, you can not assign to variable var c. If you follow that pattern, you always have to enclose functions/operations inside that (function() {} ).
More on closure- http://javascriptissexy.com/understand-javascript-closures-with-ease/.
To use this, you can modify the js to like this.
var c = (function() {
var name;
function setName(val) {
name = val;
}
return {
print: function() {
setName("yay");
console.log(name);
}
};
})();
console.log(c);
c.print();

Is it possible to append functions to a JS class that have access to the class's private variables?

I have an existing class I need to convert so I can append functions like my_class.prototype.my_funcs.afucntion = function(){ alert(private_var);} after the main object definition. What's the best/easiest method for converting an existing class to use this method? Currently I have a JavaScript object constructed like this:
var my_class = function (){
var private_var = '';
var private_int = 0
var private_var2 = '';
[...]
var private_func1 = function(id) {
return document.getElementById(id);
};
var private_func2 = function(id) {
alert(id);
};
return{
public_func1: function(){
},
my_funcs: {
do_this: function{
},
do_that: function(){
}
}
}
}();
Unfortunately, currently, I need to dynamically add functions and methods to this object with PHP based on user selected settings, there could be no functions added or 50. This is making adding features very complicated because to add a my_class.my_funcs.afunction(); function, I have to add a PHP call inside the JS file so it can access the private variables, and it just makes everything so messy.
I want to be able to use the prototype method so I can clean out all of the PHP calls inside the main JS file.
Try declaring your "Class" like this:
var MyClass = function () {
// Private variables and functions
var privateVar = '',
privateNum = 0,
privateVar2 = '',
privateFn = function (arg) {
return arg + privateNum;
};
// Public variables and functions
this.publicVar = '';
this.publicNum = 0;
this.publicVar2 = '';
this.publicFn = function () {
return 'foo';
};
this.publicObject = {
'property': 'value',
'fn': function () {
return 'bar';
}
};
};
You can augment this object by adding properties to its prototype (but they won't be accessible unless you create an instance of this class)
MyClass.prototype.aFunction = function (arg1, arg2) {
return arg1 + arg2 + this.publicNum;
// Has access to public members of the current instance
};
Helpful?
Edit: Make sure you create an instance of MyClass or nothing will work properly.
// Correct
var instance = new MyClass();
instance.publicFn(); //-> 'foo'
// Incorrect
MyClass.publicFn(); //-> TypeError
Okay, so the way you're constructing a class is different than what I usually do, but I was able to get the below working:
var my_class = function() {
var fn = function() {
this.do_this = function() { alert("do this"); }
this.do_that = function() { alert("do that"); }
}
return {
public_func1: function() { alert("public func1"); },
fn: fn,
my_funcs: new fn()
}
}
var instance = new my_class();
instance.fn.prototype.do_something_else = function() {
alert("doing something else");
}
instance.my_funcs.do_something_else();
As to what's happening [Edited]:
I changed your my_funcs object to a private method 'fn'
I passed a reference to it to a similar name 'fn' in the return object instance so that you can prototype it.
I made my_funcs an instance of the private member fn so that it will be able to execute all of the fn methods
Hope it helps, - Kevin
Maybe I'm missing what it is you're trying to do, but can't you just assign the prototype to the instance once you create it? So, first create your prototype object:
proto = function(){
var proto_func = function() {
return 'new proto func';
};
return {proto_func: proto_func};
}();
Then use it:
instance = new my_class();
instance.prototype = proto;
alert(instance.prototype.proto_func());

Encapsulation in javascript

I need to create simple reusable javascript object publishing several methods and parameterized constructor. After reading through several "OOP in JavaScript" guides I'm sitting here with an empty head. How on the Earth can I do this?
Here my last non-working code:
SomeClass = function(id) {
this._id = id;
}
(function() {
function intFun() {
return this._id;
}
SomeClass.prototype.extFun = function() {
return incFun();
}
})();
This is my usual approach:
MyClass = function(x, y, z) {
// This is the constructor. When you use it with "new MyClass(),"
// then "this" refers to the new object being constructed. So you can
// assign member variables to it.
this.x = x;
...
};
MyClass.prototype = {
doSomething: function() {
// Here we can use the member variable that
// we created in the constructor.
return this.x;
},
somethingElse: function(a) {
}
};
var myObj = new MyClass(1,2,3);
alert(myObj.doSomething()); // this will return the object's "x" member
alert(myObj.x); // this will do the same, by accessing the member directly
Normally the "this" keyword, when used in one of the object's methods, will refer to the object itself. When you use it in the constructor, it will refer to the new object that's being created. So in the above example, both alert statements will display "1".
An exception to this rule is when you pass one of your member functions somewhere else, and then call it. For example,
myDiv.onclick = myObj.doSomething;
In this case, JavaScript ignores the fact that "doSomething" belongs to "myObj". As a result, the "this" inside doSomething will point to another object, so the method won't work as expected. To get around this, you need to specify the object to which "this" should refer. You can do so with JavaScript's "call" function:
myDiv.onclick = function() {
myObj.doSomething.call(myObj);
}
It's weird, but you'll get used to it eventually. The bottom line is that, when passing around methods, you also need to pass around the object that they should be called on.
I usually don't worry too much about hiding the internals, although I do prefix them with underscores to mark them as not intended to be used outside the "class". Normally what I will do is:
var MyClass = function() {};
MyClass.prototype = {
_someVar : null,
_otherVar : null,
initialize: function( optionHash ) {
_someVar = optionsHash["varValue"];
_otherVar = optionsHash["otherValue"];
},
method: function( arg ) {
return _someVar + arg;
},
};
And use it as so...
var myClass = new MyClass( { varValue: -1, otherValue: 10 } );
var foo = myClass.method(6);
All vars are private:
SomeClass = function (id) {
var THIS = this; // unambiguous reference
THIS._id = id;
var intFun = function () { // private
return THIS._id;
}
this.extFun = function () { // public
return intFun();
}
}
Use THIS within private methods since this won't equal what you might expect.
From http://learn.jquery.com/code-organization/concepts/#the-module-pattern:
// The module pattern
var feature = (function() {
// private variables and functions
var privateThing = "secret";
var publicThing = "not secret";
var changePrivateThing = function() {
privateThing = "super secret";
};
var sayPrivateThing = function() {
console.log( privateThing );
changePrivateThing();
};
// public API
return {
publicThing: publicThing,
sayPrivateThing: sayPrivateThing
};
})();
feature.publicThing; // "not secret"
// logs "secret" and changes the value of privateThing
feature.sayPrivateThing();
So using returning an object that aliases its "methods" could be another way to do it.
I've read from http://www.amazon.com/Programming-Oracle-Press-Poornachandra-Sarang-ebook/dp/B0079GI6CW that it is always good practice to use getters and setters rather that accessing the variable directly from outside the object, so that would eliminate the need of returning variables by reference.
BTW you could just use this.variable to reference/declare a public variable and var variable to declare a private variable.
I know this is a late answer, but I hope it helps anyone who reads it in the future.

Categories

Resources