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

1、特权模式:

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

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

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

function MyClass(a,b){
//private
var _value=;
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(,);
var c2=new MyClass(,);
c1.setValue(,);
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=, _a=, _b=;
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(,);
var c2=new MyClass(,);
c1.setValue(,);
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=;
function add(a,b){
return a+b;
}
//construct
MyClass=function(a,b){
//private
var _data={ value: }
//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(,);
var c2=new MyClass(,);
c1.setValue(,);
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,这个闭包是无法避免的。

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

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

    在小项目中对于JavaScript使用,只要写几个function就行了.但在大型项目中,尤其是在开发追求 良好的用户体验的网站中,如SNS,就会 用到大量的JavaScrpt,有时JavaScrip ...

  2. 深入理解javascript闭包【整理】

    原文链接:http://www.cn-cuckoo.com/2007/08/01/understand-javascript-closures-72.html 英文原文:http://www.jibb ...

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

    javascript是基于对象的一门语言,没有想java等语言那样子拥有封装的特性.但是javascript可以通过闭包来进行模拟. 1.构造函数与私有成员 可以用构造函数形成一个闭包,实现内部成员的 ...

  4. js基础知识温习:Javascript中如何模拟私有方法

    本文涉及的主题虽然很基础,在很多人眼里属于小伎俩,但在JavaScript基础知识中属于一个综合性的话题.这里会涉及到对象属性的封装.原型.构造函数.闭包以及立即执行表达式等知识. 公有方法 公有方法 ...

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

    私有成员变量的概念,在脑海中的现象是,以private关键字声明,是类的实现部分,不对外公开,不能在对象外部访问对象的私有成员变量. 然而,在实现拷贝构造函数和赋值符函数时,在函数里利用对象直接访问了 ...

  6. JavaScript中的私有成员[翻译]

    原作者:Douglas Crockford,原文地址:http://www.crockford.com/javascript/private.html JavaScript 是世界上被误解最深的编程语 ...

  7. 精读JavaScript模式(七),命名空间模式,私有成员与静态成员

    一.前言 惰性十足,这篇2月19号就开始写了,拖到了现在,就是不愿意花时间把看过的东西整理一下,其它的任何事都比写博客要有吸引力,我要反省自己. 从这篇开始,是关于JS对象创建模式的探讨,JS语言简单 ...

  8. Python模拟保护和私有成员

    保护成员:以一个下划线开头.Python不会做特殊处理 私有成员:以两个下划线开头.Python会做mangling

  9. 深入理解javascript(一)

    此段文章摘自大叔的博客: 此文的目的是书写可维护的javascript代码. 最小的全局变量: JavaScript通过函数管理作用域.在函数内部声明的变量只在这个函数内部,函数外面不可用.另一方面, ...

随机推荐

  1. 一、python基础相关知识体系

    python基础 a. Python(解释型语言.弱类型语言)和其他语言的区别? 一.编译型语言:一次性,将全部的程序编译成二进制文件,然后在运行.(c,c++ ,go) 运行速度快.开发效率低 二. ...

  2. python读写hdf5及cdf格式文件

    Python write and read hdf5 file http://stackoverflow.com/questions/20928136/input-and-output-numpy-a ...

  3. WordPress主循环(The Loop)函数have_posts(),the_post()详解

    WordPress中调用文章标题是the_title();调用文章内容时用到the_content();调用文章的作者时用到the_author();等等这些函数,都需要在主循环中使用,下面就介绍一下 ...

  4. 用ab进行POST,GET压力测试,且定义header及json的内容

    这个以前没作过,找了文档.搞定. 要求时间的单curl测试的方式如下: time curl http://xxxxx/hq/restapi/isStart curl用来用post请求,且有header ...

  5. 根据C# 事件思想来实现 php 事件

    事件定义 当我们使用委托场景时,我们很希望有这样两个角色出现:广播者和订阅者.我们需要这两个角色来实现订阅和广播这种很常见的场景. 广播者这个角色应该有这样的功能:包括一个委托字段,通过调用委托来发出 ...

  6. AC日记——[HNOI2010]BOUNCE 弹飞绵羊 洛谷 P3203

    [HNOI2010]BOUNCE 弹飞绵羊 思路: SBlct: 代码: #include <bits/stdc++.h> using namespace std; #define max ...

  7. javascript实现与后端相同的枚举Enum对象

    ; (function (global, undefined) { global.Enum = function (namesToValues) { var enumeration = functio ...

  8. python访问web的利器:urllib2

    使用Python访问网页主要有三种方式: urllib, urllib2, httpliburllib比较简单,功能相对也比较弱,httplib简单强大,但好像不支持session1. 最简单的页面访 ...

  9. 可持久化01Trie树+LCA【p4592】[TJOI2018]异或

    Description 现在有一颗以\(1\)为根节点的由\(n\)个节点组成的树,树上每个节点上都有一个权值\(v_i\).现在有\(Q\)次操作,操作如下: 1\(\;x\;y\):查询节点\(x ...

  10. 【ModelMap】jsp中显示springmvc modelmap传递的对象

    最近在做一个小网站,功能非常基础,决定用springmvc搭建. 遇到一个问题,在controller向前端传值时,比如使用ModelMap传了一个字符串,modelmap.addattribute( ...