在支持“类”的面向对象语言中,静态成员指的是那些所有实例对象共有的类成员。静态成员实际是是“类”的成员,而非“对象”的成员。所以如果 MathUtils类中有个叫 max()的静态成员方法,那么调用这个方法的方式应该是这样的:MathUtils.max(3, 5)。

1. 公有静态成员
JavaScript里并没有“类”的实际语言表示 ,所以也就没有静态成员的语义表示。但由于构造函数本身就是个对象,如果把构造函数看成“类”,那么它的成员就是可以通过“类”名(也就是构造函数)直接访问的“静态成员”。函数的记忆模式用的也是相同的技术。下面的例子中,Gadget的构造函数提供一个公有的静态方法isShiny()以及一个常规的实例方法setPrice():
// constructor
var Gadget = function () {};
// a static method
Gadget.isShiny = function () {
return "you bet";
};
// a normal method added to the prototype
Gadget.prototype.setPrice = function (price) {
this.price = price;
};
调用Gadget的这两个方法时,由于isShiny()是静态方法,所以只能通过“类”,也就是构造函数来调用,而setPrice()是实例方法,必须用创建出的对象来调用:
// calling a static method
Gadget.isShiny(); // "you bet"
// creating an instance and calling a method
var 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引用是调用它的对象本身。据此,我们可以创建出一个方法,它既可静态地调用,也可以用对象调用,分别实现不同的功能:
// constructor
var Gadget = function (price) {
this.price = price;
};
// a static method
Gadget.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 prototype
Gadget.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 1
var g2 = new Gadget(); // logs 2
var g3 = new Gadget(); // logs 3
这样,counter也可以作为每次新创建的对象的ID:因为它不重复,而且还自增。这时可以考虑加一个可以给所有实例对象使用的访问控制方法getLastID()来访问这个ID:
// constructor
var 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(); // 1
var ipod = new Gadget();
ipod.getLastId(); // 2
var ipad = new Gadget();
ipad.getLastId(); // 3
公有和私有的静态成员可以为每一位实例对象提供共同的方法和属性,这些方法和属性不会在每次创建对象的时候多次初始化,因此在实际应用中十分有用。后面还将介绍的单例模式使用到了静态成员的技术。

最新文章

  1. 常见web攻击以及防御
  2. C/C++头文件区别
  3. LoadRunner脚本参数化设置
  4. ServiceStack.Redis客户端访问库几项事项
  5. hdu 2028 Lowest Common Multiple Plus(最小公倍数)
  6. ubuntu logout 命令
  7. mongodb教程
  8. linux2.6.32 内核源码树解析与整理
  9. samba连接提示“找不到网络路径”
  10. Java程序测试之线程的同步
  11. 浅谈装饰器(Python)
  12. Java编程的逻辑 (95) - Java 8的日期和时间API
  13. Excel函数之vlookup的用法
  14. 7.8CSS部分的学习!
  15. Entity Framework学习初级篇3--LINQ TO Entities
  16. [Android] 布局优化技巧
  17. jenkins之-----------在必要的时候并发构建
  18. mysql主备部署[高可用]
  19. javaweb学习5——JSP
  20. Java每日学习笔记1

热门文章

  1. Java实现 蓝桥杯 传纸条
  2. Java实现 蓝桥杯VIP 算法提高 3-3求圆面积表面积体积
  3. Java实现二阶魔方旋转
  4. 【Jquery】根据元素个数给予宽度
  5. thinkphp5升级thinkphp6完整步骤
  6. iOS-Core Foundation框架到Foundation桥接的三种方式
  7. 04-Python基础3
  8. LeetCode 76,一题教会你面试算法时的思考套路
  9. DedeCms 标签中channelartlist设置属性标签样式的方法
  10. 想要学深度学习但是没有GPU?我帮你找了一些不错的平台