You can access capturing groups like this:
var myString = "something format_abc";
var myRegexp = /(?:^|\s)format_(.*?)(?:\s|$)/g;
var myRegexp = new RegExp("(?:^|\s)format_(.*?)(?:\s|$)", "g");
var match = myRegexp.exec(myString);
console.log(match[1]); // abc
And if there are multiple matches you can iterate over them:
var myString = "something format_abc";
var myRegexp = new RegExp("(?:^|\s)format_(.*?)(?:\s|$)", "g");
match = myRegexp.exec(myString);
while (match != null) {
// matched text: match[0]
// match start: match.index
// capturing group n: match[n]
console.log(match[0])
match = myRegexp.exec(myString);
}
Edit: 2019-09-10
As you can see the way to iterate over multiple matches was not very intuitive. This lead to the proposal of the String.prototype.matchAll
method. This new method is expected to ship in the ECMAScript 2020 specification. It gives us a clean API and solves multiple problems. It has been started to land on major browsers and JS engines as Chrome 73+ / Node 12+ and Firefox 67+.
The method returns an iterator and is used as follows:
const string = "something format_abc";
const regexp = /(?:^|\s)format_(.*?)(?:\s|$)/g;
const matches = string.matchAll(regexp);
for (const match of matches) {
console.log(match);
console.log(match.index)
}
As it returns an iterator, we can say it's lazy, this is useful when handling particularly large numbers of capturing groups, or very large strings. But if you need, the result can be easily transformed into an Array by using the spread syntax or the Array.from
method:
function getFirstGroup(regexp, str) {
const array = [...str.matchAll(regexp)];
return array.map(m => m[1]);
}
// or:
function getFirstGroup(regexp, str) {
return Array.from(str.matchAll(regexp), m => m[1]);
}
In the meantime, while this proposal gets more wide support, you can use the official shim package.
Also, the internal workings of the method are simple. An equivalent implementation using a generator function would be as follows:
function* matchAll(str, regexp) {
const flags = regexp.global ? regexp.flags : regexp.flags + "g";
const re = new RegExp(regexp, flags);
let match;
while (match = re.exec(str)) {
yield match;
}
}
A copy of the original regexp is created; this is to avoid side-effects due to the mutation of the lastIndex
property when going through the multple matches.
Also, we need to ensure the regexp has the global flag to avoid an infinite loop.
I'm also happy to see that even this StackOverflow question was referenced in the discussions of the proposal.
It's actually not too complicated...
Say you're on domain example.com
, and you want to make a request to domain example.net
. To do so, you need to cross domain boundaries, a no-no in most of browserland.
The one item that bypasses this limitation is <script>
tags. When you use a script tag, the domain limitation is ignored, but under normal circumstances, you can't really do anything with the results, the script just gets evaluated.
Enter JSONP
. When you make your request to a server that is JSONP enabled, you pass a special parameter that tells the server a little bit about your page. That way, the server is able to nicely wrap up its response in a way that your page can handle.
For example, say the server expects a parameter called callback
to enable its JSONP capabilities. Then your request would look like:
http://www.example.net/sample.aspx?callback=mycallback
Without JSONP, this might return some basic JavaScript object, like so:
{ foo: 'bar' }
However, with JSONP, when the server receives the "callback" parameter, it wraps up the result a little differently, returning something like this:
mycallback({ foo: 'bar' });
As you can see, it will now invoke the method you specified. So, in your page, you define the callback function:
mycallback = function(data){
alert(data.foo);
};
And now, when the script is loaded, it'll be evaluated, and your function will be executed. Voila, cross-domain requests!
It's also worth noting the one major issue with JSONP: you lose a lot of control of the request. For example, there is no "nice" way to get proper failure codes back. As a result, you end up using timers to monitor the request, etc, which is always a bit suspect. The proposition for JSONRequest is a great solution to allowing cross domain scripting, maintaining security, and allowing proper control of the request.
These days (2015), CORS is the recommended approach vs. JSONRequest. JSONP is still useful for older browser support, but given the security implications, unless you have no choice CORS is the better choice.
Best Answer
Visibility:
While your angularjs is bootstrapping, the user might see your placed brackets in the html. This can be handled with
ng-cloak
. But for me this is a workaround, that I don't need to use, if I useng-bind
.Performance:
The
{{}}
is much slower.This
ng-bind
is a directive and will place a watcher on the passed variable. So theng-bind
will only apply, when the passed value does actually change.The brackets on the other hand will be dirty checked and refreshed in every
$digest
, even if it's not necessary.I am currently building a big single page app (~500 bindings per view). Changing from {{}} to strict
ng-bind
did save us about 20% in everyscope.$digest
.Suggestion:
If you use a translation module such as angular-translate, always prefer directives before brackets annotation.
{{'WELCOME'|translate}}
=><span ng-translate="WELCOME"></span>
If you need a filter function, better go for a directive, that actually just uses your custom filter. Documentation for $filter service
UPDATE 28.11.2014 (but maybe off the topic):
In Angular 1.3x the
bindonce
functionality was introduced. Therefore you can bind the value of an expression/attribute once (will be bound when != 'undefined').This is useful when you don't expect your binding to change.
Usage: Place
::
before your binding:Example:
ng-repeat
to output some data in the table, with multiple bindings per row. Translation-bindings, filter outputs, which get executed in every scope digest.