Javascript - Wenden Sie die Trimmfunktion auf jede Zeichenfolge in einem Array an

74

Möchten Sie jede Zeichenfolge in einem Array zuschneiden, z

x = [' aa ', ' bb '];

Ausgabe

['aa', 'bb']

Mein erster Versuch ist

x.map(String.prototype.trim.apply)

Es wurde "TypeError: Function.prototype.apply wurde auf undefined aufgerufen, was eine undefinierte und keine Funktion ist" in Chrom.

Dann habe ich es versucht

x.map(function(s) { return String.prototype.trim.apply(s); });

Es klappt. Was ist der Unterschied?

Neuront
quelle

Antworten:

98

String.prototype.trim.applyist die Function.prototype.applyMethode, ohne daran gebunden zu sein trim. mapruft es mit der Zeichenfolge, dem Index und dem Array als Argumente und nichts ( undefined) für das thisArg auf - applyerwartet jedoch, dass es für Funktionen aufgerufen wird:

var apply = String.prototype.trim.apply;
apply.call(undefined, x[0], 0, x) // TypeError

Sie können die trimFunktion als Kontext für Folgendes übergeben call:

[' aa ', ' bb '].map(Function.prototype.call, String.prototype.trim)
// ['aa', 'bb']

Was hier passiert ist

var call = Function.prototype.call,
    trim = String.prototype.trim;
call.call(trim, x[0], 0, x) ≡
      trim.call(x[0], 0, x) ≡
            x[0].trim(0, x); // the arguments don't matter to trim
Bergi
quelle
1
Aha. Ich dachte, fundas hätte die gleiche Bedeutung mit function(x) { return fun(x); }.
Neuront
Dies funktioniert unter IE8 nicht: String.prototype.trim funktioniert nicht mit IE8.
Sachin Kainth
1
@SachinKainth: Bei der Frage geht es nicht um Trimmen, OP geht davon aus, dass es verfügbar ist. Wenn Sie die Snippets in IE8 ausprobieren möchten, müssen Sie natürlich shim trimund map.
Bergi
90

Oder dies kann mit Pfeilfunktionen gelöst werden:

x.map(s => s.trim());
Dominic
quelle
7
Ich schlage vor:let trimedArr = oldArr.map(str => str.trim());
Flame_Phoenix
@ Dominic Ich benutze dies, aber wenn ich meine js dieses Mal minimiere, wird es den Fehler geben, dass ich javascript-minifier.com Website für minify js benutze
Sachin Sarola
1
@SachinSarola sieht so aus, als ob der Minifier mit der modernen JS-Syntax veraltet ist. Es ist sowieso besser, Ihre JS als Teil einer Build-Pipeline zu erstellen und zu minimieren, indem Sie zB Webpack verwenden
Dominic
27

Wenn Sie JQuery verwenden, ist dies ein besserer Weg, da dies auch mit IE8 funktioniert (ich muss IE8 unterstützen):

$.map([' aa ', ' bb ', '   cc '], $.trim);
Sachin Kainth
quelle
32
@ DenysSéguret "If" ist hier das Schlüsselwort.
Brennen
24

Die einfache Variante ohne Abhängigkeiten:

 for (var i = 0; i < array.length; i++) {
     array[i] = array[i].trim()
 }

ES6-Variante:

const newArray = oldArray.map(string => string.trim())

ES6-Funktionsvariante:

const trimmedArray = array => array.map(string => string.trim())
musemind
quelle
15

Machen Sie es einfach:

x.map(function(s) { return s.trim() });

Der Grund, warum der erste nicht funktioniert, ist, dass die Zeichenfolge als Argument an den Rückruf und nicht als Kontext übergeben wird. Wenn Sie kein Argument an übergeben apply, erhalten Sie dieselbe Nachricht, die Sie erhalten hätten

var f = String.prototype.trim.apply; f.call();

Nehmen wir an, Sie sind hauptsächlich zum Spaß nicht zufrieden mit der Tatsache, dass Sie mapden Rückruf auf diese Weise verwenden, und möchten eine Funktion über den Kontext und nicht über das Argument übergeben können.

Dann könnten Sie dies tun:

Object.defineProperty(Array.prototype, "maprec", {
  value: function(cb){
      return this.map(function(v){ return cb.call(v) })
  }
});
console.log([' aa ', ' bb '].maprec(String.prototype.trim)); // logs ["aa", "bb"]

Ich sagte "hauptsächlich zum Spaß", weil das Ändern von Objekten, die Sie nicht besitzen (Arrays Prototyp hier), allgemein als schlechte Praxis angesehen wird. Sie können aber auch eine nützliche Funktion ausführen, indem Sie sowohl das Array als auch den Rückruf als Argumente verwenden.

Denys Séguret
quelle
Du meinst die gleiche Botschaft, die du bekommen String.prototype.trim.apply.call()hättest, nicht wahr?
Butt4cak3
5

Ich habe nur einige Möglichkeiten verglichen, um eine Reihe von Zeichenfolgen zu kürzen, um die kürzeste und schnellste Methode zu erhalten. Wer interessiert ist, hier ist ein Leistungstest auf jsperf: http://jsperf.com/trim-array-of-strings

var chunks = "  .root  ,  .parent  >  .child  ".split(',')
var trimmed1 = chunks.map(Function.prototype.call, String.prototype.trim);
var trimmed2 = chunks.map(function (str) { return str.trim(); });
var trimmed3 = chunks.map(str => str.trim());
var trimmed4 = $.map(chunks, $.trim);

Hinweis: jQuery ist nur hier, um die Anzahl der einzugebenden Zeichen zu vergleichen;)

yckart
quelle
4

Halten Sie es einfach und dumm:

Code

[' aa ', ' b b ', '   c c '].map(i=>i.trim());

Ausgabe

["aa", "b b", "c c"]
Martín Silva
quelle
3

Ausgehend von Bergis perfekter Antwort möchte ich nur hinzufügen, dass Sie für jene Methoden, die kein thisArgument enthalten, möglicherweise den gleichen Job wie folgt erreichen:

var x = [' aa ', ' bb '],
    y = x.map(Function.prototype.call.bind(String.prototype.trim))
Reduzieren
quelle
Hat wirklich gut funktioniert!
Sanjay
1
var x = [" aa ", " bb "];
console.log(x); // => [" aa ", " bb "]

// remove whitespaces from both sides of each value in the array
x.forEach(function(value, index){
  x[index] = value.trim();
});

console.log(x); // => ["aa", "bb"]

Alle gängigen Browser unterstützen dies forEach(), beachten IESie jedoch, dass dies erst ab Version 9 unterstützt wird.

Amr
quelle
-1

Eine weitere ES6-Alternative

const row_arr = ['a ', ' b' , ' c ', 'd'];
const trimed_arr = row_arr.map(str => str.trim());
console.log(trimed_arr); // <== ['a', 'b', 'c', 'd']
gildniy
quelle
array_map ist keine native JS-Funktion und hier nicht definiert. => funktioniert nicht.
musemind
@ Greg Die erste Version dieser Antwort enthielt eine nicht spezifizierte array_map()Methode
musemind
@musemind Mein Fehler - ich hätte mir die Änderungen ansehen sollen
Greg
-1
    ### Code
    <!-- language: lang-js -->

     var x=  [' aa ', ' b b ', '   c c ']
var x = x.split(",");
            x = x.map(function (el) {
                return el.trim();
                console.log(x)

    ### Output
    <!-- language: lang-none -->
        ["aa", "b b", "c c"]     
koteswararao pv
quelle
2
Bitte setzen Sie Ihre Antwort immer in einen Kontext, anstatt nur Code einzufügen. Sehen Sie hier für weitere Details.
gehbiszumeis
1
Bist du dir da sicher? Beim Versuch, Ihren Code zu verwenden, wird der folgende Fehler TypeError: x.split is not a function
Nico Haase
### Versuchen Sie einmal diesen Code .... var x = ['aa', 'bb', 'cc'] var x = x.split (","); x = x.map (Funktion (el) {return el.trim (); console.log (x)
koteswararao pv
### TRY var x = x.split (","); x = x.map (Funktion (el) {return el.trim (); console.log (x)
koteswararao pv