在支持“类”的面向对象语言中,静态成员指的是那些所有实例对象共有的类成员。静态成员实际是是“类”的成员,而非“对象”的成员。所以如果 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
公有和私有的静态成员可以为每一位实例对象提供共同的方法和属性,这些方法和属性不会在每次创建对象的时候多次初始化,因此在实际应用中十分有用。后面还将介绍的单例模式使用到了静态成员的技术。

JavaScript基础对象创建模式之静态成员(027)的更多相关文章

  1. JavaScript基础对象创建模式之单体/单例模式(Singleton)

    首先,单例模式是对象的创建模式之一,此外还包括工厂模式.单例模式的三个特点: 1,该类只有一个实例 2,该类自行创建该实例(在该类内部创建自身的实例对象) 3,向整个系统公开这个实例接口 Java中大 ...

  2. JavaScript基础对象创建模式之模块模式(Module Pattern)(025)

    模块模式可以提供软件架构,为不断增长的代码提供组织形式.JavaScript没有提供package的语言表示,但我们可以通过模块模式来分解并组织 代码块,这些黑盒的代码块内的功能可以根据不断变化的软件 ...

  3. JavaScript基础对象创建模式之私有属性和方法(024)

    JavaScript没有特殊的语法来表示对象的私有属性和方法,默认的情况下,所有的属性和方法都是公有的.如下面用字面声明的对象: var myobj = { myprop: 1, getProp: f ...

  4. JavaScript基础对象创建模式之链式调用模式(Chaining Pattern)(029)

    链式调用模式允许一个接一个地调用对象的方法.这种模式不考虑保存函数的返回值,所以整个调用可以在同一行内完成: myobj.method1("hello").method2().me ...

  5. JavaScript基础对象创建模式之对象的常量(028)

    虽然许多编程语言提供了const关键字来支持常量的声明,但JavaScript里没有表示常量的语义.我们可以用全大写的方式来声明变量,表明它实际上是个常量: Math.PI; // 3.1415926 ...

  6. JavaScript基础对象创建模式之沙盘模式(026)

    沙盘模式可以弥补命名空间模式中的两项不足之处: 使用唯一全局对象作为程序的全局变量入口,使得无法在同一程序中使用两个不同版本的API,因此它们使用的是同一个唯一的全局对象名,如MYAPP: 较长的嵌套 ...

  7. JavaScript基础对象创建模式之声明依赖模式(023)

    运用了命名空间(Namespace)模式后, 就可以使用一些JavaScript库了,比如YAHOO作用YUI2库的全局对象,可以通过 YAHOO.util.Dom 和 YAHOO.util.Even ...

  8. JavaScript基础对象创建模式之命名空间(Namespace)模式(022)

    JavaScript中的创建对象的基本方法有字面声明(Object Literal)和构造函数两种,但JavaScript并没有特别的语法来表示如命名空间.模块.包.私有属性.静态属性等等面向对象程序 ...

  9. javascript的对象创建模式---命名空间模式

    javascript中对象的概念是很普遍的,对象是是对象,数组是对象,函数也是对象,字符串其实也是对象.常见的对象创建方法有对象字面量.构造函数创建.我们先来看看对象的创建还有哪些更高级的模式. 一. ...

随机推荐

  1. C# winform 学习(二)

    目标: 1.ADONET简介 2.Connection对象 3.Command对象 4.DataReader对象 准备工作:创建mhys数据库及员工表 代码如下: create database mh ...

  2. Java实现 蓝桥杯 算法提高 队列操作

    算法提高 队列操作 时间限制:1.0s 内存限制:256.0MB 提交此题 问题描述 队列操作题.根据输入的操作命令,操作队列(1)入队.(2)出队并输出.(3)计算队中元素个数并输出. 输入格式 ...

  3. Java实现 LeetCode 410 分割数组的最大值

    410. 分割数组的最大值 给定一个非负整数数组和一个整数 m,你需要将这个数组分成 m 个非空的连续子数组.设计一个算法使得这 m 个子数组各自和的最大值最小. 注意: 数组长度 n 满足以下条件: ...

  4. SQLServer2019安装教程

    可以去官网下载,我百度网盘也有都一样 https://pan.baidu.com/s/1i3umqHXSUMbxJ9rRi6mU4A 提取码:5g9q 打开应用程序 点击安装,点第一个全新得SQL s ...

  5. java实现第五届蓝桥杯生物芯片

    生物芯片 X博士正在研究一种生物芯片,其逻辑密集度.容量都远远高于普通的半导体芯片. 博士在芯片中设计了 n 个微型光源,每个光源操作一次就会改变其状态,即:点亮转为关闭,或关闭转为点亮. 这些光源的 ...

  6. KVM NAT(网络地址转换模式)

    NAT(网络地址转换模式) 使用NAT模式,就是让虚拟系统借助NAT(网络地址转换)功能,通过宿主机器所在的网络来访问公网.也就是说,使用NAT模式可以实现在虚拟系统里访问互联网.很显然,如果你只有一 ...

  7. 实验四 Linux系统搭建C语言编程环境

    项目 内容 这个作业属于那个课程 <班级课程的主页链接> 这个作业的要求在哪里 <作业要求链接地址> 学号-姓名 17043220-万文文 作业学习目标 1).Linux系统下 ...

  8. 离职冷静期文件.doc

    <中华人民共和国民法典>通过十三届全国人大三次会议表决,将于2021年1月1日起施行,其中#离婚冷静期#备受关注.多方人士表示,离婚冷静期设立的出发点,不是对婚姻自由的一种破坏,而是让当事 ...

  9. 宝塔面板如何有效的清除SSL证书以及缓存

    一:关闭SSL 我们先关闭SSL证书,这个大家都会的吧.如图: 二:证书夹 网站配置的证书夹,我们删除掉,如图: 三:寻找SSL证书路径 网站配置里有一路径我们看下:如下 ssl_certificat ...

  10. @atcoder - AGC018F@ Two Trees

    目录 @description@ @solution@ @accepted code@ @details@ @description@ 给定两棵树 A, B.现你需要构造一组值 (X1, X2, .. ...