1. 程式人生 > >詳解JavaScript中的replace()函式

詳解JavaScript中的replace()函式

  Javascript中字串物件有一個方法replace(),它的作用非常強大。這裡把它的用法整理一下。

  一、方法簡介

  該方法的簽名是:replace([RegExp|String],[String|Function])。

  該方法 返回一個新的字串,但並不改變字串本身。

  該方法接收2個引數,第一個引數可以是字串,也可以是一個正則表示式;第二個引數可以是一個字串,也可以是一個函式。其中第2個引數如果是函式,那麼用起來是十分強大而且靈活的,不過相對來說也比較難掌握。下面就其用法進行詳細說明。

  二、基本用法  

  假如我們有一個字串中出現了錯別字”背景“,需要用”北京“來替換,那麼我們可以如下搞定:

var str = "我愛背景天安門";
str = str.replace("背景","北京");
console.log(str); //輸出結果:我愛北京天安門

   這個用法跟C#中的replace()用法別無二致,大家一看就明白。

  但是這個用法有個“坑”,看下例:

var str = "我愛背景天安門,但是背景霧霾太嚴重";
str = str.replace("背景","北京");
console.log(str); //輸出結果:我愛北京天安門,但是背景霧霾太嚴重

  我們發現,如果字串str中有多個待替換的子串,比如本例中的“背景”,出現了2次,那麼replace()方法只能給我們用目標字串(北京)替換掉第1次出現的"背景"。如果想把所有的"背景"都給替換了,就必須呼叫多次。這是我們不能接受的,因為我們無法預知原始字串中出現了多少個錯別字。

  幸好,replace()方法還提供了第二種用法,就是使用正則表示式。

  三、使用正則表示式

var str = "我愛背景天安門,但是背景霧霾太嚴重";
str = str.replace(/背景/g,"北京");
console.log(str); //輸出結果:我愛北京天安門,但是北京霧霾太嚴重

  這裡需要說明的是,str.replace(/背景/g,"北京")的第一個引數  ”/背景/g“ 是一個正則表示式,使用/  /的正則寫法是JavaScript中正則表示式的字面量寫法。在此處,正則表示式的末尾有個g,它表示match源字串str中所有匹配項。這裡如果沒有g,那麼也只能匹配到第一個錯別字”背景“,只有加了這個g,才能匹配到所有的”背景“。

  四、正則表示式+function的用法

  以上的用法還是比較直觀的,但是能實現的功能也比較簡單,如果需要做一些複雜的字串替換運算,那麼就需要使用較為高階(複雜)的用法,就是  正則+function  的用法。說白了就是第一引數傳一個正則表示式,我們下面稱之為RegArg;第二個引數給一個函式,我們下面稱之為FuncArg。這也是replace()的核心用法。

  討論這個用法的前提,就是需要對JavaScript的Sring.match()有充分理解。不瞭解的,可以參考 詳解正則表示式匹配方法match() 

  這個用法的本質就是:對str使用RegArg做match()匹配,如果匹配到多項結果(比如使用了全域性匹配g,或者分組),那麼每一個匹配結果都將執行一次FuncArg函式,並且用該函式的返回值替代源字串中的匹配項。

  這個用法複雜就複雜在這個FuncArg有不同的使用方式,下面做詳細介紹。

  4.1簡單用法,正則表示式不使用分組

var str = '我愛背景天安門,但是背景霧霾太嚴重';
var re = str.replace(/背景/, function(){
    console.log(arguments);
    return '北京';
})

   輸出結果是

  

  解析:

  1. 本例的意圖是:把源字串中的‘背景’,替換為‘北京’。
  2. 正則表示式沒有使用全域性匹配符g,所以只替換了源字串中第一個‘背景’子串,FuncArg只執行了一次
  3. 前面都不難理解,關鍵是:replace()函式,當第二個引數是一個函式時,這個函式是有引數的,而且這些引數是預設的。需要說明的是,當前這個例子比較簡單,所以只有3個匹配項,
    • arguments[0]是匹配到的子字串;
    • arguments[1]是匹配到的子串的索引位置
    • arguments[2]是源字串本身

   4.本例如果想替換所有的‘背景’為‘北京’,只需要讓正則表示式後加個g。程式碼我就不貼出來了,只貼出來輸出結果。

  

  我們可以看到,輸出了2個Arguments,因為我們使用全域性匹配g後,會match到2個項,所以就執行了2次function。第一個跟前邊一樣,第二個arugments的索引位置是10,因為源字串中第二個‘背景’的索引是10.

  如果就做這樣的例子,你可能覺得還不如直接使用: str = str.replace(/背景/g,"北京"); 

  那麼就再來一個例子,看看使用function做引數的好處。

  這個例子的意圖是,把捐款是100元以下的金額數用‘**’來替換掉。

var txt ='劉菲:50元。張常成:150元。孫玉傑:200元。李明軒:20元。李子豪:1500元。';
var txt = txt.replace(/\d+/g, function(){
    console.log(arguments);
    return arguments[0].length > 2 ? arguments[0] : '**';
})
console.log(txt);

  輸出的結果是:

   

  我們可以看到,劉菲和李明軒的捐款被替換成 ** 了。

  4.2複雜用法,正則使用分組  

var txt ='劉菲:5萬。張常成:5000元。孫玉傑:2000元。李明軒:20萬。李子豪:8500元。';
var txt = txt.replace(/(\d+)(萬)/g, function(){
    console.log(arguments);
})
  1. 這個例子的意圖是:把所有以“萬”為單位的捐款,其金額改為‘元’。比如 :4萬,改為40000元
  2. 這個例子只寫了一半,目的是要研究下在正則表示式使用了分組以後arguments的變化
  3. 輸出結果是:  

  仔細觀察arguments結果集,明顯比上一個例子多出2項。這些項分別是:  

  • arguments[0]是匹配到的子字串;
  • arguments[1]是匹配到的第1個分組項
  • arguments[2]是匹配到的第2個分組項
  • arguments[3]是匹配到的字串的索引位置
  • arguments[4]是源字串本身

  這裡正則有2個分組,所以多了匹配到的2個分組項;同理,如果有3個分組,就會多出3個匹配到的分組項。

  看懂了這個回撥函式的arguments各項代表的意義,下面,我們就來真正的解決問題。  

var txt ='劉菲:5萬。張常成:5000元。孫玉傑:2000元。李明軒:20萬。李子豪:8500元。';
var txt = txt.replace(/(\d+)(萬)/g, function(){
    console.log(arguments);
    return arguments[1] + '0000' + '元';
})
console.log(txt);

  輸出結果是: