深入理解JavaScript模拟私有成员

  一般的面向对象语言C++或JAVA,对象都是有私有成员的。js中没有类的改变,同样也没有对象的私有成员这个概念。但是可以通过某些特殊写法,模拟出私有成员。

1、特权模式:

  (1)在构造函数内部声明的变量、子函数以及参数,全部都是函数私有的,可以看作私有成员。给this指针添加的闭包,全部都是公有成员

  所以下面例子:参数a/b、变量_value、函数add是私有的,外面无法访问,故c1.add会报错

  setValue和getValue是公有的,c1可以访问

function MyClass(a,b){
    //private
    var _value=0;
    function add(){
        _value=a+b;
    }
    //process
    add();
    //public
    this.getValue=function(){
        return _value;
    }
    this.setValue=function(a1,b1){
        a=a1;
        b=b1;
        add();
    }
}
var c1=new MyClass(1,2);
var c2=new MyClass(1,2);
c1.setValue(3,4);
alert(c1.getValue());//7
alert(c2.getValue());//3
alert(c1.add());//c1中无add方法,报错c1.add is not a function(…)

  (2)这种模拟方法的优点是代码清晰明了,缺点是每个对象的成员函数,不论是私有还是公有,都是自己独有的即便成员函数的功能相同,但他们却是存放在不同位置的不同函数。
  (3)这种模拟方法只模仿了一个外形。OOP语言中,每个对象的成员函数,在内存中只体现为一个单元,我们违背了这一原则

2、私有作用域模式:

  (1)既然模拟出了块级作用域,可以考虑把块级作用域拿来,模拟一下私有成员。

(function(){
    //private
    var _value=0, _a=0, _b=0;
    function add(){
        _value=_a+_b;
    }
    //construct
    MyClass=function(a,b){
        _a=a;
        _b=b;
        add();
    }
    //public
    MyClass.prototype.getValue=function(){
        return _value;
    }
    MyClass.prototype.setValue=function(a1,b1){
        _a=a1;
        _b=b1;
        add();
    }
})();
var c1=new MyClass(1,2);
var c2=new MyClass(1,2);
c1.setValue(3,4);
alert(c1.getValue());//7
alert(c2.getValue());//7
alert(c1.add());//报错

  (2)上面例子我们使用了块级作用域_value、_a、_b、add都是匿名函数的私有变量MyClass前面没有var,所有MyClass是全局变量,可以在块级作用域外部使用getValue和setValue是通过原型模式为MyClass添加的公共方法
  (3)这样写,MyClass所有实例的公共方法不再单独创建,而是共享使用;而私有方法,则是共享作用域链中的add,也不是独立创建的。针对成员方法而言,已经与C++和java非常接近了。
  (4)但这样写的缺点也是显而易见的就是私有数据成员_value、_a、_b在各实例之间也是共享的。这些成员,相当于static成员

3、综合模式

(function(){
    //private static
    var _count=0;
    function add(a,b){
        return a+b;
    }
    //construct
    MyClass=function(a,b){
        //private
        var _data={ value:0 }
        //process
        _data.value=add(a,b);
        _count++;
        //public
        this.data=function(){return _data;}
    }
    //public
    MyClass.prototype.getValue=function(){
        return this.data().value;
    }
    MyClass.prototype.setValue=function(a,b){
        this.data().value=add(a,b);
    }
    MyClass.prototype.getCount=function(){
        return _count;
    }
})();  

var c1=new MyClass(1,2);
var c2=new MyClass(1,2);
c1.setValue(3,4);
alert(c1.getValue());//7
alert(c2.getValue());//3
alert(c1.getCount());//2
alert(c2.getCount());//2   

  (1)为了解决私有作用域模式中私有数据成员共享的问题,必须将私有数据成员写在MyClass内。但这样,公有成员函数就不能使用他们了。所以还是要使用一个特权函数,提供私有数据成员的接口,这个是无法避免的,因此只能让代价尽量的小,比如对私有数据成员做一个打包。
  (2)私有方法是内存共享的,比如add函数。然而实际上,私有方法只要共享内存,就是private static状态,而private static状态方法,如果想使用非形参变量时,也只能使用private static的变量,比如_count。想使用实例的私有数据成员,只能通过形参传入。
  (3)公有方法是内存共享的,是通过原型链实现的。公有方法使用私有数据成员,就必须得到私有数据成员的接口。我们做的this.data就是接口
  (4)整个模式中,闭包个数只有一个,就是this.data,这个闭包是无法避免的。

时间: 2024-08-24 08:18:31

深入理解JavaScript模拟私有成员的相关文章

javascript 创建私有成员和静态私有成员

私有方法和属性 在javascript中,因为没有类的概念,所以只能通过构造函数来模拟类,假设现在需要写一个手机类,这个手机需要传入一张电话号码,然后能打电话.最简单的方式是 var Phone= function(num){ //手机号 this.num= num; //打电话 this.call = function(phone){ console.log(this.num + "正在呼叫" + phone.num); } } var p1= new Phone("130

面向对象的JavaScript(3):私有成员和公开成员

在小项目中对于JavaScript使用,只要写几个function就行了.但在大型项目中,尤其是在开发追求 良好的用户体验的网站中,如SNS,就会 用到大量的JavaScrpt,有时JavaScript的工作量胜过了C#,这时写一堆function,就会显得很乱,杂乱无章,甚至会出现命名冲突,管理和维 护起来都很麻烦.对于这种情况我们就需要使用面向对象的思想来开发JavaScript.那我们就这样作罢: 这节来说下JavaScript的私有成员和公开成员,虽然JavaScript没有privat

深入理解javascript闭包【整理】

原文链接:http://www.cn-cuckoo.com/2007/08/01/understand-javascript-closures-72.html 英文原文:http://www.jibbering.com/faq/faq_notes/closures.html 要成为高级 JavaScript 程序员,就必须理解闭包. 本文结合 ECMA 262 规范详解了闭包的内部工作机制,让 JavaScript 编程人员对闭包的理解从"嵌套的函数"深入到"标识符解析.执行

javascript在私有作用域中定义私有变量和私有函数 (1)

javascript没有私有成员,但是有私有变量,所有对戏那个属性都是公有的 任何在函数中定义的变量,都可以认为是私有变量,因为函数内部不能访问. 私有变量包括:函数的参数.局部变量.函数内部定义的其他函数 - 在私有作用域中定义私有变量和私有函数 function MyObject(){ //私有变量和私有函数 var privateVariable=10; function privateFunction(params) { return false } //特权方法----有权访问私有变量

javascript模式(1)--私有成员

javascript是基于对象的一门语言,没有想java等语言那样子拥有封装的特性.但是javascript可以通过闭包来进行模拟. 1.构造函数与私有成员 可以用构造函数形成一个闭包,实现内部成员的私有化. function Person(){ //私有成员 var country = 'cn'; //特权方法 this.getCountry = function(){ return country; } } var man1 = new Person(); var man2 = new Pe

JavaScript 私有成员

Class field declarations for JavaScript(JavaScript 类的字段声明)目前已经进入了 stage-3,其中包含一项 OOP 开发者都很关注的内容:Private fields.JavaScript 一直没有私有成员并不是没有原因,所以这一提议给 JavaScript 带来了新的挑战.但同时,JavaScript 在 ES2015 发布的时候已经在考虑私有化的问题了,所以要实现私有成员也并非毫无基础. 笔者在专栏<JavaScript 全栈工程师养成记

[C++参考]私有成员变量的理解

私有成员变量的概念,在脑海中的现象是,以private关键字声明,是类的实现部分,不对外公开,不能在对象外部访问对象的私有成员变量. 然而,在实现拷贝构造函数和赋值符函数时,在函数里利用对象直接访问了私有成员变量,因而,产生了困惑.下面以具体实例进行说明: 疑惑:为什么第26行和第32行代码可以编译通过,而第39行和第40行代码会产生编译错误? class CTest { public: CTest(int i); CTest(const CTest& rhs); CTest& opera

【C++】 私有成员变量的理解

私有成员变量的概念,在脑海中的现象是,以private关键字声明,是类的实现部分,不对外公开,不能在对象外部访问对象的私有成员变量. 然而,在实现拷贝构造函数和赋值符函数时,在函数里利用对象直接访问了私有成员变量,因而,产生了困惑.下面以具体实例进行说明: 疑惑:为什么第26行和第32行代码可以编译通过,而第39行和第40行代码会产生编译错误? 1 class CTest { 2 public: 3 CTest(int i); 4 CTest(const CTest& rhs); 5 CTest

如何理解 “私有成员只有在声明它们的类和结构体中才是可访问的” ?

通常私有成员(private)只有在声明它们的类和结构体中才是可访问的,如下类: 1 class A 2 { 3 private int i; 4 } 只有在A的内部在能访问i,这是众所周知的. 再看下面的类: 1 class B 2 { 3 private int i; 4 void DoSomeThing() 5 { 6 B b = new B(); 7 int c = b.i; //这里在b的外部也能访问其私有成员i 8 } 9 } 不要惊讶,查查MSDN,http://msdn.micr