首页 > 代码库 > JavaScript基础对象创建模式之静态成员(027)
JavaScript基础对象创建模式之静态成员(027)
在支持“类”的面向对象语言中,静态成员指的是那些所有实例对象共有的类成员。静态成员实际是是“类”的成员,而非“对象”的成员。所以如果 MathUtils类中有个叫 max()的静态成员方法,那么调用这个方法的方式应该是这样的:MathUtils.max(3, 5)。
1. 公有静态成员
JavaScript里并没有“类”的实际语言表示 ,所以也就没有静态成员的语义表示。但由于构造函数本身就是个对象,如果把构造函数看成“类”,那么它的成员就是可以通过“类”名(也就是构造函数)直接访问的“静态成员”。函数的记忆模式用的也是相同的技术。下面的例子中,Gadget的构造函数提供一个公有的静态方法isShiny()以及一个常规的实例方法setPrice():
// constructorvar Gadget = function () {};// a static methodGadget.isShiny = function () { return "you bet";};// a normal method added to the prototypeGadget.prototype.setPrice = function (price) { this.price = price;};
调用Gadget的这两个方法时,由于isShiny()是静态方法,所以只能通过“类”,也就是构造函数来调用,而setPrice()是实例方法,必须用创建出的对象来调用:
// calling a static methodGadget.isShiny(); // "you bet"// creating an instance and calling a methodvar iphone = new Gadget();iphone.setPrice(500);
反过来,用“类”调用实例方法,或用对象调用静态方法,得到的都是undefined:
typeof Gadget.setPrice; // "undefined"typeof iphone.isShiny; // "undefined"
如果需要在实例中调用静态方法,其实也很简单,只需让构造函数的prototype支持这个静态方法即可:
Gadget.prototype.isShiny = Gadget.isShiny;iphone.isShiny(); // "you bet"
当用prototype来调用静态方法时需要特别注意,在静态方法中的this引用是构造函数Gadget,而普通的实例方法中的this引用是调用它的对象本身。据此,我们可以创建出一个方法,它既可静态地调用,也可以用对象调用,分别实现不同的功能:
// constructorvar Gadget = function (price) { this.price = price;};// a static methodGadget.isShiny = function () { // this always works var msg = "you bet"; if (this instanceof Gadget) { // this only works if called non-statically msg += ", it costs $" + this.price + ‘!‘; } return msg;};// a normal method added to the prototypeGadget.prototype.isShiny = function () { return Gadget.isShiny.call(this);};
这时,如果把isShiny()作为静态方法调用,结果是这样的:
Gadget.isShiny(); // "you bet"
而非静态的调用,也就是用对象来调用这个方法,结果则变成:
var a = new Gadget(‘499.99‘);a.isShiny(); // "you bet, it costs $499.99!"
2. 私有静态成员
私有静态成员指的是,这些静态成员:
所有实例对象都可以通过“类名“(也就是构造函数)来访问;
在构造函数之外不能被访问。
计数器是常见的私有静态属性。为了提供私有的空间,需要用一个即时函数来提供局部作用域:
var Gadget = (function () { // static variable/property var counter = 0; // returning the new implementation // of the constructor return function () { console.log(counter += 1); };}()); // execute immediately
这样,每次创建新的实例,内部的静态成员counter就会加一:
var g1 = new Gadget(); // logs 1var g2 = new Gadget(); // logs 2var g3 = new Gadget(); // logs 3
这样,counter也可以作为每次新创建的对象的ID:因为它不重复,而且还自增。这时可以考虑加一个可以给所有实例对象使用的访问控制方法getLastID()来访问这个ID:
// constructorvar Gadget = (function () { // static variable/property var counter = 0, NewGadget; // this will become the // new constructor implementation NewGadget = function () { counter += 1; }; // a privileged method NewGadget.prototype.getLastId = function () { return counter; }; // overwrite the constructor return NewGadget;}()); // execute immediately
测试一下:
var iphone = new Gadget();iphone.getLastId(); // 1var ipod = new Gadget();ipod.getLastId(); // 2var ipad = new Gadget();ipad.getLastId(); // 3
公有和私有的静态成员可以为每一位实例对象提供共同的方法和属性,这些方法和属性不会在每次创建对象的时候多次初始化,因此在实际应用中十分有用。后面还将介绍的单例模式使用到了静态成员的技术。
JavaScript基础对象创建模式之静态成员(027)
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。