js 对象
私有静态成员
前面在基本概念里我们已经清楚了,只有用 function 创建函数,才能创建一个新的作用域,而要创建私有成员(不论是静态成员,还是实例成员),都需要通过创建新的作用域才能够起到数据隐藏的目的。下面所采用的方法就是基于这一点来实现的。
实现私有静态成员是通过创建一个匿名函数函数来创建一个新的作用域来实现的。
通常我们使用匿名函数时都是将它赋值给一个变量,然后通过这个变量引用该匿名函数。这种情况下,该匿名函数可以被反复调用或者作为类去创建对象。而这里,我们创建的匿名函数不赋值给任何变量,在它创建后立即执行,或者立即实例化为一个对象,并且该对象也不赋值给任何变量,这种情况下,该函数本身或者它实例化后的对象都不能够被再次存取,因此它唯一的作用就是创建了一个新的作用域,并隔离了它内部的所有局部变量和函数。因此,这些局部变量和函数就成了我们所需要的私有静态成员。而这个立即执行的匿名函数或者立即实例化的匿名函数我们称它为静态封装环境。
下面我们先来看通过直接调用匿名函数方式来创建带有私有静态成员的类的例子:
class5 = (function() {
// private static fields
var s_first = 1;
var s_second = 2;
// private static methods
function s_method1() {
s_first++;
}
var s_second = 2;
function constructor() {
// private fields
var m_first = 1;
var m_second = 2;
// private methods
function method1() {
alert(m_first);
}
var method2 = function() {
alert(m_second);
}
// public fields
this.first = "first";
this.second = ['s','e','c','o','n','d'];
// public methods
this.method1 = function() {
s_second--;
}
this.method2 = function() {
alert(this.second);
}
// constructor
{
s_method1();
this.method1();
}
}
// public static methods
constructor.method1 = function() {
s_first++;
alert(s_first);
}
constructor.method2 = function() {
alert(s_second);
}
return constructor;
})();
var o1 = new class5();
class5.method1();
class5.method2();
o1.method2();
var o2 = new class5();
class5.method1();
class5.method2();
o2.method2();
这个例子中,通过
(function() {
...
function contructor () {
...
}
return constructor;
})();
来创建了一个静态封装环境,实际的类是在这个环境中定义的,并且在最后通过 return 语句将最后的类返回给我们的全局变量 class5,然后我们就可以通过 class5 来引用这个带有静态私有成员的类了。
为了区分私有静态成员和私有实例成员,我们在私有静态成员前面用了 s_ 前缀,在私有实例成员前面加了 m_ 前缀,这样避免了重名,因此在对象中总是可以存取私有静态成员的。
但是这种命名方式不是必须的,只是推荐的,私有静态成员可以跟私有实例成员同名,在重名的情况下,在类构造器和在类中定义的实例方法中存取的都是私有实例成员,在静态方法(不论是公有静态方法还是私有静态方法)中存取的都是私有静态成员。
在类外并且在静态封装环境中通过 prototype 方式定义的公有实例方法存取的是私有静态成员。
在静态封装环境外定义的公有静态方法和通过 prototype 方式定义的公有实例方法无法直接存取私有静态成员。
另外一种方式通过直接实例化匿名函数方式来创建带有私有静态成员的类的例子跟上面的例子很相似:
new function() {
// private static fields
var s_first = 1;
var s_second = 2;
// private static methods
function s_method1() {
s_first++;
}
var s_second = 2;
class6 = function() {
// private fields
var m_first = 1;
var m_second = 2;
// private methods
function method1() {
alert(m_first);
}
var method2 = function() {
alert(m_second);
}
// public fields
this.first = "first";
this.second = ['s','e','c','o','n','d'];
// public methods
this.method1 = function() {
s_second--;
}
this.method2 = function() {
alert(this.second);
}
// constructor
{
s_method1();
this.method1();
}
}
// public static methods
class6.method1 = function() {
s_first++;
alert(s_first);
}
class6.method2 = function() {
alert(s_second);
}
};
var o1 = new class6();
class6.method1();
class6.method2();
o1.method2();
var o2 = new class6();
class6.method1();
class6.method2();
o2.method2();
这个例子的结果跟通过第一种方式创建的例子是相同的。只不过它的静态封装环境是这样的:
new function() {
...
};
在这里,该函数没有返回值,并且对于 class5 的定义是直接在静态封装环境内部通过给一个没有用 var 定义的变量赋值的方式实现的。
当然,也完全可以在
(function() {
...
})();
这种方式中,不给该函数定义返回值,而直接在静态封装环境内部通过给一个没有用 var 定义的变量赋值的方式来实现带有私有静态成员的类的定义。
这两种方式在这里是等价的。
分享到:
相关推荐
除了这两种方式,还可以利用JSON对象和自定义函数来模拟类结构,模拟实现私有成员、受保护成员和静态成员等概念。 首先,私有成员是指那些只能在类的内部访问,而不能从类的外部访问的成员。在JavaScript中,私有...
总结来说,JavaScript虽然没有直接的类和静态类概念,但通过构造函数、原型链、闭包以及对象字面量等特性,我们可以灵活地模拟这些概念,实现面向对象的编程风格。理解并掌握这些技巧,将有助于编写更复杂、可维护的...
- **对象方法绑定**:对象的方法可以通过赋值的方式绑定到对象实例上。例如: ```javascript function Person() { this.name = "abc"; } function show() { window.alert("Hello " + this.name); } var p1 ...
32. `Me`:在对象方法中引用当前对象。 33. `Mod`:取模运算符。 34. `New`:创建对象的实例。 35. `Not`:逻辑运算符,取反布尔值。 36. `Nothing`:空值,表示没有任何对象引用。 37. `On Error`:错误处理。 38. ...
9. **访问修饰符**:虽然JavaScript没有像Java或C#那样的严格访问修饰符,但我们可以通过变量的作用域和闭包来模拟公有、私有和受保护的成员。 10. **模块系统**:在ES6之前,JavaScript的模块化主要依赖于CommonJS...
接口可以声明方法、属性、索引器和事件,但不能声明公有的域或私有的成员变量。例如: ```csharp interface IMyInterface { void MyMethod(); event EventHandler MyEvent; } ``` ### 装箱与拆箱操作 在C#中,将...
- **final**:是一个修饰符,用于声明常量、不可变类和方法等,表明被修饰的对象或方法不允许被修改或重写。 - **finally**:通常与try-catch语句配合使用,用于确保无论程序是否发生异常,finally块中的代码都将被...
- **接口**只能包含抽象方法(Java 8后可以有默认方法和静态方法),没有状态,只能定义常量。 3. **Strings=new String("abc");创建了几个String Object?** - 这行代码创建了一个`String`对象,但字符串 `"abc"`...
2. **包含其他文件**: 使用自定义函数 `usingScript("utils.js")` 包含其他JavaScript文件。 3. **基类定义**: 定义基类时,使用多行注释进行类说明。 ```javascript /******************************************...
6.10.2 实现静态方法 6.10.3 检查类的类型和类型提示 6.10.4 克隆对象 6.10.5 使用抽象类 6.10.6 使用__call()重载方法 6.10.7 使用__autoload()方法 6.10.8 实现迭代器和迭代 6.10.9 将类转换成字符串 6.10...
6.10.2 实现静态方法 6.10.3 检查类的类型和类型提示 6.10.4 克隆对象 6.10.5 使用抽象类 6.10.6 使用__call()重载方法 6.10.7 使用__autoload()方法 6.10.8 实现迭代器和迭代 6.10.9 将类转换成字符串 6.10.10 使用...
6.10.2 实现静态方法 6.10.3 检查类的类型和类型提示 6.10.4 克隆对象 6.10.5 使用抽象类 6.10.6 使用__call()重载方法 6.10.7 使用__autoload()方法 6.10.8 实现迭代器和迭代 6.10.9 将类转换成字符串 6.10...