I came across the following javascript code:
this.removeEdge = function(source, target) {
if(!_states[source]) return;
var children = _states[source].children,
index = _(children).indexOf(target);
if(index !== -1) children.splice(index, 1);
};
What does _(children) mean?
_ is a valid variable identifier in JavaScript, and could theoretically refer to anything. Using _(...) with function syntax implies that _ is a function.
That said, it is commonly used by the underscore.js library, however if you're looking at minified code, it's quite possibly being used as another single-character variable name to save on file size.
In your example provided, it appears that underscore.js is being used to treat children as a collection, so that the indexOf function can be applied to the collection. This would be similar to calling:
_.indexOf(children, target);
Came looking for an answer to this and managed to find one. The _(variable) statement wraps underscore around the variable. According to this link in the "Object-Oriented and Functional Styles" section,
index = _(children).indexOf(target);
is equivalent to
index = _.indexOf(children, target);
The first is written in object-oriented style, which allows chaining of functions. Their example is as follows:
_(lyrics).chain()
.map(function(line) { return line.words.split(' '); })
.flatten()
.reduce({}, function(counts, word) {
counts[word] = (counts[word] || 0) + 1;
Each of these functions returns the underscore function wrapping lyrics, allowing chained manipulation of the lyrics variable.
Underscore changelog:
0.4.0 — November 7, 2009:
All Underscore functions can now be called in an object-oriented style, like so: _([1, 2, 3]).map(...);. Original patch provided by Marc-André Cournoyer. Wrapped objects can be chained through multiple method invocations. A functions method was added, providing a sorted list of all the functions in Underscore.
class Book {
constructor(author) {
this._author = author;
}
It is convention to precede the name of a private variable with an underscore (_). However, the practice itself does not make a variable private.
Related
I came across the following javascript code:
this.removeEdge = function(source, target) {
if(!_states[source]) return;
var children = _states[source].children,
index = _(children).indexOf(target);
if(index !== -1) children.splice(index, 1);
};
What does _(children) mean?
_ is a valid variable identifier in JavaScript, and could theoretically refer to anything. Using _(...) with function syntax implies that _ is a function.
That said, it is commonly used by the underscore.js library, however if you're looking at minified code, it's quite possibly being used as another single-character variable name to save on file size.
In your example provided, it appears that underscore.js is being used to treat children as a collection, so that the indexOf function can be applied to the collection. This would be similar to calling:
_.indexOf(children, target);
Came looking for an answer to this and managed to find one. The _(variable) statement wraps underscore around the variable. According to this link in the "Object-Oriented and Functional Styles" section,
index = _(children).indexOf(target);
is equivalent to
index = _.indexOf(children, target);
The first is written in object-oriented style, which allows chaining of functions. Their example is as follows:
_(lyrics).chain()
.map(function(line) { return line.words.split(' '); })
.flatten()
.reduce({}, function(counts, word) {
counts[word] = (counts[word] || 0) + 1;
Each of these functions returns the underscore function wrapping lyrics, allowing chained manipulation of the lyrics variable.
Underscore changelog:
0.4.0 — November 7, 2009:
All Underscore functions can now be called in an object-oriented style, like so: _([1, 2, 3]).map(...);. Original patch provided by Marc-André Cournoyer. Wrapped objects can be chained through multiple method invocations. A functions method was added, providing a sorted list of all the functions in Underscore.
class Book {
constructor(author) {
this._author = author;
}
It is convention to precede the name of a private variable with an underscore (_). However, the practice itself does not make a variable private.
I'm trying to find out which would be the most optimal way of intersection a set of texts and find the common words in them. Given this scenario:
var t1 = 'My name is Mary-Ann, and I come from Kansas!';
var t2 = 'John, meet Mary, she comes from far away';
var t3 = 'Hi Mary-Ann, come here, nice to meet you!';
intersection result should be:
var result =["Mary"];
It should be able to ignore punctuation marks like .,!?-
Would a solution with regular expressions be optimal?
Here's a tested solution :
function intersect() {
var set = {};
[].forEach.call(arguments, function(a,i){
var tokens = a.match(/\w+/g);
if (!i) {
tokens.forEach(function(t){ set[t]=1 });
} else {
for (var k in set){
if (tokens.indexOf(k)<0) delete set[k];
}
}
});
return Object.keys(set);
}
This function is variadic, you can call it with any number of texts :
console.log(intersect(t1, t2, t3)) // -> ["Mary"]
console.log(intersect(t1, t2)) // -> ["Mary", "from"]
console.log(intersect()) // -> []
If you need to support non English languages, then this regex won't be enough because of the poor support of Unicode in JavaScript regexes. Either you use a regex library or you define your regex by explicitly excluding characters as in a.match(/[^\s\-.,!?]+/g); (this will probably be enough for you) .
Detailed explanation :
The idea is to fill a set with the tokens of the first text and then remove from the set the tokens missing in the other texts.
The set is a JavaScript object used as a map. Some purists would have used Object.create(null) to avoid a prototype, I like the simplicity of {}.
As I want my function to be variadic, I use arguments instead of defining the passed texts as explicit arguments.
arguments isn't a real array, so to iterate over it you need either a for loop or a trick like [].forEach.call. It works because arguments is "array-like".
To tokenize, I simply use match to match words, nothing special here (see note above regarding better support of other languages, though)
I use !i to check if it's the first text. In that case, I simply copy the tokens as properties in the set. A value must be used, I use 1. In the future, ES6 sets will make the intent more obvious here.
For the following texts, I iterate over the elements of the sets (the keys) and I remove the ones which are not in the array of tokens (tokens.indexOf(k)<0)
Finally, I return the elements of the sets because we want an array. The simplest solution is to use Object.keys.
I'm going through John Resig's snippets on advanced JavaScript. On #19 he mentions a method to cache the return value of a function. What's the best way to cache the return value of a function that has more than one parameter?
There has to be a much better way than stringify-ing the recieved arguments and using that as the key for the cache object:
function $$(selector, el) {
var cacheKey = JSON.stringify(arguments);
if ($$.cache[cacheKey]) return $$.cache[cacheKey];
return ($$.cache[cacheKey] = NodeListToArray( (el || document).querySelectorAll(s) ));
}
$$.cache = {};
You could use a custom hash function that can operate on objects. But hash functions cause collisions and would require significantly more code than your simple example.
Or you could make the cache n-dimensional, where n is the number of arguments. So essentially this:
function $$(selector, el) {
if ($$.cache[selector] && $$.cache[selector][el])
return $$.cache[cacheKey][el];
// etc.
That assumes that both selector and el are able to be used as object keys. You may need to stringify them in another manner.
Just consider an array element,
JSON (JavaScript Object Notation) works with generic platform, so for easy use you must create a function for your use,
Here, $$.cache[0] is your easy way after reading the cachekey,
If we make thing more easy, we might have security problem later.
I hope this will satisfy your requirement :)
I'm working my way through "Learning jQuery" (Third Edition).
In Chapter 4: "Manipulating the DOM" there is a section explaining something called the "Value Callback". This is a new one for me.
The author explains this via an example of list of links wherein the ID's of each must be unique.
From the book:
"A value callback is simply a function that is supplied instead of the value for an argument. This function is then invoked once per element in the matched set. Whatever data is returned from the function is used as the new value for the attribute. For example, we can use this technique to generate a different id value for each element, as follows:"
Chaffer, Jonathan (2011-09-23). Learning jQuery, Third Edition (p. 116). Packt Publishing. Kindle Edition.
jQuery(document).ready(function($){
// get all external links
$('div.chapter a').attr({
rel:'external',
title:'Learn more at Wikipedia',
id: function ( index, oldValue ) {
return 'wikilink-' + index;
}
});
})
Works like a charm, but the mechanics of the id: property escape me.
How does parameter 1 (index) know to be an integer?
How does the function know to increment index?
How does the second parameter (oldValue) know to hold the old value of the property (before modification)?
Is this a jQuery construct? A JSON thing? It's cool. it works, but ...what the heck is this "value callback" thing made of?
Please advise
1) How does parameter 1 (index) know to be an integer?
jQuery passes an integer.
2) How does the function know to increment index?
The callback doesn't increment index, the jQuery method does.
3) How does the second parameter (oldValue) know to hold the old value of the property (before modification)?
jQuery passes it.
The answers to questions 1-3 are perhaps best understood by a function that performs something similar to $.attr:
Array.prototype.each = function (f) {
var i;
for (i=0; i < this.length; ++i) {
f(i, this[i]);
}
};
['zero', 'one', 'two'].each(function (i,item) {console.log({i: item})});
f is a callback. each is responsible for iterating over a collection and calling f for each index & item. The same code structure can be used for functions:
/* Map each item in a sequence to something else,
* returning a new sequence of the new values.
*/
Array.prototype.map = function (f) {
var i, result = [];
for (i=0; i < this.length; ++i) {
result[i] = f(i, this[i]);
}
return result;
};
['zero', 'one', 'two'].map(function(i,item) {return item.length});
// result: [4, 3, 3]
/* Return a sequence of the items from this sequence
* for which 'keep' returns true.
*/
Array.prototype.filter = function (keep) {
var i, result = [];
for (i=0; i < this.length; ++i) {
if (keep(i, this[i])) {
result.push(this[i]);
}
}
return result;
};
['zero', 'one', 'two'].filter(function(i,item) {return item.length <= 3});
// result: ['one', 'two']
Implementation of mapconcat, foldl and foldr left as an exercise. As another exercise, rewrite map and filter in terms of each.
Note these functions are merely intended to illustrate how callbacks work. They may cause problems in production code.
4) Is this a jQuery construct? A JSON thing? It's cool. it works, but ...what the heck is this "value callback" thing made of?
Callbacks are a generic technique that jQuery makes extensive use of. They're the key feature of functional programming, where functions are data that can be operated on just like other data types. Thus, you have functions that take functions as arguments and can return functions. In certain contexts, callbacks are also known as "continuations" and form the basis of continuation passing style (CPS). This is particularly important for asynchronous function calls [2] (where the function returns before the computation completes, as opposed to synchronous calls), such as is used for Ajax requests. To see some of the power of CPS, read "Use continuations to develop complex Web applications".
The other aspect of this, the "value" in "value callback", is that, as JS is a dynamically typed language (types are associated with data, rather than variables), formal parameters can be bound to objects of any type. A function can then behave differently depending on what is passed. Sometimes this is implemented by examining the type of the argument, which is in effect ad-hoc polymorphism (the function, rather than the language, must handle dispatch). However, parametric polymorphism or (failing that) duck typing should always be preferred over examining argument types. Parametric polymorphism is achieved by ensuring that all types that can be passed to a given function support the same interface (method names, arguments, preconditions, postconditions & so on). For example, all sequence types should have a length property and be indexed by integers; as long as that holds, you can use your own sequence type with many functions that take arrays.
I'm not sure what you mean by JSON, but it's probably not what is generally meant. JSON is a data interchange format based on a limited version of the JS object literal syntax. JSON is not involved anywhere in the sample code or quoted text.
It's a JQuery construct. If you look at the source, you will find that JQuery is inspecting the parameter in order to learn whether you passed a value or a function. If it's a function, it handles as you see.
With libraries such as ES5-Shim, we can use the new hotness now. Many methods on arrays (like forEach, map, every, etc) could be used now to write clean and beautiful code.
I'd like to have a list a practical uses I can have right now with those new methods when working with the current browsers' API (such as the DOM) or with just javascript.
I'm talking about this kind:
var nodes = document.getElementsByClassName('class')
[].forEach.call(nodes, callback)
function callback(node) {
console.log(node)
}
Another example from #Esailija:
[].filter.call( document.myform.elements, function(input){
return input.type == "text";
});
This is the kind of practical use I'm looking for. Some kind of patterns I'd be able to use in real projects.
The first thing you really will be able to use is the bind() method, I think.
var o = {
act: function() { ...}
}
// Instead of
element.addEventListener("type", function(){ o.act(); }, false)
// you can write
element.addEventListener("type", o.act.bind(o), false)
which is very useful in namespaced modules, where this is everything.
The array iterator methods are useful everywhery when it comes to data handling. No specific examples.
You can use iterator functions to manipulate lists.
So before you used for or while loops and now you use functions.
function isTextNode(node) {
return node.nodeType === Node.TEXT_NODE
}
function extractText(node) {
return node.data
}
function combineText(memo, text) {
return memo += text
}
var text = toArray(nodeList).filter(isTextNode).map(extractText).reduce(combineText)
To get used to "how or why this is useful" stop using for/while and think of your data as sets or lists and think about how you would filter / map / reduce these lists to extract data.
Also make an exercise to not use closures and have your iterator functions seperate and not bound over upvalues.