I have tried to figure this out or search for it on google, i can only find how to create objects, not exactly how functions work. If someone could explain to me how encapsulation works.
function myObject() {
this.variable1 = "tst";
this.function1 = function() {
//Now this function works. A 'this' function to a private function is ok
_PrivateFunction1();
//Here is error one, I cannot seem to call methods within the object
//from.
this.function2();
}
this.function2 = function() {
alert("look! function2!");
}
function _PrivateFunction1() {
//This does work though. I am confused.
_PrivateFunction2();
}
function _PrivateFunction2() {
alert("look! PrivateFunction1");
//this does not work.
alert(this.variable1);
}
}
I think I can explain this better if we go in reverse order. First, we define some functions:
function _PrivateFunction1() {
//This does work though. I am confused.
_PrivateFunction2();
}
function _PrivateFunction2() {
alert("look! PrivateFunction1");
//this does not work.
alert(this.variable1);
}
This is pretty normal stuff. The only thing that's weird is that they appear inside another function, but that's perfectly fine. JavaScript has function scope, which means that all variables defined inside a function are defined in a new scope. They do not trample on the global namespace. And functions are first-class objects in JavaScript, which means they can be used just like other data types. They can be nested, passed to functions, returned from functions, etc.
Then we run into some trouble:
function _PrivateFunction2() {
alert("look! PrivateFunction1");
//this does not work.
alert(this.variable1);
}
}
Functions in JavaScript are always executed in some context which is referred to by the this keyword. When you call a function directly (i.e. like this: functionName()) the context in which that function executes is the global window object. So, inside _PrivateFunction2, this.variable1 is equivalent to window.variable1 which is probably not what you meant.
You probably wanted to refer to the current instance of myobject which is what this refers to outside of _PrivateFunction2. You can preserve access to this in an inner scope by storing a reference to it in another variable:
var _this = this;
function _PrivateFunction2() {
alert("look! PrivateFunction1");
//this does not work.
alert(_this.variable1);
}
There's something subtle here you should notice. _PrivateFunction2 has access to the variables defined in its lexical scope, which is why it can access _this. This will be important later.
Next up:
function _PrivateFunction1() {
//This does work though. I am confused.
_PrivateFunction2();
}
This should be the most normal-looking section to you, I would think. There's nothing strange going on here. Just one regular function calling another one. Don't be confused by the fact that these are nested inside myObject. That changes the scope they're in, but not much else.
Next we define some instance variables and methods:
this.variable1 = "tst";
this.function1 = function() {
//Now this function works. A 'this' function to a private function is ok
_PrivateFunction1();
//Here is error one, I cannot seem to call methods within the object
//from.
this.function2();
}
this.function2 = function() {
alert("look! function2!");
}
Here this really does refer to myObject, assuming -- and it's an important assumption -- that myObject was called with the new operator, like this:
var obj = new myObject();
If it had been called like this:
var obj = myObject();
Then this would refer to the window object, just like it did for the functions we saw earlier. The key takeaway is that the value of this is not fixed. It's determined by the way in which the function is called. There are even ways to set it to an arbitrary object explicitly.
The value of this inside this.function1 will also be the current instance of myObject, because it will most likely be used like this:
var obj = new myObject();
obj.function1();
Writing object.method() sets this to object inside method.
So how is this.function1 able to call _PrivateFunction1()? Just as we saw earlier when saving the value of this for use inside a nested function, _PrivateFunction1() is just another object defined in this.function1's lexical scope, so it is available for its use, just as _this was earlier.
And it's because of closure that these private variables are still alive long after myObject has returned.
Footnote: Because failing to use new when instantiating objects breaks things so spectacularly without warning, it's considered good practice to capitalize the names of functions you intend to be used as a constructor. So myObject should really be MyObject.
You have to save a copy of the actual object like here note the var that = this
Tested in chrome and FF
for encapsulation I would prefer module pattern like
var someMethod = function(){
var i,
length,
// public method
public = function(num1, num2){
return num1+num2;
},
//private method
_private = function(){};
//exposing the public method
return{
public:public
}
};
var callPublic = someMethod();
callPublic.public(20, 30);// call the public method and return 50
now , if you try to call that private method like
callPublic._private();//it will return not a function since its not been exposed
There are lot of other pattern to encapsulate your methods but module pattern is most common. Hope ot will help you how to encapsulate data in javascript.
Related
I'm new to node.js and not yet fully into scoping of anonymous functions. I declared a object with several methods. Inside my method I first get a mysql connection from mysql pool and than do a query on the connection. Now I want to call a method of my object. After reading into scoping and binding i came to the following code as result.
I was wondering whether the following is bad practise or good and if there are any better patterns to achieve this?
function myclass() {}
myclass.prototype.dosomthing = function () {}
myclass.prototype.init = function() {
pool.getConnection(function(err,connection)){
this.dosomthing();
connection.query("sql_statement", function(err,rows){
this.dosomething();
}.bind(this));
}.bind(this));
}
Thx, I really appreciate your expertise!
What you have is fine, although it does involve creating unnecessary function objects (bind creates and returns a new function).
As an alternative, just use a variable you close over:
function myclass() {}
myclass.prototype.dosomthing = function () {}
myclass.prototype.init = function() {
var self = this; // Remember `this`
pool.getConnection(function(err,connection)){
self.dosomthing(); // Use it
connection.query("sql_statement", function(err,rows){
self.dosomething(); // Use it
});
});
};
I've used self above, but generally I pick a name based on what the object actually is. So for instance, if myclass were Foo, I'd probably use the name thisFoo or similar.
Side note: The overwhelming convention in JavaScript is that functions meant to be used as constructors are named with an initial uppercase character. So MyClass rather than myclass.
I know I can define properties on functions, which can then be accessed from within the function. Right now, the only syntax I can work out involves two statements. Is there a more concise way to express the following:
function myFunc() {
// do some work
}
myFunc.myProp = 0;
I'm not looking for a solution that is fewer characters -- this isn't code golf. I'm asking something more along the lines of "are there different patterns of function declaration that have this other desirable merit?" This is almost about ways to use closures (because I suspect the answer lies there).
Thanks!
Especially if you want to access properties of the function from inside the function itself, you're better off doing this:
var theFunction = function() {
function theRealFunction() {
// the code
if (theRealFunction.something == "not whatever")
// do something
// more code
}
theRealFunction.something = "whatever";
return theRealFunction;
}();
What that does is wrap your function declaration up in an anonymous function. The problem with accessing function properties via the function name is that it must do that by finding the function's name in the surrounding scope. That's kind-of icky, but at least this way it involves a scope that's essentially private. It'll work whether or not the resulting function (returned as the return value of the anonymous function) is assigned to a different variable, passed to a function as a handler function, etc.
This really, really all depends. If you're looking for private variables, then you can easily return a function from the function -- an inner-function will contain access to its parent's scope.
var outer_function = (function () {
var private_var = "secret",
public_var = "public",
inner_function = function () {
return private_var;
};
inner_function.public_var = public_var;
return inner_function;
}());
outer_function now equals inner_function, with the benefit of having access to the enclosed data. Any properties attached to the inner (in the way you did) will now be accessible as public properties of outer.
To this end, you can return, say, a constructor for a class, with public-static properties, with the enclosed vars acting as private-static properties, shared between every instance of the "class" you build.
Not exactly the answer to your question, but if you ever want to read up some different design patterns that can be used when defining a javascript function, this is one of the best articles I've ever read on the topic:
http://www.klauskomenda.com/code/javascript-programming-patterns/
Can someone explain in detail what this snippet of js does?
(function (window) {
var test = window['test'] = {};
test.utils = new(function(){ ... })();
})(window);
I understand that the function is not globally scoped. I understand that it is creating a variable called test that points to a property in the window object that is an empty object. I also understand that utils is a property of test.
I don't understand what the purpose of the last part is (window); or why the utils function is being designated as new.
Please explain.
It creates a function and calls it immediately, passing in window. The function receives an argument called window and then creates an empty object on it which is available both as a property on window called test and as a local variable called test. Then it creates an object by calling a function via new and assigns that object to test.utils.
I don't understand what the purpose of the last part is (window);...
It doesn't really serve any purpose in the code you've quoted, because the symbol passed into the main (outer) function, window, is the same as the name of the argument receiving it. If their names were different, then it would serve a purpose, e.g.:
(function(wnd) {
})(window);
That would make window available within the function as wnd.
or why the utils function is being designated as new.
utils won't be a function (at least, not unless the code you've replaced with ... is doing something really strange), it will be an object created by calling that function.
The whole thing could be rewritten more clearly:
(function(window) {
var test;
test = {};
window['test'] = test;
test.utils = new NiftyThing();
function NiftyThing() {
}
})(window);
That still does the window thing for no reason, but hopefully it makes it clear what the new(function() { ... })(); bit was doing.
First of all, this is a self-invoked function.
It's invoked itself giving the window object as function input argument in order to ensure that, inside the whole function, window will have the expected meaning.
test.utils = new(function(){ ... })(); <--- This is an object constructor.
When the function is called using the new operator, it turns into an object constructor.
For example:
var conztructor = function() {
this.name = "Matias";
};
var obj = new conztructor();
alert(obj.name); // <--- This will alert "Matias"!
The purpose of (window); is creating a new variable and reference holding the JavaScript Window object instance, avoiding that other libraries may reuse the window (or any other) identifier and your own library may break because of this situation.
This is nice in order to avoid altering global scope identifiers that may be used by other libraries.
UPDATE
In response to some comments, run this code:
http://jsfiddle.net/wChh6/5/
What is happening here is that a new anonymous function is being declared. The last part with (window) makes a call to that function, passing window as a parameter.
Inside, the call to test.utils = new(function(){ ... })(); creates a new object (with contents defined by the function passed to new) and assigns it to test.utils.
When you define a function with last parentetheses, the function is executed itself after loading with the parameter given, in your case window
(function (window) {
var test = window['test'] = {};
test.utils = new(function(){ ... })();
})(window);
JS function definition : meaning of the last parentheses
The below doesnt work and im struggling to work out why....
function CommentHandler() {
var Text;
}
var myCommentHandler = new CommentHandler();
myCommentHandler.prototype.SayHello = function () {
document.write('Hello World');
}
I get the error : 'myCommentHandler.prototype is undefined'
I just cant see why? I have declared a variable called myCommentHandler and copied in the object CommentHandler then Im trying to access the protoype of it and assign a function but I cant...Anyone know why?
The prototype belongs to the class, not the instance:
CommentHandler.prototype.MyFunction = ...
However you can also access the prototype via the instance's constructor property:
myObj.constructor.prototype.MyFunction = ...
This will of course add that function to every instance of your CommentHandler.
If instead you only wanted to add that function to that one instance, you'd do:
myObj.MyFunction = ...
Note that in none of these variants would it be possible for MyFunction to access your private variable Text.
This is the compromise forced by the prototype inheritance model - variables and methods must be public (e.g. this.Text) if they're to be accessed from outside, and in this case functions declared in the prototype are effectively "outside".
The alternative (using closure-scoped variables and methods) seems more natural to OO programmers, but makes inheritance much harder.
I think what you actually want here is this:
CommentHandler.prototype.SayHello = function () {
document.write('Hello World');
};
You have to use
CommentHandler.prototype.SayHello = function(){....}
You can find more about the prototype object in the following references
http://www.javascriptkit.com/javatutors/proto.shtmlhttps://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Object/prototypehttp://msdn.microsoft.com/en-us/magazine/cc163419.aspx
You need to prototype the class function rather than the instance. Also if you want the Text variable to be accessible outside the constructor, in the other method functions, then you need to add the this keyword.
function CommentHandler() {
this.Text = 'Hello World';
}
CommentHandler.prototype.SayHello = function () {
document.write(this.Text);
}
var myCommentHandler = new CommentHandler();
myCommentHandler.SayHello();
As a side point you could create the SayHello function inside the constructor, but this would add increased overhead to the creation of each instance of CommentHandler. Thus the prototyping method that you are using is a better option.
myCommentHandler does not have a prototype, because it is an instance. CommentHandler does have a prototype that can be modified. I am guessing you want to edit the object after initializing, and can do so like this:
myCommentHandler.SayHello = function() {
document.write('Hello World');
}
Here is a good explanation of prototypes and object oriented programming in javascript with many examples: http://mckoss.com/jscript/object.htm
Using instance methods as callbacks for event handlers changes the scope of this from "My instance" to "Whatever just called the callback". So my code looks like this
function MyObject() {
this.doSomething = function() {
...
}
var self = this
$('#foobar').bind('click', function(){
self.doSomethng()
// this.doSomething() would not work here
})
}
It works, but is that the best way to do it? It looks strange to me.
This question is not specific to jQuery, but specific to JavaScript in general. The core problem is how to "channel" a variable in embedded functions. This is the example:
var abc = 1; // we want to use this variable in embedded functions
function xyz(){
console.log(abc); // it is available here!
function qwe(){
console.log(abc); // it is available here too!
}
...
};
This technique relies on using a closure. But it doesn't work with this because this is a pseudo variable that may change from scope to scope dynamically:
// we want to use "this" variable in embedded functions
function xyz(){
// "this" is different here!
console.log(this); // not what we wanted!
function qwe(){
// "this" is different here too!
console.log(this); // not what we wanted!
}
...
};
What can we do? Assign it to some variable and use it through the alias:
var abc = this; // we want to use this variable in embedded functions
function xyz(){
// "this" is different here! --- but we don't care!
console.log(abc); // now it is the right object!
function qwe(){
// "this" is different here too! --- but we don't care!
console.log(abc); // it is the right object here too!
}
...
};
this is not unique in this respect: arguments is the other pseudo variable that should be treated the same way — by aliasing.
Yeah, this appears to be a common standard. Some coders use self, others use me. It's used as a reference back to the "real" object as opposed to the event.
It's something that took me a little while to really get, it does look odd at first.
I usually do this right at the top of my object (excuse my demo code - it's more conceptual than anything else and isn't a lesson on excellent coding technique):
function MyObject(){
var me = this;
//Events
Click = onClick; //Allows user to override onClick event with their own
//Event Handlers
onClick = function(args){
me.MyProperty = args; //Reference me, referencing this refers to onClick
...
//Do other stuff
}
}
If you are doing ES2015 or doing type script and ES5 then you can use arrow functions in your code and you don't face that error and this refers to your desired scope in your instance.
this.name = 'test'
myObject.doSomething(data => {
console.log(this.name) // this should print out 'test'
});
As an explanation: In ES2015 arrow functions capture this from their defining scope. Normal function definitions don't do that.
var functionX = function() {
var self = this;
var functionY = function(y) {
// If we call "this" in here, we get a reference to functionY,
// but if we call "self" (defined earlier), we get a reference to function X.
}
}
edit: in spite of, nested functions within an object takes on the global window object rather than the surrounding object.
One solution to this is to bind all your callback to your object with javascript's bind method.
You can do this with a named method,
function MyNamedMethod() {
// You can now call methods on "this" here
}
doCallBack(MyNamedMethod.bind(this));
Or with an anonymous callback
doCallBack(function () {
// You can now call methods on "this" here
}.bind(this));
Doing these instead of resorting to var self = this shows you understand how the binding of this behaves in javascript and doesn't rely on a closure reference.
Also, the fat arrow operator in ES6 basically is the same a calling .bind(this) on an anonymous function:
doCallback( () => {
// You can reference "this" here now
});
I haven't used jQuery, but in a library like Prototype you can bind functions to a specific scope. So with that in mind your code would look like this:
$('#foobar').ready('click', this.doSomething.bind(this));
The bind method returns a new function that calls the original method with the scope you have specified.
Just adding to this that in ES6 because of arrow functions you shouldn't need to do this because they capture the this value.
I think it actually depends on what are you going to do inside your doSomething function. If you are going to access MyObject properties using this keyword then you have to use that. But I think that the following code fragment will also work if you are not doing any special things using object(MyObject) properties.
function doSomething(){
.........
}
$("#foobar").ready('click', function(){
});