我知道这是可行的:

function Foo() {};
Foo.prototype.talk = function () {
    alert('hello~\n');
};

var a = new Foo;
a.talk(); // 'hello~\n'

但如果我想打电话

Foo.talk() // this will not work
Foo.prototype.talk() // this works correctly

我找到了一些制作Foo的方法。谈工作,

Foo。__proto__ = Foo.prototype Foo。talk = Foo.prototype.talk

还有别的办法吗?我不知道这样做是否正确。在JavaScript代码中使用类方法还是静态方法?


当前回答

只是额外的注释。使用类ES6,当我们创建静态方法时,javacscript引擎设置的描述符属性与老式的“静态”方法略有不同

function Car() {

}

Car.brand = function() {
  console.log('Honda');
}

console.log(
  Object.getOwnPropertyDescriptors(Car)
);

它将brand()的内部属性(描述符属性)设置为

..
brand: [object Object] {
    configurable: true,
    enumerable: true,
    value: ..
    writable: true

}
..

相比

class Car2 {
   static brand() {
     console.log('Honda');
   }
}

console.log(
  Object.getOwnPropertyDescriptors(Car2)
);

将brand()的内部属性设置为

..
brand: [object Object] {
    configurable: true,
    enumerable: false,
    value:..
    writable: true
  }

..

在ES6中static method的enumerable设置为false。

这意味着你不能使用for-in循环来检查对象

for (let prop in Car) {
  console.log(prop); // brand
}

for (let prop in Car2) {
  console.log(prop); // nothing here
}

静态方法在ES6中被视为其他类的私有属性(名称,长度,构造函数),除了静态方法仍然是可写的,因此描述符writable被设置为true {writable: true}。这也意味着我们可以推翻它

Car2.brand = function() {
   console.log('Toyota');
};

console.log(
  Car2.brand() // is now changed to toyota
);

其他回答

在你的例子中,如果你想要Foo.talk():

function Foo() {};
// But use Foo.talk would be inefficient
Foo.talk = function () {
    alert('hello~\n');
};

Foo.talk(); // 'hello~\n'

但这是一种低效的实现方式,使用原型更好。


另一种方式,My way定义为静态类:

var Foo = new function() {
  this.talk = function () {
    alert('hello~\n');
    };
};

Foo.talk(); // 'hello~\n'

上面的静态类不需要使用原型,因为它只会被构造一次作为静态使用。

https://github.com/yidas/js-design-patterns/tree/master/class

你可以通过以下方式实现:

function Foo() {};

Foo.talk = function() { alert('I am talking.'); };

你现在可以调用"talk"函数如下:

Foo.talk();

您可以这样做,因为在JavaScript中,函数也是对象。

静态方法调用是直接在类上进行的,不能在类的实例上调用。静态方法经常用于 创建效用函数

非常清晰的描述

直接取自mozilla.org

Foo需要绑定到你的类 然后当你创建一个新实例时,你可以调用myNewInstance.foo() 如果你导入你的类,你可以调用一个静态方法

当你尝试调用Foo时。JS尝试通过__proto__搜索函数talk,当然,它找不到。

Foo。__proto__是Function.prototype。

在函数或类对象以及它们的实例上实现方法和属性有很多方法。

在类(或函数)本身:Foo.method()或Foo.prop。这些是静态方法或属性 在它的原型上:Foo.prototype.method()或Foo.prototype.prop。创建时,实例将通过原型女巫{method:function(){…},道具:…}。所以foo对象会接收,作为原型,一个foo的副本。原型对象。 在实例本身上:将方法或属性添加到对象本身。foo ={方法:函数(){…},道具:}

this关键字将根据上下文以不同的方式表示和执行。在静态方法中,它将代表类本身(witch毕竟是Function的一个实例:类Foo{}相当等效于let Foo = new Function({})

随着ECMAScript 2015,今天似乎已经很好地实现了,可以更清楚地看到类(静态)方法和属性,实例方法和属性以及自己的方法和属性之间的区别。因此,您可以创建三个具有相同名称但不同的方法或属性,因为它们应用于不同的对象,方法中的this关键字将分别应用于类对象本身和实例对象,通过原型或通过它自己。

class Foo {
  constructor(){super();}
  
  static prop = "I am static" // see 1.
  static method(str) {alert("static method"+str+" :"+this.prop)} // see 1.
  
  prop="I am of an instance"; // see 2.
  method(str) {alert("instance method"+str+" : "+this.prop)} // see 2.
}

var foo= new Foo();
foo.prop = "I am of own";  // see 3.
foo.func = function(str){alert("own method" + str + this.prop)} // see 3.