JS从类调用静态方法

问题描述 投票:0回答:7

我有一个带有静态方法的类:

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

  static staticMethod() {}
}

静态方法是否有与此等效的方法(即引用没有实例的当前类)?

this.staticMethod()

所以我不必写类名:“User”。

javascript class static this
7个回答
83
投票

来自 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.';
  }
}

6
投票

您可以使用:

User.staticMethod()
代替:
this.constructor.staticMethod()


3
投票

@Rohith K P 的答案就是简而言之的解决方案。

如果你想理解它,你需要了解 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

Image of inheritance strructure in this case

所以,类本质上是一个函数,它是其原型对象的公共接口(构造函数)。

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:权威指南。


2
投票
static

事物绑定到类而不是实例。所以你至少必须指定类名。


如果您不想将它们绑定到类,请将它们设置为全局。


2
投票

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}
```



1
投票

本质上,解决方案是将类本身传递给静态方法。例如:

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'



0
投票

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()

,但它可能会让其他开发人员感到困惑并引导他们回到此页面:-)

    

© www.soinside.com 2019 - 2024. All rights reserved.