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
工作,
-
Foo.__proto__ = Foo.prototype
-
Foo.talk = Foo.prototype.talk
有没有其他的方法来做到这一点? 我不知道这样做是否正确。 你在JavaScript代码中使用类方法还是静态方法?
首先,请记住,JavaScript主要是原型语言 ,而不是基于类的语言 1 。 Foo
不是一个类,它是一个函数,它是一个对象。 您可以使用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: 原始值(包括undefined
, null
,布尔值,数字和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
另外,现在可以用class
和static
来做
'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现在支持class
和static
关键字,如魅力:
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");