What does this javascript function do? - javascript

var n = {
Android: /Android/i.test(navigator.userAgent),
Safari: /iPhone|iPad|iPod/i.test(navigator.userAgent) && !/CriOS|Chrome|Mercury/.test(navigator.userAgent)
};
I am curious about the /Android/i.test() function. If this a function in another file? I'm guessing it is not since the next function /iPhone|iPad|iPod/i.test() is even more curious. Is it a string compare on the 'Android' string? Could anyone provide me with some documentation?

It's a method call on the regular expression /Android/i.
The /Android/i part represents a regular expression or "regex", which is used to do pattern-matching on strings.
A regular expression has a method called test, and returns true if it matches. You could rewrite that hunk above as:
androidRegex = /Android/i;
safariRegex = /iPhone|iPad|iPod/i;
criOsregex = /CriOS|Chrome|Mercury/;
var n = {
Android: androidRegex.test(navigator.userAgent),
Safari: safariRegex.test(navigator.userAgent) && !criOsregex.test(navigator.userAgent)
};
The syntax for declaring a regular expression in Javascript is /pattern/flags, where pattern is the pattern to compare against, and flags are additional options.
The Android one is very simple: it just compares against the string Android, with the flag i to make it case-insensitive.
The Safari one is slightly more complex, because it uses "alternation" to match iPhone, iPad, or iPod. The | character delimits alternates in a regex.
The CriOS regex, notably, leaves off the i flag because the author wants it to be case-sensitive (the default).

The var n is declared as an object with two properties which are called Android and Safari.
When the object is initialized, both properties are executed returning a boolean result either the User Agent of the Navigator is Android for the first one, or iPhone, iPad or iPod for the second one.
Therefore, you can expect both properties to be either true or false.
EDIT: As #N3dst4 stated, this is called regular expression. See his reply for more info about it.

Related

Javascript literal regexp vs RegExp object, instances inside loops

I have the following two js example codes, one using literal regexp and the other one using RegExp object:
"use strict";
var re;
// literal regexp
for(var i = 0; i<10; i++)
{
re = /cat/g;
console.log(re.test("catastrophe"));
}
// RegExp constructor
for(var i = 0; i<10;i++)
{
re = new RegExp("cat", "g");
console.log(re.test("catastrophe"));
}
Some books say that using the first example "true" should be printed on each second iteration given the fact that the using the literal expression there will be created only one instance of RegExp. So the loop finds on the first run the substring "cat", than on the second run continues from where is left and finds nothing. On the third run it starts from the beginning and so on. I've tested this but it seems that in both examples i get the count of 10.
Can you explain why this is happening?
The 3rd Edition ECMAScript (JavaScript) specification allowed caching and reusing regular expression literals, including their state, leading to the "surprising" behavior you mention in relation to your first code example, which certainly looks like it should create a new regular expression object on every loop. That caching of literals was not implemented by most engines and was a phenomenally bad idea, and the 5th Edition specification fixes it.
I believe all modern engines that used to do caching (primarily SpiderMonkey, Firefox's engine) were updated accordingly. A new regex is created for every iteration in both of your examples.
More in this blog post (right at the end) by Steven Levithan, and in the fourth paragraph of Annex E in the specification:
7.8.5: Regular expression literals now return a unique object each time the literal is evaluated. This change is detectable by any programs that test the object identity of such literal values or that are sensitive to the shared side effects.
In both cases, you are creating a new RegExp each time through the for loop. It doesn't matter which way you declare the RegExp - it's still creating a new one each time the loop iterates. Thus, you get the same behavior.
Now, if you initialized the re variable before the for loop, you would get a different behavior because of the persistence of the same RegExp object and how it uses the g flag.

Why does IE choke on ({function:1}[typeof somefunc])?

Ok, I've been doing some research and starting using this convention when testing for object types or more apt, detecting typeof ..
({function:1}[typeof somefunc])
and this works, but alas - I tested in IE, error. So, no longer using it.. :-) ,.. but.
So, I reverted to testing in a standard way, no biggie (typeof somefunc === "function" or $.isFunction(somefunc)). But I am curious "why" it doesn't work in IE.
Also, can someone explain why this "does" work in Firefox, or what i mean to say is that the expression is odd to me, I want to know the internals of WHY It works (even though in selective browsers). I don't understand how its backreferencing the function:1 as a test with the typeof?
The JScript parser in IE8 and earlier is following the old ECMAScript 3.1 (1999) rules for object initializers, which require that if you want to use a reserved word (like function) as a property name, it must be in quotes. As of ECMAScript5 (2009), the quotes aren't required anymore because the context is unambiguous. Versions of IE released since the spec was updated (IE9+) do allow you to leave off the quotes.
The difference is that in ECMAscript5, the PropertyName in the object initializer grammar is just IdentifierName, not Identifier. Identifier is an IdentifierName that isn't a ReservedWord. function is a valid IdentifierName, but not a valid Identifier because it is a ReservedWord. More: Identifier Names and Identifiers. But the older spec didn't make that distinction between IdentifierName and Identifier, and so to use function there, you have to put it in quotes. (Thanks to chuckj for reminding me that this changed in ECMAScript5.)
Also, can someone explain why this "does" work in Firefox, or what i mean to say is that the expression is odd to me...
Yes, it's quite odd and anyone working on code using it is likely to stumble on it. It's a short way of writing (typeof somefunc=="function"). Here's what's happening:
The expression creates an object with one property, in this case the property name is function and the value is 1.
The typeof somefunc part is evaluated and returns "function" for a JavaScript function, "object" for a wide range of objects, "number" for a number primitive, "string" for a string primitive, etc.
That property name is used to look up a property on the object created in Step 1. If the property is found, the overall result of the expression is 1, a truthy value. If the property is not found, the overall result is undefined, a falsey value.
So ({function:1}[typeof somefunc]) tests if typeof returns "function" for somefunc. Similarly you can do ({object:1}[typeof someobj]) to check if typeof returns "object" for someobj, or ({string:1}[typeof somestring]) to check if typeof returns "string" for somestring.
Side note: This obscure way of doing the test doesn't perform well at all compared to the straightforward (typeof somefunc=="function"): Test when true | Test when false Unsurprising, given that typeof x == y can be highly optimized by a good optimizing engine. So this way of doing the check is harder to read, longer, no easier to type, and usually slower. Hmmm.... :-)
{function:1} is an object with exactly one key, 'function', mapped to a truthy value, 1. So, ({function:1}['function']) is truthy, but (for example) ({function:1}['string']) is falsy.
Most likely, the reason that IE doesn't support it is that function is a reserved word (as you must know), and IE apparently is getting confused by its use in this context. (If so, this is a mistake in IE: surprisingly, the spec actually does allow reserved words to be used in this context.)
just put function in quotes as function is a reserved keyword but "function" is just a string literal
({"function":1}[typeof somefunc])
should work just fine
but then, why won't you simply use:
(typeof somefunc == "function")
it's shorter and more intuitive

Difference between RegExp constructor and Regex literal test function? [duplicate]

This question already has answers here:
Why does a RegExp with global flag give wrong results?
(7 answers)
Closed 6 years ago.
I'm confused on how this is possible...
var matcher = new RegExp("d", "gi");
matcher.test(item)
The code above contains the following values
item = "Douglas Enas"
matcher = /d/gi
Yet when I run the matcher.test function back to back I get true for the first run and false for the second run.
matcher.test(item) // true
matcher.test(item) // false
If I use a regexp literal such as
/d/gi.test("Douglas Enas")
and run it back to back in chrome I get true both times. Is there an explanation for this?
Sample of a back to back run in chrome console creating a regexp object using constructor
matcher = new RegExp("d","gi")
/d/gi
matcher.test("Douglas Enas")
true
matcher.test("Douglas Enas")
false
matcher
/d/gi
Sample using back to back calls on literal
/d/gi.test("Douglas Enas")
true
/d/gi.test("Douglas Enas")
true
The reason for this question if because using the RegExp constructor and the test function against a list of values I'm losing matches... However using the literal I'm getting back all the values I expect
UPDATE
var suggestions = [];
////process response
$.each(responseData, function (i, val)
{
suggestions.push(val.desc);
});
var arr = $.grep(suggestions, function(item) {
var matcher = new RegExp("d", "gi");
return matcher.test(item);
});
Moving the creation of the matcher inside the closure included the missing results. the "d" is actually a dynamically created string but I used "d" for simplicity sake. I'm still not sure now creating a new expression every time I do the test when I am iterating over the suggestions array would inadvertently exclude results is a little confusing still, and probably has something to do with the advancement of the match test
From RegExp.test():
test called multiple times on the same global regular expression instance will advance past the previous match.
So basically when you have an instance of RegExp, each call to test advances the matcher. Once you've found the first d, it will look beyond that and try to find another d. Well, there are none anymore, so it returns false.
On the other hand, when you do:
/d/gi.test("Douglas Enas")
You create a new RegExp instance every time on the spot, so it will always find that first d (and thus return true).
According to Mozilla Developer Network,
As with exec (or in combination with it), test called multiple times
on the same global regular expression instance will advance past the
previous match.
https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/RegExp/test
I can't find the link ATM, but as I recall, this is a known issue with the test method in combination with a g pattern: the match position isn't "forgotten" somehow. Either drop the global flag and/or use the .match method, and it'll work just fine.

A unary operator function expression is ~5261% faster than a brackets function expression in Firefox

In this test, I am looking at two different ways of function expressions; using the exclamation point unary operator and using brackets.
The following are the 2 tests:
var f = !function() {};
var f = (function() {});
Given the results below, I was intrigued when I saw that the unary operator test was ~5261% faster than the brackets test in Firefox.
What sort of optimization is going on that amounts to such a significant increase in performance in Firefox, dwarfing the other browsers?
The first one is resulting in a boolean, and the second one a function. There doesn't seem to be much real-world significance to your test.
"What sort of optimization is going on that amounts to such a significant increase in performance in Firefox, dwarfing the other browsers?"
I suppose Firefox has an optimization that avoids creation of the function object since it is never actually used, but that's just a guess.
Here's an updated jsPerf. This one adds two tests that create boolean values. Notice that they're very close to the "Exclamation" test in Firefox.
This lends support to the idea that Firefox has this particular optimization.
If you put this in a more "real-life" example, the difference is no longer really imporant.
Those expressions are most likely used to create an outer function context to encapsulate your code from the global context, like
!function() {
}();
(function() {
}());
See results for that here: http://jsperf.com/function-expressions/2
You actually double the work for the engine there. But assigning a function to a variable you implicitly create a function expression
var f = function() {};
Also applying the ! operator, is unnecessary work.
You're getting somewhere around 1e9 operations per second on the "exclamation" case. Your CPU probably does somewhere around 1-4 billion clock ticks per second. so that case is taking around 1-4 clock ticks.
What that means is that the entire thing got optimized away to "f = false" by the JIT. Most likely because type inference detected that unary "!" is always followed by an object, and optimized it to "false".
One reason it's slower in Chrome is that in Chrome there are objects for which unary "!" returns true, so the optimization I describe above is invalid there.

How often does JavaScript recompile regex literals in functions?

Given this function:
function doThing(values,things){
var thatRegex = /^http:\/\//i; // is this created once or on every execution?
if (values.match(thatRegex)) return values;
return things;
}
How often does the JavaScript engine have to create the regex? Once per execution or once per page load/script parse?
To prevent needless answers or comments, I personally favor putting the regex outside the function, not inside. The question is about the behavior of the language, because I'm not sure where to look this up, or if this is an engine issue.
EDIT:
I was reminded I didn't mention that this was going to be used in a loop. My apologies:
var newList = [];
foreach(item1 in ListOfItems1){
foreach(item2 in ListOfItems2){
newList.push(doThing(item1, item2));
}
}
So given that it's going to be used many times in a loop, it makes sense to define the regex outside the function, but so that's the idea.
also note the script is rather genericized for the purpose of examining only the behavior and cost of the regex creation
From Mozilla's JavaScript Guide on regular expressions:
Regular expression literals provide compilation of the regular expression when the script is evaluated. When the regular expression will remain constant, use this for better performance.
And from the ECMA-262 spec, ยง7.8.5 Regular Expression Literals:
A regular expression literal is an input element that is converted to a RegExp object (see 15.10) each time the literal is evaluated.
In other words, it's compiled once when it's evaluated as a script is first parsed.
It's worth noting also, from the ES5 spec, that two literals will compile to two distinct instances of RegExp, even if the literals themselves are the same. Thus if a given literal appears twice within your script, it will be compiled twice, to two distinct instances:
Two regular expression literals in a program evaluate to regular expression objects that never compare as === to each other even if the two literals' contents are identical.
...
... each time the literal is evaluated, a new object is created as if by the expression new RegExp(Pattern, Flags) where RegExp is the standard built-in constructor with that name.
The provided answers don't clearly distinguish between two different processes behind the scene: regexp compilation and regexp object creation when hitting regexp object creation expression.
Yes, using regexp literal syntax, you're gaining the performance benefit of one time regexp compilation.
But if your code executes in ES5+ environment, every time the code path enters the doThing() function in your example, it actually creates a new RegExp object, though, without need to compile the regexp again and again.
In ES5, literal syntax produces a new RegExp object every time code path hits expression that creates a regexp via literal:
function getRE() {
var re = /[a-z]/;
re.foo = "bar";
return re;
}
var reg = getRE(),
re2 = getRE();
console.log(reg === re2); // false
reg.foo = "baz";
console.log(re2.foo); // "bar"
To illustrate the above statements from the point of actual numbers, take a look at the performance difference between storedRegExp and inlineRegExp tests in this jsperf.
storedRegExp would be about 5 - 20% percent faster across browsers than inlineRegExp - the overhead of creating (and garbage collecting) a new RegExp object every time.
Conslusion:
If you're heavily using your literal regexps, consider caching them outside the scope where they are needed, so that they are not only be compiled once, but actual regexp objects for them would be created once as well.
There are two "regular expression" type objects in javascript.
Regular expression instances and the RegExp object.
Also, there are two ways to create regular expression instances:
using the /regex/ syntax and
using new RegExp('regex');
Each of these will create new regular expression instance each time.
However there is only ONE global RegExp object.
var input = 'abcdef';
var r1 = /(abc)/;
var r2 = /(def)/;
r1.exec(input);
alert(RegExp.$1); //outputs 'abc'
r2.exec(input);
alert(RegExp.$1); //outputs 'def'
The actual pattern is compiled as the script is loaded when you use Syntax 1
The pattern argument is compiled into an internal format before use. For Syntax 1, pattern is compiled as the script is loaded. For Syntax 2, pattern is compiled just before use, or when the compile method is called.
But you still could get different regular expression instances each method call. Test in chrome vs firefox
function testregex() {
var localreg = /abc/;
if (testregex.reg != null){
alert(localreg === testregex.reg);
};
testregex.reg = localreg;
}
testregex();
testregex();
It's VERY little overhead, but if you wanted exactly one regex, its safest to only create one instance outside of your function
The regex will be compiled every time you call the function if it's not in literal form.
Since you are including it in a literal form, you've got nothing to worry about.
Here's a quote from websina.com:
Regular expression literals provide compilation of the regular expression when the script is evaluated. When the regular expression will remain constant, use this for better performance.
Calling the constructor function of the RegExp object, as follows:
re = new RegExp("ab+c")
Using the constructor function provides runtime compilation of the regular expression. Use the constructor function when you know the regular expression pattern will be changing, or you don't know the pattern and are getting it from another source, such as user input.

Categories

Resources