① 新生成的每个实例对象都会拷贝构造函数中的属性和方法,而私有的_xx 无疑在每次实例化的时候都会重复拷贝,这样会占用大量内存,所以不适合大量使用,仅在必要时适当使用
② 不利于类的继承,所有派生的子类都不能访问超类中的私有属性和方法。不过可以使用特权方法来访问超类中的私有属性和方法。举个例子:
// B 是超类 function B() { var _private = 1; function _checkPrivate() { return _private; } this.checkPrivate = function() { return _checkPrivate; } } // C 是派生类 function C() { B.call(this); // 用call 实现继承 ,后面我们会讲到如何继承 // this.private = _private; // 这里尝试访问超类的私有属性,因为无法访问,会报错 } // 实例化 派生类C var c = new C(); // console.log(c.private); // 和在C内部的尝试一样,是无法访问的,报错 // 不过可以用下面的方法访问超类中的私有属性 console.log(c.checkPrivate()()); // 1
静态方法
在面向对象编程中,大多数的方法和属性与类的实例产生联系。还有一种情况是,静态属性和方法是与类本身直接联系,可直接从类访问,也就是说,静态成员在类上操作,而不是实例上。在JavaScript中的Math和Global都是静态对象,不需要实例化就可直接访问。
类的静态成员,包括私有和公共两种。他们在系统中只有一份副本,意思就是说他们不会被分成多份传递给不同的实例对象。而是通过函数指针进行引用。书上有个例子非常好,下面举例:
var F = (function(){ // 把闭包函数赋给F,返回一个构造函数 var _a = 1; // 定义一个闭包体内的私有变量 this.a = _a; // 闭包体内的公共属性 a this.get1 = function(){ // 闭包体内的公共方法get1 return _a; } this.set1 = function(x){ // 闭包体内的公共方法set1 _a = x; }; return function(){ // 返回一个构造函数,构造函数也是函数,更是对象(相当于一个类) this.get2 = function() { // 类的get2方法 return _a; }; this.set2 = function(x) { // 类的set2方法 _a = x; }; } })(); // 定义类的静态公共方法和属性 F.get3 = function(){ // 定义一个静态方法get3 return get1(); // 这里可以直接使用 F内的公共方法get1 } F.set3 = function(x) { // 定义一个静态方法set3 return set1(x); // 同get1 } // 下面开始测试 var f = new F(); // 实例化这个类 console.log(f.get2()); // 1 用实例对象访问公共方法get2 F.set3(3); // 调用静态方法set3 console.log(F.get3()); // 3 F.A = ++a; // 定义一个静态属性A console.log(F.A); // 2
我们推荐使用这种闭包的封装方式
感兴趣的朋友可以使用在线HTML/CSS/JavaScript代码运行工具:测试上述代码运行效果。
更多关于JavaScript相关内容可查看本站专题:《javascript面向对象入门教程》、《JavaScript错误与调试技巧总结》、《JavaScript数据结构与算法技巧总结》、《JavaScript遍历算法与技巧总结》及《JavaScript数学运算用法总结》