Extract重構(gòu)

2018-10-22 11:06 更新

Extract重構(gòu)

IntelliJ IDEA提供各種Extract重構(gòu),以引入?yún)?shù),變量,常量,字段,方法和函數(shù)。要運(yùn)行任何這些重構(gòu),請選擇要重構(gòu)的表達(dá)式并選擇:Refactor|提取|<target>。您可以選擇整個(gè)表達(dá)式或?qū)⒐鈽?biāo)放在其中的任何位置,IntelliJ IDEA將幫助您進(jìn)行選擇。

Extract Parameter

使用Extract Parameter(提取參數(shù))重構(gòu)將函數(shù)調(diào)用中的表達(dá)式替換為參數(shù)。IntelliJ IDEA將相應(yīng)地更新聲明和函數(shù)調(diào)用。新參數(shù)的默認(rèn)值可以在函數(shù)體內(nèi)初始化或通過函數(shù)調(diào)用傳遞。

假設(shè)您在函數(shù)calculate_sum(i)中有一段硬編碼1的代碼。使用Extract Parameter重構(gòu),您可以使用i2參數(shù)替換此硬編碼1。新i2參數(shù)可以作為可選項(xiàng)或根據(jù)需要提取。

示例1:提取可選參數(shù)

提取新參數(shù)i2作為可選參數(shù)。新參數(shù)在主體calculate_sum(i)中初始化,并且show_sum()中calculate_sum(i)調(diào)用不會(huì)更改。

function calculate_sum(i) {
    alert('Adding ' + 1 + ' to ' + i);
    return  1 + i;
}

function show_sum() {
    alert('Result: ' + calculate_sum(5));
}
function calculate_sum(i, i2) {
    i2 = i2 || 1;
    alert('Adding ' + i2 + ' to ' + i);
    return i2 + i;
}

function show_sum() {
    alert('Result: ' + calculate_sum(5));
}

示例2:提取所需參數(shù)

提取新參數(shù)i2作為必需參數(shù),相應(yīng)地更改show_sum()中calculate_sum(i)調(diào)用。

function calculate_sum(i) {
    alert('Adding ' + 1 + ' to ' + i);
    return 1 + i;
}

function show_sum() {
    alert('Result: ' + calculate_sum(5));
}
function calculate_sum(i, i2) {
    alert('Adding ' + i2 + ' to ' + i);
    return i2 + i;
}

function show_sum() {
    alert('Result: ' + calculate_sum(5, 1));
}

提取參數(shù)的操作如下:

  1. 在編輯器中,將光標(biāo)放在要轉(zhuǎn)換為參數(shù)的表達(dá)式中,然后按Ctrl+Alt+P,或在上下文菜單或主菜單上選擇:Refactor|提取|參數(shù)。
  2. 如果在當(dāng)前光標(biāo)位置中檢測到多個(gè)表達(dá)式,請?jiān)凇氨磉_(dá)式”列表中選擇所需的表達(dá)式。
    ws_js_extract_parameter_select_expression.png
  3. 如果找到多個(gè)選定表達(dá)式,請選擇“僅替換此事件”或“找到多個(gè)匹配項(xiàng)”彈出菜單中的“替換所有匹配項(xiàng)”。
    ws_js_extract_parameter_multiple_occurrences.png
    最后,出現(xiàn)用于配置重構(gòu)的彈出窗口。
    ws_js_extract_parameter_specify_parameter_name_and_type.png
  4. 選擇Generate JSDoc以生成JSDoc注釋塊。如果您需要指定自定義默認(rèn)參數(shù)值,這可能會(huì)有所幫助。從JSDoc官方網(wǎng)站了解更多信息。
  5. 選擇新參數(shù)的類型(可選或必需)并指定其默認(rèn)值(如果適用):
    • 如果選中“可選參數(shù)”復(fù)選框,則將使用函數(shù)體中的默認(rèn)值初始化該參數(shù)。
    • 如果清除“可選參數(shù)”復(fù)選框,則默認(rèn)參數(shù)值將通過現(xiàn)有函數(shù)調(diào)用傳遞。所有函數(shù)調(diào)用都將根據(jù)新的函數(shù)簽名進(jìn)行更改,并且參數(shù)初始化將添加到函數(shù)體中。
    最初,IntelliJ IDEA接受調(diào)用重構(gòu)作為默認(rèn)值的表達(dá)式。在大多數(shù)情況下,您無需更改它。如果仍然需要,請以格式@param <parameter name> - <default value>在JSDoc注釋中指定另一個(gè)默認(rèn)值。
  6. 通過在彈出列表中雙擊建議的參數(shù)名稱,或者在文本框中使用紅色畫布指定自定義名稱,接受其中一個(gè)建議的參數(shù)名稱。準(zhǔn)備好后按“Enter”。
    ws_js_extract_parameter_result.png
    另請注意,在ES6代碼中,將應(yīng)用新的默認(rèn)函數(shù)參數(shù)語法function calculate_sum(i, i2 = 1) 而不是i2 = i2 || 1;。從https://developer.mozilla.org網(wǎng)站了解有關(guān)默認(rèn)函數(shù)參數(shù)的更多信息 。

選擇重構(gòu)模式:

您可以如上所述在編輯器中(在in-place模式下)提取參數(shù), 或使用“提取參數(shù)(Extract Parameter )”對(duì)話框。這兩種方法相似,區(qū)別如下:

  • 預(yù)覽重構(gòu)的結(jié)果。在對(duì)話框中,可以單擊“預(yù)覽”并在“查找”工具窗口的專用選項(xiàng)卡中檢查預(yù)期的更改。在in-place模式下,此功能不可用。
  • 指定默認(rèn)參數(shù)值。在對(duì)話框中,IntelliJ IDEA會(huì)在“值”字段中建議默認(rèn)參數(shù)值,您可以在其中接受建議或指定其他值。在in-place模式下,IntelliJ IDEA將調(diào)用重構(gòu)的表達(dá)式視為默認(rèn)參數(shù)值。要指定另一個(gè)值,您必須使用JSDoc注釋塊。

默認(rèn)情況下,IntelliJ IDEA在in-place模式下運(yùn)行Extract Parameter重構(gòu)。要使用“提取參數(shù)”對(duì)話框,請?jiān)凇霸O(shè)置/首選項(xiàng)”對(duì)話框(Ctrl+Alt+S)中單擊:編輯器|常規(guī)。在打開的“常規(guī)”頁面上,清除“重構(gòu)”區(qū)域中的“啟用in-place模式”復(fù)選框。

Extract Variable

使用Extract Variable(提取變量)重構(gòu)將表達(dá)式替換為函數(shù)范圍的變量(var),塊范圍的變量(let)或常量。這種重構(gòu)使您的源代碼更易于閱讀和維護(hù)。它還可以幫助您避免使用硬編碼常量,而無需對(duì)其值或目的進(jìn)行任何解釋。

假設(shè)您在return語句中有一個(gè)帶有部分硬編碼表達(dá)式的函數(shù):

Parenizor.method('toString', function ()) {
    return '(' + this.getValue() + ')';
}

使用Extract Variable重構(gòu),您可以使用變量替換'(' + this.getValue() + ')'表達(dá)式,例如string。提取變量的范圍取決于其聲明(var或let)中使用的語句以及聲明新變量的上下文(函數(shù)內(nèi)部或外部)。

示例1:使用let語句聲明提取塊范圍的變量

從return語句中的'(' + this.getValue() + ')'表達(dá)式中提取變量。新變量使用let語句在Parenizor.method('toString', function ())內(nèi)部聲明。 


Parenizor.method('toString', function ()) {
    return '(' + this.getValue() + ')';
}


Parenizor.method('toString', function ()) {
    let string = '(' + this.getValue() + ')';
    return string;
}

示例2:提取變量并在任何函數(shù)外聲明它

變量appName從navigator.appName表達(dá)式中提取并在任何函數(shù)之外使用var語句聲明。


var browserName = "N/A";
if (navigator.appName.indexOf("Netscape") != -1) {
    browserName = "NS";
} else if (navigator.appName.indexOf("Microsoft") != -1) {
    browserName = "MSIE";
} else if (navigator.appName.indexOf("Opera") != -1) {
    browserName = "O";
}


var browserName = "N/A";
var appName = navigator.appName;
if (appName.indexOf("Netscape") != -1) {
    browserName = "NS";
} else if (appName.indexOf("Microsoft") != -1) {
    browserName = "MSIE";
} else if (appName.indexOf("Opera") != -1) {
    browserName = "O";
}

提取變量的操作如下所示:

  1. 在編輯器中,選擇要轉(zhuǎn)換為變量的表達(dá)式,然后按Ctrl+Alt+V,或在上下文菜單或主菜單上選擇:Refactor |提取|變量。
  2. 如果在當(dāng)前光標(biāo)位置中檢測到多個(gè)表達(dá)式,請?jiān)凇氨磉_(dá)式”列表中選擇所需的表達(dá)式。
    ws_js_refactoring_extract_variable_inplace_select_expression.png
  3. 如果找到多個(gè)選定表達(dá)式,請選擇“僅替換此事件”或“找到多個(gè)匹配項(xiàng)”彈出菜單中的“替換所有匹配項(xiàng)”。
    ws_js_refactoring_extract_variable_inplace_multiple_occurrences.png
    最后,出現(xiàn)用于配置重構(gòu)的彈出窗口。
  4. 在彈出菜單中,選擇要在新變量聲明中使用的語句:
    • 選擇var以引入函數(shù)范圍的變量。
    • 選擇let以引入塊范圍的變量,請參閱上面的示例2。
    • 選擇const來引入常量。
    ws_js_refactoring_extract_variable_inplace_choose_scope_type.png
  5. 通過在彈出列表中雙擊建議的變量名稱或在文本框中指定自定義名稱來接受其中一個(gè)建議變量名稱。準(zhǔn)備好后按“Enter”。

選擇重構(gòu)模式

您可以如上所述在編輯器中(在in-place模式下)提取變量, 或使用“提取變量”對(duì)話框。默認(rèn)情況下,IntelliJ IDEA在in-place模式下運(yùn)行Extract Variable重構(gòu)。要使用“提取變量”對(duì)話框,請?jiān)凇霸O(shè)置/首選項(xiàng)”對(duì)話框(Ctrl+Alt+S)中單擊:編輯器|常規(guī)。在打開的“常規(guī)”頁面上,清除“重構(gòu)”區(qū)域中的“啟用in-place模式”復(fù)選框。

Extract Field

在Extract Field重構(gòu)宣布一個(gè)新的字段,并使用選定的表達(dá)對(duì)其進(jìn)行初始化。原始表達(dá)式將替換為字段的用法。

在下面的示例中,提取相同的_calcArea字段。這些示例說明了初始化提取字段的三種不同方法。

示例1:在封閉方法中初始化提取的字段


class Rectangle {
    constructor(height, width) {
        this.height = height;
        this.width = width;
    }

    get area() {
        return this.calcArea();
    }

    calcArea() {
        return this.height * this.width;
    }
}


class Rectangle {
    constructor(height, width) {
        this.height = height;
        this.width = width;
    }

    _calcArea;

    get area() {
        this._calcArea = this.calcArea();
        return this._calcArea;
    }

    calcArea() {
        return this.height * this.width;
    }
}

示例2:提取的字段在其聲明中初始化


class Rectangle {
    constructor(height, width) {
        this.height = height;
        this.width = width;
    }

    get area() {
        return this.calcArea();
    }

    calcArea() {
        return this.height * this.width;
    }
}


class Rectangle {
    constructor(height, width) {
        this.height = height;
        this.width = width;
    }

    _calcArea = this.calcArea();

    get area() {
        return this._calcArea;
    }

    calcArea() {
        return this.height * this.width;
    }
}

示例3:提取的字段在類的構(gòu)造函數(shù)中初始化


class Rectangle {
    constructor(height, width) {
        this.height = height;
        this.width = width;
    }

    get area() {
        return this.calcArea();
    }

    calcArea() {
        return this.height * this.width;
    }
}


class Rectangle {
    constructor(height, width) {
        this._calcArea = this.calcArea();
        this.height = height;
        this.width = width;
    }

    _calcArea;

    get area() {
        return this._calcArea;
    }

    calcArea() {
        return this.height * this.width;
    }
}

提取字段的操作如下:

  1. 在編輯器中,選擇要轉(zhuǎn)換為字段的表達(dá)式,然后按Ctrl+Alt+F,或從上下文菜單或主菜單上選擇:Refactor|提取|字段?!疤崛∽侄巍睂?duì)話框?qū)⒋蜷_。
  2. 從列表中接受一個(gè)建議的名稱或鍵入自定義名稱。
  3. 選擇新字段的初始化位置:
    • 目前的方法,見上面的例1。
    • 字段聲明,請參見上面的示例2。
    • 類構(gòu)造函數(shù),請參見上面的示例3。
    ws_js_extract_field_dialog_1.png

Extract Method

該Extract Method重構(gòu),您可以使用提取的代碼創(chuàng)建命名方法或函數(shù)。當(dāng)調(diào)用Extract Method重構(gòu)時(shí),IntelliJ IDEA會(huì)檢測作為所選代碼片段輸入的變量以及作為其輸出的變量。檢測到的輸出變量用作提取的方法或函數(shù)的返回值。

在下面的示例中,從c = a + b;表達(dá)式中提取函數(shù)。

實(shí)例1:從另一個(gè)函數(shù)內(nèi)的表達(dá)式提取一個(gè)全局范圍函數(shù)

調(diào)用重構(gòu)的c = a + b;表達(dá)式,位于MyFunction()函數(shù)內(nèi)部。選擇全球目標(biāo)范圍。

例1.1:生成函數(shù)聲明


function MyFunction(a,b) {
    c = a + b;
    return (c * c);
}
result = MyFunction(4,6);
document.write(result);


function extracted(a, b) {
    c = a + b;
}

function MyFunction(a,b) {
    extracted(a, b);
    return (c * c);
}
result = MyFunction(4,6);
document.write(result);

例1.2:提取的函數(shù)在表達(dá)式中聲明


function MyFunction(a,b) {
    c = a + b;
    return (c * c);
}
result = MyFunction(4,6);
document.write(result);


let extracted = function (a, b) {
    c = a + b;
};

function MyFunction(a,b) {
    extracted(a, b);
    return (c * c);
}
result = MyFunction(4,6);
document.write(result);

實(shí)例2:從任何函數(shù)之外的表達(dá)式提取一個(gè)全局范圍函數(shù)

調(diào)用重構(gòu)的c = a + b;表達(dá)式,位于任何函數(shù)之外。因此,無法選擇目標(biāo)范圍。

例2.1:生成函數(shù)聲明


c = a + b;


function extracted() {
    c = a + b;
}

extracted();

例2.2:提取的函數(shù)在表達(dá)式中聲明


c = a + b;


let extracted = function () {
    c = a + b;
};
extracted();

示例3:在封閉函數(shù)內(nèi)提取具有定義的函數(shù)

調(diào)用重構(gòu)的c = a + b;表達(dá)式,位于MyFunction()函數(shù)內(nèi)部。選擇函數(shù)MyFunction目標(biāo)范圍。


function MyFunction(a,b) {
    c = a + b;
    return (c * c);
}
result = MyFunction(4,6);
document.write(result);


function MyFunction(a,b) {
    function extracted() {
        c = a + b;
    }

    extracted();
    return (c * c);
}
result = MyFunction(4,6);
document.write(result);

提取函數(shù)的操作如下:

  1. 在編輯器中,選擇要轉(zhuǎn)換為函數(shù)的代碼片段,然后按Ctrl+Alt+M,或從上下文菜單或主菜單上選擇:Refactor|提取|方法。
  2. 如果所選表達(dá)式位于函數(shù)內(nèi),請從彈出列表中選擇目標(biāo)范圍:
    • 如果選擇全局,則提取的函數(shù)將在任何函數(shù)外聲明。參見上面的示例1。
    • 要在當(dāng)前封閉函數(shù)內(nèi)定義提取的函數(shù),請選擇function <current enclosing function name>。參見上面的實(shí)施例3。
      a685a45a-2bf8-46cb-85ee-63e7b26ff646
  3. 要打開包含更多選項(xiàng)的“提取函數(shù)”對(duì)話框,請?jiān)侔匆淮蜟trl+Alt+M。在此對(duì)話框中,您可以選擇是通過生成的函數(shù)聲明還是在表達(dá)式內(nèi)聲明提取的函數(shù) 。見上面的例子。
    30f852de-4c11-4acf-a47b-6dae6a0e0017

如何在默認(rèn)情況下打開“Extract Function”對(duì)話框:

  • 在“設(shè)置/首選項(xiàng)”對(duì)話框(Ctrl+Alt+S)中,單擊:編輯器|常規(guī)。在打開的“常規(guī)”頁面上,清除“重構(gòu)”區(qū)域中的“啟用in-place模式”復(fù)選框。

Extract Superclass

該Extract Superclass(提取超類)重構(gòu)創(chuàng)建基于當(dāng)前類的成員一個(gè)新的抽象類。創(chuàng)建的類會(huì)自動(dòng)擴(kuò)展。

假設(shè)您有一個(gè)類AccountingDepartment,并且您希望來自它的printName()方法能夠重新使用。

class AccountingDepartment {
    name;

    printName() {
        console.log("Department name: " + this.name);
    }

    printMeeting() {
        console.log("The Accounting Department meets each Monday at 10am.");
    }

    generateReports() {
        console.log("Generating accounting reports...");
    }
}

您可以提取超類Department并在其中包含printName該Name字段。

class Department {
    name;

    printName() {
        console.log("Department name: " + this.name);
    }
}

class AccountingDepartment extends Department {
    printMeeting() {
        console.log("The Accounting Department meets each Monday at 10am.");
    }

    generateReports() {
        console.log("Generating accounting reports...");
    }
}

提取超類的操作如下:

  1. 將光標(biāo)放在要從中提取超類的類的任何位置。
  2. 在主菜單或上下文菜單上選擇:Refactor|提取|超類?!疤崛〕悺睂?duì)話框?qū)⒋蜷_。
  3. 指定新超類的名稱,然后選擇要包含在其中的類成員旁邊的復(fù)選框。(可選)標(biāo)記要進(jìn)行抽象的成員。
  4. 在“目標(biāo)文件”字段中,指定新類所在文件的位置。默認(rèn)情況下,該字段顯示調(diào)用重構(gòu)的當(dāng)前文件的路徑。
  5. 選擇Extract Superclass。IntelliJ IDEA創(chuàng)建一個(gè)新類并使用extends標(biāo)記源類。
    要?jiǎng)?chuàng)建超類并使用對(duì)方法參數(shù)中超類的引用替換對(duì)源類的引用,請選擇Extract superclass并盡可能使用它。IntelliJ IDEA在“查找”工具窗口的“重構(gòu)預(yù)覽”窗格中顯示建議的更改。

Extract Vue Component

Extract Vue Component(提取Vue組件)重構(gòu)允許您從現(xiàn)有組件中提取新的Vue.js組件,而無需任何復(fù)制和粘貼。請注意,此重構(gòu)僅適用于in-place模式,因此請確保在“編輯器:常規(guī)”頁面上選中“啟用in-place模式”復(fù)選框 。

提取Vue組件的操作方法如下:

  1. 選擇要提取的模板片段,然后在主菜單或選擇的上下文菜單中選擇:Refactor|提取|提取Vue組件。
  2. 輸入新組件的名稱。如果此名稱已被使用或無效,則IntelliJ IDEA會(huì)顯示警告。否則,將創(chuàng)建一個(gè)新的單文件組件并將其導(dǎo)入父組件。
以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)