JavaScript的public、private和privileged模式

Summary

  私有变量 在对象内部使用'var'关键字来声明,而且它只能被私有函数和特权方法访问。

  私有函数 在对象的构造函数里声明(或者是通过var functionName=function(){...}来定义),它能被特权函数调用(包括对象的构造函数)和私有函数调用。

  特权方法 通过this.methodName=function(){...}来声明而且可能被对象外部的代码调用。它可以使用:this.特权函数() 方式来调用特权函数,使用 :私有函数()方式来调用私有函数。

  公共属性 通过this.variableName来定义而且在对象外部是可以读写的。不能被私有函数所调用。

  公共方法 通过ClassName.prototype.methodName=function(){...}来定义而且可以从对象外部来调用。

  原型属性 通过ClassName.prototype.propertyName=someValue来定义。

  静态属性 通过ClassName.propertyName=someValue来定义。

  另外注意下这种写法: var 函数名=function 函数名(){...} 这个函数被调用时具有特权函数和私有函数的特性。

  例:

  

复制代码 代码如下:

  <html>

  <head>

  <title></title>

  <script type="text/javascript">

  function Container( param ) {

  function dec(){

  if ( secret > 0 ) {

  secret -= 1;

  setSecret( 7)

  alert( secret );

  return true;

  }

  else {

  // alert( "over"+this.member);

  return false;

  }

  }

  // this.dec = dec;

  //this.dec = function dec (){...} different from above code.

  function setSecret( num ){

  secret = num;

  }

  this.member = param;

  var secret = 3;

  var self = this;

  this.service = function () {

  if (dec()) {

  alert();

  }

  else {

  return null;

  }

  }

  }

  // ---------------------------------------

  function start(){

  alert( "Start" )

  var test = new Container( 'liuqi' );

  // test.setSecret( 2 );

  test.service();

  test.service();

  test.service();

  test.service();

  var test2 = new Container( 'liuqi' );

  //test2.service();

  // Container.dec();

  }

  </script>

  </head>

  <body>

  <div onclick="start()" style="color:blue">click me</div>

  </body>

  </html>

  JavaScript是世界上最被误解的编程语言。有人认为它缺少信息隐藏的特性,因为JavaScript对象不能拥有私有变量的方法。

  但是这是个误解。JavaScript对象可以拥有私有成员。

  对象

  JavaScript从根本上就是关于对象的。数组是对象,方法是对象,Object也是对象。什么是对象?对象就是键值对的集合。键是字符串,

  值可以是字符串,数字,布尔和对象(包括数组和方法)。对象通常被实现为Hashtable,这样值就可以被快速获取。

  如果值是一个函数,我可以称其为方法。当对象的方法被调用时,“this”变量则被赋予该对象。方法可以通过“this”变量访问实例

  变量。

  对象可以由初始化对象的方法 -- 构造函数产生。构造函数提供在其他编程语言中类提供的特性,包括静态变量和方法。

  Public

  对象的成员都是public成员。任何对象都可以访问,修改,删除这些成员或添加新成员。主要有两种方式来在一个新对象里放置成员:

  在构造函数里

  这种技术通常用来初始化public实例变量。构造函数的“this”变量用来给对象添加成员。

  Java代码

  

复制代码 代码如下:

  functin Container(param) {

  this.member = param;

  }

  functin Container(param) {

  this.member = param;

  }

  这样,如果我们构造一个新对象var myContainer = new Container('abc'),则myContainer.member为'abc'。

  在prototype里

  这种技术通常用来添加public方法。当寻找一个成员并且它不在对象本身里时,则从对象的构造函数的prototype成员里找。

  prototype机制用来做继承。为了添加一个方法到构造函数创建的所有对象里,只需添加到构造函数的prototype:

  Java代码

  

复制代码 代码如下:

  Container.prototype.stamp = function (string) {

  return this.member + string;

  }

  Container.prototype.stamp = function (string) {

  return this.member + string;

  }

  这样,我们可以调用该方法myContainer.stamp('def'),结果为'abcdef'。

  Private

  private成员由构造函数产生。普通的var变量和构造函数的参数都称为private成员。

  Java代码

  

复制代码 代码如下:

  function Container(param) {

  this.member = param;

  var secret = 3;

  var that = this;

  }

  function Container(param) {

  this.member = param;

  var secret = 3;

  var that = this;

  }

  该构造函数创建了3个private实例变量: param,secret和that。它们被添加到对象中,但是不能被外部访问,也不能被该对象自己的

  public方法访问。它们只能由private方法访问。private方法是构造函数的内部方法。

  Java代码

  

复制代码 代码如下:

  function Container(param) {

  function dec() {

  if (secret > 0) {

  secret -= 1;

  return true;

  } else {

  return false;

  }

  }

  this.member = param;

  var secret = 3;

  var that = this;

  }

  function Container(param) {

  function dec() {

  if (secret > 0) {

  secret -= 1;

  return true;

  } else {

  return false;

  }

  }

  this.member = param;

  var secret = 3;

  var that = this;

  }

  private方法dec检查secret实例变量。如果它大于0,则减少secret并返回true,否则返回false。它可以用来让这个对象限制用3次。

  按照惯例,我们定义一个private的that变量。这用来让private方法可以使用本对象。这样做是因为ECMAScript语言规范有一个错误,

  该错误导致不能正确的设置this给内部方法。

  private方法不能被public方法调用。为了让private方法有用,我们需要引入privileged方法。

  Privileged

  privileged方法可以访问private变量和方法,并且它本身可以被public方法和外界访问。可以删除或替代privileged方法,但是不能

  更改它或强制它泄露自己的秘密。

  privileged方法在构造函数里用this分配。

  Java代码

  

复制代码 代码如下:

  function Container(param) {

  function dec() {

  if (secret > 0) {

  secret -= 1;

  return true;

  } else {

  return false;

  }

  }

  this.member = param;

  var secret = 3;

  var that = this;

  this.service = function() {

  if (dec()) {

  return that.member;

  } else {

  return null;

  }

  };

  }

  function Container(param) {

  function dec() {

  if (secret > 0) {

  secret -= 1;

  return true;

  } else {

  return false;

  }

  }

  this.member = param;

  var secret = 3;

  var that = this;

  this.service = function() {

  if (dec()) {

  return that.member;

  } else {

  return null;

  }

  };

  }

  service是privileged方法。前三次调用myContainer.service()将返回'abc'。之后,它将返回null。service调用private的dec方法,

  dec方法访问private的secret变量。service对其他对象和方法可见,但是它不允许直接访问private变量。

  闭包

  由于JavaScript有闭包,public,private和privileged成员的模式是可行的。这意味着一个内部方法始终可以访问它的外部方法的

  var变量和参数,甚至在外部方法返回之后。这是JavaScript语言的一个非常强大的特性。当前没有展示如何发掘这种特性的JavaScript

  编程书籍,大多数甚至都没提到。

  private和privileged成员只能在对象被构造时产生。public成员则可以在任何时候添加。

  模式

  public

  Java代码

  

复制代码 代码如下:

  function Constructor(...) {

  this.membername = value;

  }

  Constructor.prototype.membername = value;

  function Constructor(...) {

  this.membername = value;

  }

  Constructor.prototype.membername = value;

  Private

  Java代码

  

复制代码 代码如下:

  function Constructor(...) {

  var that = this;

  var membername = value;

  function membername(...) {...}

  }

  // 注意: function语句

  // function membername(...) {...}

  // 是如下代码的简写

  // var membername = function membername(...) {...};

  function Constructor(...) {

  var that = this;

  var membername = value;

  function membername(...) {...}

  }

  // 注意: function语句

  // function membername(...) {...}

  // 是如下代码的简写

  // var membername = function membername(...) {...};

  Privileged

  Java代码

  

复制代码 代码如下:

  function Constructor(...) {

  this.membername = function (...) {...};

  }

  function Constructor(...) {

  this.membername = function (...) {...};

  }

  译者注:我认为可以简单的把privileged方法简单的看成是构造函数里的public方法,因为privileged方法可以被外界和public方法访问,

  而它自身又可以访问private变量。