How do I execute a function only once in CoffeeScript - javascript

I want to make a CoffeeScript function that even if it is invoked multiple times, has its effects only run once.
Is one of these, or another way a good way to make a once-invokable function ? Is the extra do an issue or actually better ?
once_maker_a = (f)->
done=false
->
f.call() unless done
done=true
once_maker_b = (f)->
do(done=false)->
->
f.call() unless done
done=true
oa = once_maker_a(-> console.log 'yay A')
ob = once_maker_b(-> console.log 'yay B')
oa()
yay A #runs the function passed to the once_maker
undefined #return value of console.log
oa()
undefined #look, does not reprint 'yay A'
ob()
yay B
undefined
ob()
undefined
I know about http://api.jquery.com/one/ and http://underscorejs.org/#once but in this case using those libraries is not an option.

Is one of these a good way to make a once-invokable function?
As #UncleLaz stated in the comments, you're ignoring any arguments to the function. Also you don't memoize the return value of the function, and always just return true. If you're really only caring about side effects, then that might not be a problem.
Is the extra do an issue or actually better?
In your case it's an issue. Check out the compiled javascript. Even if you corrected the indentation, it's not better since it's just unnecessarily introducing another scope.
A better, minimalistic way might be
once_maker = (f) ->
->
f?.apply this, arguments
f = null
(still not caring about the return value)

Related

Inconsistent jQuery each() behavior with unexplainable fix

I'm writing a plugin based on this handy template for class-based CoffeeScript jQuery plugins: https://gist.github.com/rjz/3610858
Everything works pretty well. However, there is some unexpected behavior at the end when I register the plugin:
$.fn.extend markdownAsides: (option, args...) ->
#each ->
$this = $(this)
data = $this.data('markdownAsides')
if not data?
$this.data 'markdownAsides', (data = new MarkdownAsides(this, option))
if typeof option is 'string'
data[option].apply(data, args)
data # Plugin breaks without this line
Before I added that final line (a solution I discovered purely on accident), the initial construction of the plugin worked fine, but on successive method calls, the jQuery each loop sometimes failed to iterate through every element.
Checking this.size() outside the each loop returned the correct value, and checking individual elements outside the loop also looked fine. But inside the loop, elements would sometimes be skipped, in a pattern I could not discern.
Like I said, the problem is fixed by adding the final line. (Perhaps the return value of the function being passed to each matters somehow?) My question isn't "how do I fix this?" but "why does this work?"
Returning false from the callback function passed to each will break out of the loop. I haven't verified but perhaps jQuery will also break on any falsey value except undefined.
Since in CoffeeScript there's an implicit return, you were possibly returning something falsey or even false from the callback depending on the operation performed in it.
To avoid any issues, just change data for true at the end.

Is this bad practice: getMyObject().method()

Suppose I have a function which returns an object :
getMyObject(){
//do stuff here
return object;
}
Is it bad practice to call a method (that doesn't return anything) on the function name itself:
getMyObject().method();
instead of assigning a variable to the return object and then calling the method on that variable :
var returnedObject = getMyObject();
returnedObject.method();
I am working with an html page that has many nested frames, and I have access to a function that returns one of these frames. The frame might be used several times within other functions in my script, and I was wondering if it would be ok for me to access the frame in the way asked above, or if it would be better to declare a global variable.
*EDIT: * Ahh I haven't gotten a chance to use jQuery. Good to know!
Yes, this is perfectly OK. jQuery for example uses this as well. It returns objects on which you can call methods immediatley. This is called chaining.
In your example, method chaining is the better practice IMHO. If a function returns an object, upon which you want to call a method, but you do not need to reference that object after calling that method, don't assign it to a variable.
Also, jQuery code does this all the time(1):
$('#foo').on('click',function(){});
/\ \\
|| \\
|| \\
function call returns jQ object <============|
\\ ||
\\call method "on" upon _||
(1)To clarify: I do not claim that all jQ methods return an object .attr() or .prop() don't. What I mean by "all the time" is actually that the scenario the OP describes is very common in jQ code (function call, invoke method on returned object):
var someString = $($('.foo').get(0)).attr('id');//tricky little bugger, this :)
var aBool = $('#foo').prop('checked');
Usually, no. Chaining method calls like that is usually simpler, more elegant, and easier to read. However, there are a few cases when it's better to use a variable.
If you use a method (or chain of methods) a lot of times, you can use a variable if it makes the code cleaner.
If the method takes a long time to process, it's better to cache the result. For example, if you have some method called calculateResults(), and it pulls data from a database, that takes some time. If the data doesn't change, you'll be incurring that cost for each call to the method. Better to store it in a variable and reuse it.
If the method has side effects, you should be careful about calling it more than once. Those side-effects will be inflicted each time you call it. Again, as an example, if you have a function like nextItem() that advances to the next item and returns it (a la Java iterators), then calling it more than intended will actually change the result. In this case, you have no choice but store the result, since calling it more than once will produce incorrect behavior.
Otherwise, chain away!

Why does JSHint dislike ternaries for method calls on objects?

JSHint give the following error:
Expected an assignment or function call and instead saw an expression.
For the following line of code:
(aFunctionOrNull) ? aFunctionOrNull() : someObject.someMethod();
It highlights the final ) on someMethod so I assume the error is there. The code works and JSHint doesn't have a problem when I change it to if () {} else {} syntax. I don't mind the longer syntax but I'd like to learn why JSHint says this and if this is a bad practice.
The biggest piece of confusion may come from the terminology. Is someObject.someMethod() not a function call?
Well, in general it's considered bad practice to call a function using the ternary operator(s), without assigning the return value (which is what you seem to be doing).Also, it could be worth checking what JSHint has to say about the following code:
(aFunctionOrNull || someObject.someMethod)();
If aFunctionOrNull is undefined (or null, or falsy), the logical-or-bit will cause the expression to evaluate to someObject.someMethod, and the resulting value of that is invoked (a reference to a function object, hopefully). This gives you the opportunity to write your code more "fail-safe" without the bulk of a nested ternary:
(aFunctionOrNull || someObject.someMethod || function(){})();
The grouped expression is now bound to evaluate to a truthy value, so no errors are thrown there.
To avoid JSHint nagging about your not doing anything with the return value, either assign it to a variable (which I don't really like doing), or add a little operator to the mix:
~(aFunctionOrNull || someObject.someMethod || function(){})();//bitwise not
!(aFunctionOrNull || someObject.someMethod || function(){})();//logical not, doesn't really matter which one
On your last question: someObject.someMethod is indeed a function call. More specifically, it's a call to a function object in the someObject's context.
For those who don't know this: JS functions are objects, and the called context is either explicitly set using the bind method (defined on the Function.prototype) or ad-hoc:
var referenceToMethod = someObject.someMethod;
referenceToMethod();//<-- inside the function objects, this now points to the global object
An easy way to think of it is that JS functions just float around aimlessly in memory/space/time, until they are called via a reference, the context of that reference is then passed to the function object, to determine what object it'll interact with. This is, sadly, the global object by default, or null in strict mode.
JSHint says about expressions, or expr:
This option suppresses warnings about the use of expressions where
normally you would expect to see assignments or function calls. Most
of the time, such code is a typo. However, it is not forbidden by the
spec and that's why this warning is optional.
While JSLint says:
An expression statement is expected to be an assignment or a
function/method call or delete. All other expression statements are
considered to be errors.
AFAIK, there's no problem in doing what you're doing only that it will issue a warning because it would expect you to use an if..else statement, but you can turn this off in JSHint with:
/*jshint expr:true */
There error is because a ternary is an expression. You could use it to set a variable:
var result = a ? b : c;
Notice that the ternary evaluates to either b or c. It's an expression.
That said, the warning (I believe) comes from the notion that ternaries suffer poorer readability than an if...else block. The code above can be rewritten
var result;
if (a) {
result = b;
} else {
result = c;
}
Which is easier to read than a ternary. JSHint does as much to promote readable code as it does valid code. If you're comfortable including these expressions in your code, go ahead and disable the warnings for expressions. (It's what I would do.)

Reference to Originating Conditional Value within a Javascript IF Statement

I often find that I write IF statements which immediately reference the value of the conditional statement. For example, let's say I need to check to see if a string matches a pattern:
if (mystring.match(/mypattern/) {
var mymatch = mystring.match(/mypattern/)[1];
...
};
I suspect that what I'm looking for doesn't exist, but I've wondered whether you can reference the conditional statement's value within the if block, the way you can reference "arguments" within a function. In many cases, of course, I can rewrite it like this:
var mymatch = mystring.match(/mypattern/)[1];
if (mymatch) { ... };
But that's often not possible if there's a series of methods called. For example:
var mymatch = $('.myclass')[0].text().match(/mypattern/)[1];
... that would throw an exception if there were no item [0] on which to call .text(). Is there some convenient shorthand I'm missing out on? Or a better way to organize things? Just curious, really — I'll go on living if the answer is no.
In cases where relevant you can use the fact that the assignment operator returns a value in JavaScript, so for instance you can write things like:
if (assignedTest = testedValue) {
//value of assignedTest is now available
//and conditional will only be executed if true
This could be used if the RHS was compatible or properly set-up but it's also a huge readability concern since it's very easy to confuse the assignment = with comparison ==/===.
If you were particularly motivated to pursue this you could extract this type of functionality into a function that would behave in a reliable way: such as assigning the result of a closure to a named variable, and you could further tune the behavior to do other things (such as optionally evaluating to a different value within the test). Ultimately it would primarily be making a simple structure more complex though.

JavaScript object definition conditionals - which is better?

I've come across two different ways to define/name objects and functions in JavaScript that first check for the existence of the name before using it. The issue is, I don't know which one is better (from speed and usability standpoints) and it's impossible to use the boolean operators in a Google search to figure it out.
The first one I see most often:
var myNewObject = myNewObject ? myNewObject : function () {
// Code goes here.
};
The second one seems more concise, but I've only seen it one or two places, so I don't know if there's a standard or even a name for it:
var myNewObject = myNewObject || function() {
// Code goes here.
};
Functionally, they both do the same thing and they both seem to work in every browser I can test in. My question is this - which is better and why? Also, while the first definition is essentially a single-line conditional ... what is the second one called?
I would choose the latter if only for the fact that you type myNewObject twice instead of thrice.
Also, while the first definition is essentially a single-line conditional ... what is the second one called?
Short-circuit evaluation
I would use the second example, which is described as (Minimum Eval). Its simpler and seems more readable.
It's just like getting an event from onClick method across multiple browsers.
element.onclick = function (evt) {
evt = evt || window.event
}
The latter, it's similar to the null coalesce operator in c# ?? when used in that manner
see: Is there a "null coalescing" operator in JavaScript?
FWIW I see the second approach more often, and (for my part) I feel it's more clear, concise, and idiomatic.
Both methods work.
But I think the most optimized version is to simply use a normal if test like:
if(!myNewObject)
myNewObject = ...
Doing in any one of the method you suggest in your answer, it might involve an unnecessary reassignment every time the function/object is already defined. I mean if myNewObject is already defined, the JavaScript runtime would have to perform an unnecessary reassignment myNewObject = myNewObject (unless the runtime doesn't optimize it out).
On Mozilla website they suggest to use a simple if, view this.

Categories