JavaScript中的类与静态方法

我知道这将工作:

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 

我find一些方法来使Foo.talk工作,

  1. Foo.__proto__ = Foo.prototype
  2. Foo.talk = Foo.prototype.talk

有没有其他的方法来做到这一点? 我不知道这样做是否正确。 你在JavaScript代码中使用类方法还是静态方法?

首先,请记住,JavaScript主要是原型语言 ,而不是基于类的语言 1Foo不是一个类,它是一个函数,它是一个对象。 您可以使用new关键字该函数实例化一个对象,这将允许您使用标准的OOP语言创build类似于类的东西。

我build议大多数时候忽略__proto__ ,因为它支持跨浏览器,而不是专注于学习prototype是如何工作的。

如果你有一个从函数2创build的对象的实例,并且以任何方式访问它的一个成员(方法,属性,属性,常量等),那么访问将沿着原型层次结构stream动,直到(a)find成员,或(b)没有find另一个原型。

层次结构从调用的对象开始,然后search它的原型对象。 如果原型对象有一个原型,它会重复,如果没有原型存在,返回undefined

例如:

 foo = {bar: 'baz'}; alert(foo.bar); //alerts "baz" foo = {}; alert(foo.bar); //alerts undefined function Foo(){} Foo.prototype = {bar: 'baz'}; f = new Foo(); alert(f.bar); //alerts "baz" because the object f doesn't have an attribute "bar" //so it checks the prototype f.bar = 'buzz'; alert( f.bar ); //alerts "buzz" because f has an attribute "bar" set 

在我看来,至less你已经对这些“基本”部分有所了解了,但是我需要明确地说明这些“基本”部分。

在JavaScript中,一切都是对象3

一切都是一个对象。

function Foo(){}不只是定义一个新的函数,它定义了一个新的函数对象,可以使用Foo访问。

这就是为什么你可以用Foo.prototype访问Foo的原型。

你也可以做的是在Foo上设置更多的function

 Foo.talk = function () { alert('hello world!'); }; 

这个新function可以通过以下方式访问:

 Foo.talk(); 

我希望现在你注意到函数对象和静态方法之间的相似性。

想想f = new Foo(); 作为创build一个类实例, Foo.prototype.bar = function(){...}为该类定义一个共享方法,而Foo.baz = function(){...}定义一个公共静态方法类。


1: ECMAScript 5规范中的class是“未来保留字” ,但ES6引入了使用class关键字定义类的能力。

2:本质上是一个由构造函数创build的类实例,但是我不想误导你

3: 原始值(包括undefinednull ,布尔值,数字和string)在技术上并不是对象,因为它们是低级语言实现。 布尔值,数字和string仍然与原型链相互作用,好像它们是对象一样,所以就这个答案而言,即使它们不是很完美,也可以更容易地将它们视为“对象”。

你可以做到这一点如下:

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

您现在可以调用“talk”function,如下所示:

 Foo.talk(); 

你可以这样做,因为在JavaScript中,函数也是对象。 “zzzzBov”也回答了这个问题,但这是一个冗长的阅读。

从实例中调用一个静态方法:

 function Clazz() {}; Clazz.staticMethod = function() { alert('STATIC!!!'); }; Clazz.prototype.func = function() { this.constructor.staticMethod(); } var obj = new Clazz(); obj.func(); // <- Alert's "STATIC!!!" 

简单的Javascript类项目: https : //github.com/reduardo7/sjsClass

下面是一个很好的例子来演示Javascript如何使用静态/实例variables和方法。

 function Animal(name) { Animal.count = Animal.count+1||1;// static variables, use function name "Animal" this.name = name; //instance variable, using "this" } Animal.showCount = function () {//static method alert(Animal.count) } Animal.prototype.showName=function(){//instance method alert(this.name); } var mouse = new Animal("Mickey"); var elephant = new Animal("Haddoop"); Animal.showCount(); // static method, count=2 mouse.showName();//instance method, alert "Mickey" mouse.showCount();//Error!! mouse.showCount is not a function, which is different from Java 

另外,现在可以用classstatic来做

 'use strict' class Foo { static talk() { console.log('talk') }; speak() { console.log('speak') }; }; 

会给

 var a = new Foo(); Foo.talk(); // 'talk' a.talk(); // err 'is not a function' a.speak(); // 'speak' Foo.speak(); // err 'is not a function' 

我使用命名空间:

 var Foo = { element: document.getElementById("id-here"), talk: function(message) { alert("talking..." + message); }, ChangeElement: function() { this.element.style.color = "red"; } }; 

并使用它:

 Foo.Talk("Testing"); 

要么

 Foo.ChangeElement(); 

ES6现在支持classstatic关键字,如魅力:

 class Foo { constructor() {} talk() { console.log("i am not static"); } static saying() { console.log(this.speech); } static get speech() { return "i am static method"; } } 

当你尝试调用Foo.talk ,JS尝试通过__proto__search一个函数,当然,它不能被find。

Foo.__proto__Function.prototype

如果你必须在ES5中编写静态方法,我find了一个很好的教程:

 //Constructor var Person = function (name, age){ //private properties var priv = {}; //Public properties this.name = name; this.age = age; //Public methods this.sayHi = function(){ alert('hello'); } } // A static method; this method only // exists on the class and doesn't exist // on child objects Person.sayName = function() { alert("I am a Person object ;)"); }; 

请参阅@ https://abdulapopoola.com/2013/03/30/static-and-instance-methods-in-javascript/

就你而言,你可以在类函数中定义方法:

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

另外,将类定义为一个静态类:

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

最后,我的静态类的方式:

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

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

当我遇到这样的情况时,我做了这样的事情:

 Logger = { info: function (message, tag) { var fullMessage = ''; fullMessage = this._getFormatedMessage(message, tag); if (loggerEnabled) { console.log(fullMessage); } }, warning: function (message, tag) { var fullMessage = ''; fullMessage = this._getFormatedMessage(message, tag); if (loggerEnabled) { console.warn(fullMessage);`enter code here` } }, _getFormatedMessage: function () {} }; 

所以现在我可以调用信息方法Logger.info("my Msg", "Tag");