This is the source code for Underscore.js' delay function:
_.delay = function (func, wait) {
var args = slice.call(arguments, 2);
return setTimeout(function () { return func.apply(null, args); }, wait);
};
How is this any different from setTimeout? Why does Underscore.js need delay?
It's a cross browser way of being able to pass extra arguments which will appear as the arguments to the callback, like setTimeout(). This doesn't work in IE.
It can make your code prettier...
setTimeout(_.bind(function() { }, null, "arg1"), 1e3);
...vs...
_.delay(function() { }, 1e3, "arg1");
I agree that it's one of the less useful Underscore methods, which are outlined in Naomi's answer.
Why does Underscore.js have a delay function?
Because dumb. This particular underscore.js method seems pretty stupid.
Cons
additional function in lib means larger code base
larger code base means more to maintain and more possible bugs
code that uses this function now has a dependency on that lib
lesser/nil improvement over native API means low cost:gain ratio
new apis to learn
Pros
this section intentionally left blank
I would just learn to use javascript and do something like
var hello = function() {
console.log("hello");
};
var delay = 1000;
window.setTimeout(hello, delay);
Simple, right? Underscore.js is sometimes pretty useless. Honestly, window.setTimeout is perfectly useful just the way it is.
Here's another example to show how to pass an arg to the function
var Cat = function(name) {
function meow(message) {
console.log(name, "says meow!", message);
}
this.meow = meow;
};
var duchess = new Cat("Duchess");
window.setTimeout(duchess.meow.bind(duchess, "please feed me!"), 2000);
// 2 seconds later
// => Duchess says meow! please feed me!
If you can't depend on .bind you can use a closure too
window.setTimeout(function() {
duchess.meow("please feed me!");
}, 1000);
Wow, that was difficult, though. I'm going back to underscore and lodash and jquery. This JavaScript stuff is tough !
aes·thet·ics
The author of that library, who chose to spend his/her spare time to open source it, talk about it, use it as a way to introduce people to javascript and perhaps get someone to have a light-bulb moment around closure scope thought the library's attractiveness was enhanced by having this.
Arguing the relevancy of this function in isolation is like arguing the relevancy of a painting or other piece of craftsmanship. Some may like it, others may not.
You are free to like it or not. I, personally, prefer just-get-to-the-point libs.
_.delay, _.defer, _.throttle, _.after have a flow IMHO that reads better than window.
On-top of this, generally I also like writing node server side (nodejs) and not have to shift/in/out of mode... try using window.timeout in node and see what happens.
Not much, although it fits thematically with defer, debounce, and so on. This means you can use the underscore wrapping notation:
_(yourfunction).delay(1000);
Also it doesn't seem like it will let you get away with a string argument, which would call eval.
Related
Is it worth using mini functions in JavaScript? Example:
function setDisplay(id, status) {
document.getElementById(id).style.display = status;
}
And after that, each time you want to manipulate the display attribute of any given object, you could just call this function:
setDisplay("object1", "block");
setDisplay("object2", "none");
Would there be any benefit of coding this way?
It would reduce file size and consequently page load time if that particular attribute is changed multiple times. Or would calling that function each time put extra load on processing, which would make page loading even slower?
Is it worth using mini functions in JavaScript?
Yes. If done well, it will improve on:
Separation of concern. For instance, a set of such functions can create an abstraction layer for what concerns presentation (display). Code that has just a huge series of instructions combining detailed DOM manipulation with business logic is not best practice.
Coding it only once. Once you have a case where you can call such a function more than once, you have already gained. Code maintenance becomes easier when you don't have (a lot of) code repetition.
Readability. By giving such functions well chosen names, you make code more self-explaining.
Concerning your example:
function setDisplay(id, status) {
document.getElementById(id).style.display = status;
}
[...]
setDisplay("object1", "block");
setDisplay("object2", "none");
This example could be improved. It is a pity that the second argument is closely tied to implementation aspects. When it comes to "separation of concern" it would be better to replace that argument with a boolean, as essentially you are only interested in an on/off functionality. Secondly, the function should probably be fault-tolerant. So you could do:
function setDisplay(id, visible) {
let elem = document.getElementById(id);
if (elem) elem.style.display = visible ? "block" : "none";
}
setDisplay("object1", true);
setDisplay("object2", false);
Would there be any benefit of coding this way?
Absolutely.
would [it] reduce file size...
If you have multiple calls of the same function: yes. But this is not a metric that you should be much concerned with. If we specifically speak of "one-liner" functions, then the size gain will hardly ever be noticeable on modern day infrastructures.
...and consequently page load time
It will have no noticeable effect on page load time.
would calling that function each time put extra load on processing, which would make page loading even slower?
No, it wouldn't. The overhead of function calling is very small. Even if you have hundreds of such functions, you'll not see any downgraded performance.
Other considerations
When you define such functions, it is worth to put extra effort in making those functions robust, so they can deal gracefully with unusual arguments, and you can rely on them without ever having to come back to them.
Group them into modules, where each module deals with one layer of your application: presentation, control, business logic, persistence, ...
It would reduce file size and consequently page load time if that particular attribute is changed multiple times. Or would calling that function each time put extra load on processing, which would make page loading even slower?
It won't make the page's loading slower. Adding a few lines here and there with vanilla js won't effect the page loading time, after all, the page's loading time is the time to load the html js and css files, so a few lines in js won't effect it. A performance issue is unlikely to happen unless you're doing something really intended that brings you into a massive calculation or huge recursion.
Is it worth using mini functions in JavaScript?
In my opinion - Yes. You don't want to overuse that when unnecessary, after all, you don't want to write each line of code in a function right? In many cases, creating mini functions can improve the code's cleanness, readability and they can made it easier and faster to code.
With es6 you can use a single line functions with is very nice and easy:
const setDisplay = (id, status) => document.getElementById(id).style.display = status;
It doesn't really affect the performance unless you execute that function 10,000 or more times.
Jquery use mini functions, like $('#id').hide(); $('#id').show(); and $("#id").css("display", "none"); $("#id").css("display", "block");
It creates more readable code but it doesn't do that much to the performance.
var divs = document.querySelectorAll("div");
function display(div, state) {
div.style.display = state;
}
console.time("style");
for(var i = 0; i < divs.length; i++) {
divs[i].style.display = "none";
}
console.timeEnd("style");
console.time("function");
for(var j = 0; j < divs.length; j++) {
display(divs[j], "block");
}
console.timeEnd("function");
<div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div>
In terms of runtime performance I’d say it doesn’t make any difference. The JavaScript engines are incredibly optimized and are able to recognize that this function is being called often and to replace it by native code, and maybe even able to inline the function call so that the cost of calling an extra function is eliminated completely.
If your intent is to reduce the JavaScript files: you save a few tens of bytes for each place in the code where the function can be used, but even if you call this mini function 100 times, you will be saving 1 or 2 kb of uncompressed JavaScript. If you compare the final gzipped JavaScript (which should be how you serve your resources if you care about performance) I doubt there will be any noticeable difference.
You also need to think about how this type of code will be understood by your colleagues, or whoever may have to read this code in the future. How likely it is that a new programmer in your team knows the standard DOM API? Your non-standard functions might confuse your future teammates, and require them to look into the function body to know what they do. If you have one function like this it probably doesn’t make much of a difference, but as you start adding more and more mini functions for each possible style attribute you end up with hundreds of functions that people need to get used to.
The real benefit is ability to update on several places. Let say that you realize that you want to use classes instead of using styles. Instead of having to change on all places, you can just change that one method.
This is even more apparent when you read from a common source. Perhaps you have an API that you call with a single method.
let user = getData('user');
...but instead doing a API call, you want to use localforage to store the user data and read from the disk instead.
let user = getData('user');
... but you realized that it takes about 70-200 ms to read from localforage, so instead you store everything in memory, but reading from localforage if it's not in memory, and doing an API call if it's not in localforage. Getting user information is still the same:
let user = getData('user');
Just imagine if you wrote the whole call in every single place.
I usually create mini functions like these if I 1) read/write data, 2) if the code gets shorter OR more readable (i.e. the method name replaces comments), 3) or if I have repeatable code that I can sum up in a dynamic way.
Also, to quote from the book Clean Code: each function should do only one thing. Thinking in terms of mini functions helps with that.
I'm not fully sure of what a mini function is but if you're asking whether it's better to define functions for code that needs to be called multiple times instead of typing out/ copy-pasting those same lines of code over and over then it's better to go with option 1 for readability and file-size.
It would reduce file size and consequently page load time if that particular attribute is changed multiple times. Or would calling that function each time put extra load on processing, which would make page loading even slower?
It's not in typical scenarios possible for the usage of such functions to put (any significant) extra load on processing that would slow down the document parsing, it's likeliness to do that would however depend on when and how you call your code to be executed but it's not like you'll be looping O(N3) and calling such functions thousands of times to impact page loading (right?) - if anything, predefined functions like that meant to take dynamic inputs would make your code neater, more uniform looking and reduce file-size... with a very tiny obvious overhead when compared to directly accessing properties without having to go through another function. So you decide whether you want to take up that bargain depending on whether the frequency of you calling functions like that would be significant enough to be considered.
I'm sure most engines optimize repetitive code so it's (or nearly) equivalent to the same thing anyway so I'd choose readability and improve how easy it is for others to understand and follow through code instead.
JavaScript is prototype language on top of that going on a leaf to say everything in JavaScript is an object so its object oriented as object oriented gets to be although at a very different level.
So the question is like we create classes in object oriented, would we develop script framework as functional programming or prototype and what will be performance hit.
so lets consider this very fine example.
function abc(name, age) {
this.name = name;
this.age = age;
}
person1 = new abc('jhon', 25);
person2 = new abc('mark', 46);
console.log(person1.age);console.log(person2.age);
person1.father = 'mark';
console.log(person1.father);
we have created a function and have used the power of this in the scope of function thus every new insurance will carry this information. and no two instances will be alike.
Then down the a line we have used prototype to add father information on instance. This where prototyping becomes awesome. Thus whole this scoping + instance + prototyping is fast.
function abc(name, age) {
name = name;
age = age;
return name; // its either name or age no two values
}
person1 = abc('jhon', 25);
person2 = abc('mark', 46);
console.log(person1);
console.log(person2);
abc.father = 'mark';
console.log(person1.father);
console.log(abc.father);
we tried the same on functional sense the whole thing fell apart. no instance + no this scoping + no new prototyping delegating down the line. Thus in long run this approach will reduce performance as one would have to re-fetch things over and over again on top of that with t=out this scoping we are only returning single factor where as with this scooping we are packing a lot more into object. this one point.
function abc(name, age) {
this.name = name;
this.age = age;
}
person1 = new abc('jhon', 25);
person1.fatherName = 'Mark';
person1.fatherUpdate = function (d){this.fatherAge = this.fatherName+' '+d;};
person1.fatherUpdate(56);
console.log(person1.fatherAge);
Now have added more complexity we have carried this down the line hence the scope and have added functions on top of it.
This will literally make your hair fall out if things were done in pure functional way.
Always keep in mind any given function can and may compute and execute as many things you want but it will always give single return with 99% of the time single property.
If you need more prototype way with scoping as above.
jquery way of doing things.
I had made my framework ActiveQ which uses the above its almost 30 Kb unminified and does everything jquery does and much more with template engine.
anyways lets build example - it is an example so please be kind ;
function $(a){
var x;
if(x = document.querySelector(a)) return x;
return;}
console.log($('div'));
console.log($('p'));
<div>abc</div>
Now this almost 50% of your jquery selector library in just few lines.
now lets extended this
function $(a){
this.x = document.querySelector(a);
}
$.prototype.changeText = function (a){
this.x.innerHTML = a;
}
$.prototype.changeColor = function (a){
this.x.style.color = a;
}
console.log(document.querySelector('div').innerText);
app = new $('div');
app.changeText('hello');
console.log(document.querySelector('div').innerText);
app.changeColor('red');
<div>lets see</div>
what was the point of the whole above exercise you wont have to search through DOM over and over again as long as long one remains in scope of the function with this
Obviously with pure functional programming one would have to search though all over again and again.
even jquery at time forgets about what it had searched and one would have to research because this context is forwarded.
lets do some jquery style chaining full mode way - please be kind its jusrt an example.
function $(a){
return document.querySelector(a);
}
Element.prototype.changeText = function (a){
this.innerHTML = a;
return this;
}
Element.prototype.changeColor = function (a){
this.style.color = a;
return this;
}
console.log($('div').innerText);
//now we have full DOm acces on simple function reurning single context
//lets chain it
console.log($('div').changeText('hello').changeColor('red').innerText);
<div>lets see</div>
See the difference less line of code is way faster in performance as its working with the browser rather then pure functional way rather then creating a functional call load and search load all repeatedly
so you need to perform bunch of tasks with single output stick to functions as in conventional way and if you need to perform bunch of tasks on context as in last example where context is to manipulate properties of the element as compared to $ function which only searches and returns the element.
Why would you use a jQuery plugin over a traditional javascript function? The only difference I see is you need to pass in a jQuery object into the js function... other that that, I don't see a huge difference, as it seems both can accomplish the same thing in similar steps:
$(document).ready(function () {
$('p').jQuery_greenify();
greenify($('p'));
});
$.fn.jQuery_greenify = function () {
this.css("color", "green");
};
function greenify (el) {
el.css("color", "green");
}
I also find namespacing to be easier with javascript functions:
var mynamespace = {
greenify : function (el) {
el.css("color", "green");
}
}
mynamespace.greenify($('p'));
Usually, usefulness of JQuery functions is in chaining them. Just like you want to call:
string.substring(2, 5).startsWith("lol")
instead of
Util.StartsWith(Util.substring(string, 2, 5), "lol")
It's easier to read that way. In fact, I think that second function might still need a "return this" to be useful?
It may depend on the context - some operations are very much tied to an element or set of elements, while others just make more sense standing on their own - thus, your approach of namespacing would be just fine. It's partially coding style.
A disclaimer - I'm not as experienced with writing JQuery plugins, this is just my general observations based on JS language design.
Always a jQuery object
When using a plugin as you said (it is really an object prototype) You are sure that this will be a jQuery object since you cannot call it without a jQuery object except if you make your way around with .call, .apply, .bind and etc.
Meanwhile, you can pass anything to a function, so the argument may not be a jQuery object and will throw an error.
Readability when chaining
You can chain function with both method, but let be honest, with a jQuery prototype, it is prettier :
$.fn.jQuery_greenify = function () {
return this.css("color", "green");
};
$('div').jQuery_greenify().append(...);
//VS
function greenify (el) {
return el.css("color", "green");
}
greenify($('div')).append(...);
Scope
When adding a function to the prototype, no matter which scope you are, it will be accessible everywhere. That allow you the create a certain closure :
(function(){
$.fn.jQuery_greenify = function () {
return this.css("color", "green");
};
})();
$('div').jQuery_greenify(); //Work
//VS
(function(){
function greenify (el) {
return el.css("color", "green");
}
})();
greenify($('div')); //Undefined is not a function error
The original usefulness of jQuery was to provide a consistent API to things such as DOM manipulation and AJAX - things which [older] browsers implemented very differently. It would take 20+ lines of code to do what can be done with 1 - 2 lines with jQuery. It abstracted away all of the inconsistencies so you could just focus on coding.
Then, John Resig's worst nightmare happened and people now think jQuery is a language, almost separate and independent from Javascript. </rant>
Today, most browsers have adopted standards and you don't have to worry so much about inconsistencies unless you are trying to support < IE9. You can use something like underscore to help take advantage of newer javascript features (with backwards compatability for things which are still inconsistently implemented even in today's browsers).
Regarding plugins, the advantage is having a consistent way to implement reusable code. For example, I kind of disagree with how you created a namespace (not really, but I would have done it differently).
Point is, it's all javascript. Learn javascript. If it's easier and quicker to do it without using a library, by all means do it! Pay attention to the community and try and use techniques which have been adopted by others... even if it occasionally means using a library.
NOTE: If someone puts jQuery under the "languages" section on their resume, throw it in the trash.
I know we can use Ctrl+Click or Ctrl+B in NetBeans, but it doesn’t work for me when I’m writing javascript files.
And I’m not the only one (sadly that question has no reply).
I can see the functions on the Navigator, but I can’t use “Go to declaration”.
I’m declaring my functions this way:
function anyName(params...) { ... }
I tried changing to this style:
var anyName = function (params...) { ... }
But that didn’t work either.
I’m using Netbeans 6.9.1.
More info:
NetBeans supports “Go to declaration” in javascript.
As I said, the function is recognized because I can see it in the Navigator.
I can use Ctrl+O and then search for my function, and NetBeans can find it when I do that. I’m using this right now as a poor replacement for “Go to declaration”.
I’ve noticed that I don’t have code completion either. Following the above example, if I write “an” (Ctrl+Space) I can see a lot of functions and methods but I can’t find my function (anyName).
I think I’m doing something really wrong, but I don’t know what.
I think the short answer is NetBeans doesn't have a good parser for JavaScript. JS is such a loosely typed language, it could be incredibly difficult to "Go To" the actual definition of a function. Take these examples:
function callStuff(myFunc)
{
myFunc(); //Where does this go?
}
callStuff(function () { window.alert(123); });
Or:
var x = {
X: function () { },
Y: function () { },
};
x.Z = function () { };
x.Y(); //Where do I go?
x.Z(); //How about this?
Or maybe:
string s = "window.alert(123);";
var callback = Function(s);
callback(); //Now we just made a function with a string, weird..
So as you can see, a JavaScript IDE would need to have an immense amount of knowledge on the run-time execution of your script to figure out exactly where a function was defined. There's a few IDEs that fake it pretty well if you use standard syntax or very obvious function declarations, but I've yet to see anything incredibly useful in this area. It's most likely not really something NetBeans has made an effort to support, since it's such a Java-centric IDE.
The problem seems to be in defining everything as “global”. If you work in your own namespace — that is, create a global object and define everything there — then Netbeans can understand better where your code is and can also give you type hints.
I've been programming for the Web for quite some time now, but have only just recently discovered a few new intricacies regarding the use of functions and the weird (or so I view them as) things you can do with them. However, they seem at this point only to be syntactically pretty things. I was hoping somebody might enlighten me as to how some of these newly discovered aspects could prove to be useful.
For example, the first time I ran this, I thought for sure it would not work:
<script>
function x(q)
{
q(x);
}
x(function(a)
{
alert(a);
}
);
</script>
But it did! Somehow, creating a named function which receives a different, anonymous function as its only parameter and then runs the function passed to it with itself passed as the parameter to it works just fine. This positively blew my mind and I'm almost certain there's a vast amount of practicality to it, but I just can't quite place it yet.
Ah, and another thing I was elated to discover: using a globally scoped variable to store a function, one can later in the execution use JavaScript's eval() function to modify that variable, thus changing the function's inner workings dynamically. An example:
<script>
var f = function()
{
alert('old text');
}
eval('f = ' + f.toString().replace('old text', 'new text'));
f();
</script>
Sure enough, that code alerts the "new text" string; when I saw that, my mind was once again blown, but also immediately intrigued as to the potential to create something incredible.
So... my burning question for Stack Overflow: how can such seemingly abstract coding principles be used in any positive way?
What you're basically asking is How can I use functions as first-class objects?
The biggest and most common usage is closures (or anonymous functions) for event handling. However, just because you can be clever, it doesn't mean you should. Write clear, readable code just as you would in any other language.
Oh, and flog yourself for typing eval and never think about doing it again
The first one, closures, are very common in javascript. If you want some more advanced examples, here's a nice interactive playground you can mess with: http://ejohn.org/apps/learn/.
Here's my window.onload function I use when whatever I'm working on doesn't require a full blown library.
//add events to occur on page load
window.addOnload = function(fn) {
if (window.onload) {
var old = window.onload;
window.onload = function() {
old();
fn();
}
} else {
window.onload = fn;
}
}
Then whenever I need something to happen onload, I can just use an anonymous function. Here's an example from a recent maintenance project of mine.
//make all menu items have a hover property
window.addOnload(function(){
var cells = document.getElementsByTagName('td');
for (var i=0; i < cells.length; i++) {
if (cells[i].className != 'NavMenuItem') continue;
(function(cell){
cell.onmouseover = function() {
cell.className = 'NavMenuItemHighlight';
}
cell.onmouseout = function() {
cell.className = 'NavMenuItem';
}
})(cells[i])
}
});
As for your second 'discovery', just pretend you never found out about it.
Well, the first one is typically how you prove that the Halting Problem is undecidable...
Whether or not you consider that "useful" is entirely up to you, I guess B-)
A friend of mine and I were having a discussion regarding currying and partial function application in Javascript, and we came to very different conclusions as to whether either were achievable. I came up with this implementation of Function.prototype.curry, which was the basis of our discussion:
Function.prototype.curry = function() {
if (!arguments.length) return this;
var args = Array.prototype.slice.apply(arguments);
var mmm_curry = this, args;
return function() {
var inner_args = Array.prototype.slice.apply(arguments);
return mmm_curry.apply(this, args.concat(inner_args));
}
}
Which is used as follows:
var vindaloo = function(a, b) {
return (a + b);
}
var karahi = vindaloo.curry(1);
var masala = karahi(2);
var gulai = karahi(3);
print(masala);
print(other);
The output of which is as follows in Spidermonkey:
$ js curry.js
3
4
His opinion was that since the Javascript function primitive does not natively support "partial function application", it's completely wrong to refer to the function bound to the variable karahi as partially applied. His argument was that when the vindaloo function is curried, the function itself is completely applied and a closure is returned, not a "partially applied function".
Now, my opinion is that while Javascript itself does not provide support for partial application in its' function primitives (unlike say, ML or Haskell), that doesn't mean you can't create a higher order function of the language which is capable of encapsulating concept of a partially applied function. Also, despite being "applied", the scope of the function is still bound to the closure returned by it causing it to remain "partially applied".
Which is correct?
Technically you're creating a brand new function that calls the original function. So if my understanding of partially applied functions is correct, this is not a partially applied function. A partially applied function would be closer to this (note that this isn't a general solution):
vindaloo.curry = function(a) {
return function(b) {
return a + b;
};
};
IIUC, this still wouldn't be a partially applied function. But it's closer. A true partially applied function would actually look like this if you can examine the code:
function karahi(b) {
return 1 + b;
};
So, technically, your original method is just returning a function bound within a closure. The only way I can think of to truly partially apply a function in JavaScript would be to parse the function, apply the changes, and then run it through an eval().
However, your solution is a good practical application of the concept to JavaScript, so practically speaking accomplishes the goal, even if it is not technically exact.
I think it's perfectly OK to talk about partial function application
in JavaScript - if it works like partial application, then it must
be one. How else would you name it?
How your curry function accomplishes his goal is just an implementation
detail. In a similar way we could have partial application in the ECMAScript spec,
but when IE would then implement it just as you did, you would have
no way to find out.
The technical details don't matter to me - if the semantics remain the same and, for all intents and purposes, the function acts as if it were really a partially-applied function, who cares?
I used to be as academic about things, but worrying about such particulars doesn't get real work done in the end.
Personally, I use MochiKit; it has a nice partial() function which assists in the creation of such. I loves it.
You should check out Curried JavaScript Functions. I haven't completely wrapped my head around his curry function, but it might have your answer.
Edit: I would agree with your assessment, however.
His opinion was that since the Javascript function primitive does not natively support "partial function application"
You can do currying in ES6 pretty elegantly:
> const add = a => b => a + b
> const add10 = add(10)
> [1,2,3].map(add10)
[ 11, 12, 13 ]