Employees that previously worked at my company used the following form of the Singleton pattern to create and obtain UI components in JavaScript:
getDetailForm: function() {
this.getDetailForm = (function() {
var form = // form creation logic
return function() {
return form;
};
}());
return this.getDetailForm();
}
Is there any reason to use that variation over the following standard way?
getDetailForm: function() {
var form;
if (!form) {
form = // form creation logic
}
return form;
}
The second code block will not remember the value of the variable form: every time the function getDetailForm is called, it represents a new closure, and a new variable form is created within that scope, which will start out as undefined -- each time.
See how the following prints "init" on each call:
var o = {
getDetailForm: function() {
var form;
if (!form) {
form = 'form'; // form creation logic
console.log('init');
}
return form;
}
}
console.log(o.getDetailForm());
console.log(o.getDetailForm());
You can make it work by declaring form in the scope of your singleton object, and for that you could use a constructor for instantiating that object, which at the same time is a closure for your form variable:
var o = new function () {
var form;
this.getDetailForm = function() {
if (!form) {
form = 'form'; // form creation logic
console.log('init');
}
return form;
}
};
console.log(o.getDetailForm());
console.log(o.getDetailForm());
See how the output now only shows "init" once.
The difference
The first version you provided has a tiny advantage: after the first call the function will have been replaced by a very basic function:
function() {
return form;
};
There is not even an if in that function. It is only a return. One could argue that therefore it is to be preferred: no performance is lost by the evaluation of an if condition on any subsequent calls of this function, which, when you call the method many times, always returns the same result, except for the first time.
However, also that can be achieved with the constructor pattern, if you would assign the value to form directly in the constructor function. Then you don't need the if in the method any more, as the initialisation already took place in the constructor.
Note that this is not exactly the same, because now the constructor is doing the heavy lifting of assigning the (maybe very time consuming) expression to form. The advantage of the first code you provided, is that this is only done when the function is called the first time, which you could consider an advantage: "don't waste time on things that might never be used".
Related
I've been trying to understand async, promises, etc. and I think I have a basic understanding of it, but I'm not getting the results I expect.
I have a HTML table, with the following:
<table data-bind="visible: viewPrincipal()">
viewPrincipal() is a function that should return true or false. This does work at the most basic level if viewPrincipal() just consists of return false or return true. But what I'm trying to do is call an async function to get the true or false value from there.
function viewPrincipal() {
console.log("Seeing if person is in principal group");
return IsCurrentUserMemberOfGroup("Principal Members", function (isCurrentUserInGroup) {
console.log(isCurrentUserInGroup);
return isCurrentUserInGroup;
});
}
The console.log works, and returns a true or false as I'd expect it to. But I want the parent viewPrincipal() function to return that true or false value, and all I get is "undefined".
I understand why this is happening - the IsCurrentUserMemberOfGroup() function is taking a bit of time to complete - but I don't know how to fix it. I know how to chain functions together, but when I'm trying to use something like knockout.js to determine if a table should be visible or not, I don't know how to chain.
Can anyone help?
The best way is to use an observable bool, and let your a-sync function change it's value. Let the magic of two-way-bindings do the rest.
Example:JSFIDDLE
function vm() {
this.viewPrincipal = ko.observable(false);
};
var vm = new vm();
ko.applyBindings(vm);
function fakeAsync() {
setTimeout(() => {
vm.viewPrincipal(true);
}, 1500);
}
fakeAsync();
I am a bit lost with your approach, but I'll try to help.
First, please double-think whether you really want to implement access control on the client side. Simply hiding an element if the user does not have sufficient rights is pretty dangerous, since the (possibly) sensitive content is still there in the DOM, it is still downloaded, all you do like this is not displaying it. Even a newbie hacker would find a way to display it though - if nothing else he can simply view it using the F12 tools.
Second, is that triple embedding of functions really necessary? You have an outermost function, that calls a function, which, in turn, calls the provided callback. You could clear this up by using computed observables:
function viewModel() {
var self = this;
var serverData = ko.observable(null);
this.viewPrincipal = ko.computed(function() {
var srvDataUnwrapped = serverData(); // access the inner value
if (!srvDataUnwrapped) {
return false;
}
// Do your decision logic here...
// return false by default
return false;
});
// Load the permission details from the server, this will set
// a variable that the viewPrincipal depends on, this will allow
// Knockout to use its dependency tracking magic and listen for changes.
(function() {
$.ajax(url, {
// other config
success: function (data) {
serverData(data);
}
);
})();
};
var vm = new viewModel();
and then in your view:
<table data-bind="visible: viewPrincipal">
note the lack if ()'s here, it is an observable, so Knockout will know how to use it.
If this seems overly complicated to add to your already existing code, then you could simply define an observable instead, and set the value of that inside your callback:
function viewModel() {
// other stuff ...
this.viewPrincipal = ko.observable(false);
// Call this wherever it fits your requirements, perhaps in an init function.
function checkPrincipal() {
IsCurrentUserMemberOfGroup("Principal Members", function (isCurrentUserInGroup) {
viewPrincipal(isCurrentUserInGroup);
});
};
};
With this approach, the markup would be the same as in the previous one, that is, without the parentheses:
<table data-bind="visible: viewPrincipal">
Doing it this way will simply set the inner value of an observable inside the callback you pass to IsCurrentUserMemberOfGroup, and because Knockout is able to track changes of observables, the value change will be reflected in the UI.
Hope that helps.
I've got 3 codes :
var control = new Control();
function Control() {
this.doSomethingElse = function() {...}
this.doSomething = function () {
control.doSomethingElse();
}
}
Or
var control = new Control();
function Control() {
var self = this;
this.doSomethingElse = function() {...}
this.doSomething = function () {
self.doSomethingElse();
}
}
Or
var control = Control();
function Control() {
var self = this;
this.doSomethingElse = function() {...}
this.doSomething = function () {
self.doSomethingElse();
}
return self;
}
Important : The function is a controller, and just declared once. Then I'm using "control" everywhere in my code...
I was wondering if the control.doSomethingElse() was slow ?
In the end, what is the right thing to do and/or the fastest code in those exemple ?
Thanks !
The first is wrong - an object should never internally use the variable name by which it is known outside. Other code could change that variable to point to something else, breaking this code.
The third is also wrong - when calling Control() without new the assignments to this.foo inside will end up getting attached to the global object (except in strict mode, where there's no implicit this on bare function calls, so the assignment to this.doSomethingElse tries to attach to undefined, causing a runtime error).
That only leaves the second as appropriate, but ultimately it's a question of correctness, not performance.
Do not define methods in constructor - that means defining them every time an instance is created. Use Control.prototype.foo = function() {} instead. Also you do not need to return this if you're using new operator - that's the whole point of new operator.
The recommended approach is this:
function MyClass(param1) {
// Here we're changing the specific instance of an object
this.property1 = param1;
}
// Prototype will be shared with all instances of the object
// any modifications to prototype WILL be shared by all instances
MyClass.prototype.printProperty1 = function() {
console.log(this.property1);
}
var instance = new MyClass("Hello world!");
instance.printProperty1(); // Prints hello world
To understand this code, you need to understand javascript's prototype-based inheritance model. When you create instance of MyClass, you get a new object that inherits any properties present in MyClass.prototype. Read more about it.
Also I wonder:
The function is a controller, and just declared once.
If you're not using this multiple times, you don't need to create something like class. You can do this instead:
var control = {doSomething:function() { ... }};
I assume you are used to Java, where everything must be a class, whether it makes sense or not. Javascript is different, you can also make single objects or functions as you need.
EDIT:
Everything is working as I expected. It was just an error calling the template method. I mistyped a () so I was trying template.method instead of template().method;
Anyway, if somebody would like to explain me if this is a valid design pattern or if I should go in a different way I will be definitively very grateful.
I read about the module pattern and I'm trying to implement it in some of my projects. The problem is that, in my opinion, I'm twisting it too much.
I'm inspired by the google apps script style where many objects returns other objects with methods and so on and they pass arguments.
something like
object.method(var).otherMethod();
What I want to achieve is a method that receives a parameter, sets an internal variable to that parameter and then returns an object with methods that uses that variable. Here is a minified version of the code that does not work:
var H_UI =(function (window) {
var selectedTemplate,
compileTemplate = function(){},
parseTemplateFields = function(){};
//template subModule. Collect: collects the template fields and returns a JSON representation.
var template = function(templateString){
if(templateString) selectedTemplate = templateString;
return {
getHtml:function(){ return compileTemplate( parseTemplateFields( selectedTemplate ) ) } ,
collect:function(){
.. operating over selectedTemplate ...
return JSON.stringify(result)}
} };
return {
template:template
};
})(window);
If I remove the line :
if(templateString) selectedTemplate = templateString;
and replace selectedTemplate with the parameter templateString in the methods of the returned object it works as expected. I know that I cant create a set() method in the returned object and use it like this
H_UI.template().set(var)
But I find it ugly. Anyway I think that I'm messing things up.
What is the best way to construct this?
If you want H_UI.template() creates a new object every time you call template() on it, your solution does not work. Because the variable selectedTemplate is created only once when the immediate function is called.
However if your intent is this your solution works fine. (variable selectedTemplate is shared for all calls to template()).
But if you want to every call to template creates a new object. Please tell me to write my idea
Is this a valid design pattern or if I should go in a different way
Yes, enabling chaining is definitely a valid design pattern.
However, if your template() method returns a new object, that object and its methods should only depend on itself (including the local variables and parameters of the template call), but not on anything else like the parent object that template was called on.
So either remove that "global" selectedTemplate thing:
var H_UI = (function () {
function compileTemplate(){}
function parseTemplateFields(){}
// make a template
function template(templateString) {
return {
getHtml: function(){
return compileTemplate(parseTemplateFields(templateString));
},
collect: function(){
// .. operating over templateString ...
return JSON.stringify(result)
}
}
}
return {template:template};
})();
or make only one module with with a global selectedTemplate, a setter for it, and global methods:
var H_UI = (function () {
var selectedTemplate;
function compileTemplate(){}
function parseTemplateFields(){}
return {
template: function(templateString){
if (templateString)
selectedTemplate = templateString;
return this; // for chaining
},
getHtml: function(){
return compileTemplate(parseTemplateFields(selectedTemplate));
},
collect: function(){
// .. operating over selectedTemplate ...
return JSON.stringify(result)}
}
};
})();
The difference is striking when we make two templates with that method:
var templ1 = H_UI.template("a"),
templ2 = H_UI.template("b");
What would you expect them to do? In a functional design, templ1 must not use "b". With the first snippet we have this, and templ1 != templ2. However, if .template() is a mere setter, and every call affects the whole instance (like in the second snippet), we have templ1 == H_UI and templ2 == H_UI.
I've just seen this pattern in javascript:
var test = function () {
function test(args) {
this.properties = args || {}; //etc
}
}
test.prototype.methodName = function (){} //...etc
What is going on with the function definition; declared once outside and once inside. What is the value of this approach?
It is strange. The "outer" function acts as a constructor, you can use var myTest = new test(); to create a new test.
The inner function, because of JS function-scoping, would only be available within the constructor method. You could call the inner test(...) from within the constructor, but it seems pointless as presumably args should be passed in to the constructor.
What might have been intended is:
var test = function(args) {
this.properties = args || {}; // you may want to actually parse each arg here
}
test.prototype.someOtherMethod = function() {}
The first thing to understand here is that functions in JavaScript create new scopes – there is no block scope (yet). So every variable or function declared inside another function is not visible to the outside.
With that in mind: when you define the inner function with the same name of the outer, you lose the ability to call the outer function recursively from itself, by name, because the inner function will "take over" (or "shadow") that name. Inside both functions, test will refer to the inner function, and outside the outer function test always refer to the outer function.
Since after the function definition you're modifying test.prototype, we can assume test (the outer one) will be used as a constructor. In this case, the inner test can be seen as a "private" method of the constructor, callable only from within the constructor. For detailed examples of this object-oriented use of functions within functions, see James T's answer.
This is scope.
When you define a variable as a function, it creates function scope.
Inside that function you can declare the same name, because that function is declared within that scope... Take an easier to follow example:
var User = function()
{
function PrivateToScope()
{
// A Function Only Accessible Inside This Function
alert( "private" );
}
return
{
PublicToScope: function()
{
// A Function Accessible From Outside This Function
alert( "public" );
}
}
}
var James = new User();
James.PublicToScope(); // Will alert "public"
James.PrivateToScope(); // Will fail to do anything
So to explain the answer, the User sets scope, and because you declare the function as above wit the same name, it does not matter.
People do not like me saying this but you can think of this approach as if it were a class in other languages.
var User = function()
{
}
is like
class User
{
}
var User = function()
{
function Something()
{
}
}
is like
class User
{
private function Something()
{
}
}
and finally
var User = function()
{
this.Something = function()
{
}
// or
return {
Something: function(){}
}
}
is like
class User
{
public function Something()
{
}
}
It's alllll about scope. maybe you have a user variable declared as a function and you wish to allow people to get his first name and last name, you would declare these variables or functions as "public"... but what if you wanted to know his diet was good or bad, you may have some complex functions to work it out, but you want to know one thing, good or bad.. you could make all these functions that do ugly stuff private, and then just display the result with a public function...
var User = function()
{
function CalculateDiet()
{
// Lots of scary diet calculating stuff comes out with the result
return result;
}
return
{
FirstName: "James",
LastName: "Poop",
StandardOfDiet: function()
{
return CalculateDiet();
}
}
}
var MyUser = new User();
alert( MyUser.FirstName );
alert( MyUser.StandardOfDiet() );
Why do you care?
Quantifying it is both easy and hard but here are some good ones...
It's neat
If you place a pile of chocolates on a table, they'll all get eaten.. but one of them was for you, people are greedy... Only layout on the table what you want them to eat, they can't be greedy then an accidently eat your chocolate
It sets you up for class oriented programming
It's clear what the programmer meant to do with the code
Memory usage (I'm sure there are overheads to declaring more functions public without need to
Finally, and on a very different note, you have a prototype attached to test, so let's go do this for our user example. Imagine we had an array of users:
var users = [
new User(),
new User()
];
we can iterate over these and get all their usual properties and methods:
for( a in users )
{
alert( users[ a ].FirstName );
}
But let's say something happens in our application... a user clicks on a button that asks each user if they like fish and chips or not, we now need a new method for the user... We can prototype a new method to all iterations of that variable "user" we created... We could declare it before hand, but then we'd waste memory and maybe confuse future programmers with its presence that is based off of something very specific:
// user clicks button and runs this code
User.protoype.DoesUserLikeChips = function(){
// put some code in here that somehow makes this example make sense :)
}
now on every user in your array, you can call this new method... New functionality babehhh!
You may be thinking, why do you not just go users[ a ].DoesUserLikeChips = function(){}... The answer is that it is applied to only that one instance...
Inner test function is a private function of outer test function. And then a methodName function has been set as public function of outer test function. There are no special thing about naming inner function as outer one.
I’ve got a JavaScript object built like this:
var Dashboard = {
form: {
action: function(){
return $('#upload_form').attr('action');
}(),
//snip (more functions)
}
}
If I call (using Chrome 17 on WinXP) Dashboard.form.action in the Chrome console after the page loaded (I checked the script and the function is there) the result is undefined but, if I then redefine Dashboard.form.action using the same function:
Dashboard.form.action = function(){
return $('#upload_form').attr('action');
}();
and subsequently call it, it works as expected!
What am I doing wrong? Is this a bug or am I just overthinking it?
Update:
Re your comment below:
actually what I want to do IS assigning the result to the action property...
In the question you said:
If I call...Dashboard.form.action...
which makes it seem like you're expecting action to be a function (you don't "call" non-functions).
If you're expecting it to be a string (the "action" attribute value from #upload_form), then you don't need to use a function at all. But you do need to be sure that you're doing it after the #upload_form element already exists in the DOM.
To do that, either put your script below it in the markup (anywhere below it is fine; just before or just after the closing </body> tag works well), or wrap your script in a ready call.
So your code becomes either this if it's after the #upload_form in the markup:
var Dashboard = {
form : {
action : $('#upload_form').attr('action'),
//snip (more functions)
}
};
...or this if you want to use ready (anything else using Dashboard will have to wait until ready as well):
jQuery(function($) {
var Dashboard = {
form : {
action : $('#upload_form').attr('action'),
//snip (more functions)
}
};
});
Note that in the second case, Dashboard will no longer be a global variable. That's a good thing, but if you need it to be global for some reason, you can export it:
jQuery(function($) {
var Dashboard = {
form : {
action : $('#upload_form').attr('action'),
//snip (more functions)
}
};
// Export the global
window.Dashboard = Dashboard;
});
Just make sure nothing tries to use Dashboard before ready has fired.
Original answer:
You have an extra pair of () on that:
action: function(){return $('#upload_form').attr('action');}()
// here -------^^
By putting them there, you call the function immediately, and assign the result of calling it to the action property. You just want to assign the function itself to the property, so don't put the () at the end to call it:
action: function(){return $('#upload_form').attr('action');}
This is for exactly the same reason you wouldn't use () here (let's assume you have a function called foo) if you want f to refer to foo:
var f = foo;
If you said
var f = foo();
...you'd be calling foo, not referring to it.