簡體   English   中英

JS從類中調用靜態方法

[英]JS call static method from class

我有一個帶有靜態方法的類:

class User {
  constructor() {
    User.staticMethod();
  }

  static staticMethod() {}
}

對於靜態方法,是否有與 this 等效的方法(即在沒有實例的情況下引用當前類)?

this.staticMethod()

所以我不必寫類名:“用戶”。

來自 MDN 文檔

靜態方法調用直接在類上進行,不能在類的實例上調用。 靜態方法通常用於創建實用程序函數。

有關更多信息,請參閱=> https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes/static

你可以做這樣的事情 => this.constructor.staticMethod()); 調用靜態方法。

class StaticMethodCall {
  constructor() {
    console.log(StaticMethodCall.staticMethod()); 
    // 'static method has been called.' 

    console.log(this.constructor.staticMethod()); 
    // 'static method has been called.' 
  }

  static staticMethod() {
    return 'static method has been called.';
  }
}

而不是這個 User.staticMethod() 你可以添加 this.constructor.staticMethod()

static事物綁定到類而不是實例。 所以你至少必須指定類名。

如果您不想將它們綁定到一個類,請將它們設為全局。

javascript中類的靜態成員被添加為類屬性,您可以使用代碼查看列表

        console.log(Object.getOwnPropertyNames(PaymentStrategy));

和訪問成員只是

const memberFun = PaymentStrategy["memberName"];
//if member is a function then execute 
memberFun();
 //or 
memberFun(data);

例子:

class PaymentStrategy{

    static Card(user){
        console.log(`${user} will pay with a credit card`);
    }

    static PayPal(user){
        console.log(`${user} will pay through paypal`);

    }

    static BKash(user){
        console.log(`${user} will pay through Bkash`);
    }
}

export default PaymentStrategy;

import PaymentStrategy from "./PaymentStrategy";
class Payment{
    constructor(strategy = "BKash"){
        this.strategy = PaymentStrategy[strategy];
        console.log(Object.getOwnPropertyNames(PaymentStrategy));
    }

    changeStrategy(newStratgey){
        this.strategy = PaymentStrategy[newStratgey];

        console.log(`***Payment Strategy Changed***`);
    }

    showPaymentMethod(user){
        this.strategy(user);
    }
}

export default Payment;
```
```
import Payment from "./Payment"


const strategyPattern = (()=>{
    const execute = ()=>{
        const paymentMethod = new Payment();

        paymentMethod.showPaymentMethod("Suru");
        paymentMethod.showPaymentMethod("Nora");

        paymentMethod.changeStrategy("PayPal");

        paymentMethod.showPaymentMethod("Rafiq");
    }
    return{
        execute:execute
    }
})();

export {strategyPattern}
```

@Rohith KP 的答案簡而言之就是解決方案。

如果你想理解它,你需要了解什么是 JavaScript 類“幕后”。

這是在 ES6 之前創建類的方式:

// This is a constructor function that initializes new Range objects. 
// Note that it does not create or return the object. It just initializes this. 
function Range(from, to) { 
    // Store the start and end points (state) of this new range object.
    // These are noninherited properties that are unique to this object. 
    this.from = from; 
    this.to = to; 
} 

// All Range objects inherit from this object. 
// Note that the property name must be "prototype" for this to work. 
// Note that the prototype property is the property of the Range function
Range.prototype = { 
    // create some methods

    // Return true if x is in the range, false otherwise 
    // This method works for textual and Date ranges as well as numeric. 
    includes: function(x) { return this.from <= x && x <= this.to; },

    // A generator function that makes instances of the class iterable. 
    // Note that it only works for numeric ranges. 
    [Symbol.iterator]: function*() { 
        for( let x = Math.ceil( this.from); x <= this.to; x ++) yield x; 
    }, 

    // Return a string representation of the range 
    toString: function() { return "(" + this.from + "..." + this.to + ")"; } 
}; 

// Here are example uses of this new Range class 
let r = new Range(1,3); 
// r inherits from Range.prototype
r.includes(2) // = > true: 2 is in the range 
r.toString() // = > "(1...3)" 
[...r] // => [1, 2, 3]; convert to an array via iterator

本例中的繼承結構圖

因此,類本質上是一個函數,它是其原型對象的公共接口(構造函數)。

let F = function() {}; // This is a function object.
let p = F.prototype; // This is the prototype object associated with F. 
let c = p.constructor; // This is the function associated with the prototype. 
c === F // true

重要的是要理解本示例中定義的類與 ES6 類的工作方式完全相同 在語言中引入“class”關鍵字並沒有改變 JavaScript 基於原型的類的基本性質。

靜態方法

靜態方法被定義為構造函數的屬性而不是原型對象的屬性。

static parse(s) { 
    let matches = s.match(/^\((\d+)\.\.\.(\d+)\)$/); 
    if (!matches) { 
        throw new TypeError(`Cannot parse Range from "${s}".`) 
    } 
    return new Range(parseInt(matches[1]), parseInt(matches[2])); 
}

這段代碼定義的方法是Range.parse(),而不是Range.prototype.parse(),你必須通過構造函數調用它,而不是通過實例:

let r = Range.parse('(1...10)'); // Returns a new Range object 
r.parse('(1...10)'); // TypeError: r.parse is not a function 

您有時會看到稱為類方法的靜態方法,因為它們是使用類/構造函數的名稱調用的。 使用該術語時,是將類方法與在類的實例上調用的常規實例方法進行對比。 因為靜態方法是在構造函數上而不是在任何特定實例上調用的,所以在靜態方法中使用this關鍵字幾乎沒有任何意義。

資料來源:弗拉納根,大衛。 JavaScript:權威指南。

在@Ninjaneer 接受的答案中:

class StaticMethodCall {   constructor() {
    console.log(StaticMethodCall.staticMethod()); 
    // 'static method has been called.' 

    console.log(this.constructor.staticMethod()); 
    // 'static method has been called.'    }

  static staticMethod() {
    return 'static method has been called.';   } }

this.constructor.staticMethod()將拋出錯誤,因為在構造函數中訪問this之前必須調用超級構造函數。

假設你解決了前面提到的這個問題,沒有雙關語,我認為調用this.constructor.staticMethod()的唯一好處是你不依賴於類的名稱——如果它發生了變化。 但是,這種好處可能微不足道,因為它只會從類內部進行的靜態方法調用中受益。 外部進行的靜態方法調用必須是像StaticMethodCall.constructor.staticMethod()這樣的東西,這違背了目的並且看起來很傻。

總之:

如果您打算在類之外使用靜態方法,我肯定會堅持使用 StaticMethodCall.staticMethod(),因為它更慣用和簡潔。

如果您只打算在類中使用靜態方法,那么使用this.constructor.staticMethod()可能是可以的,但它可能會混淆其他開發人員並將他們帶回此頁面:-)

我剛剛遇到了一個類似的問題(引用超級靜態方法),在這里留下一個答案,以防其他人覺得它有用。

本質上,解決方案是將類本身傳遞給靜態方法。 例如:

class Foo {
  static greet(Type) {
    return `Hello, ${Type.name()}`
  }
  static name() {
    return 'foo'
  }
}
class Bar extends Foo {
  static name() {
    return 'bar'
  }
}

現在你可以打電話

Bar.greet(Bar) // returns 'Hello, bar'

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM