JavaScript Accessor实现说明

  第一种算是比较常见了,通过闭包Store Value从而实现accessor,适用于所有浏览器.

  

复制代码 代码如下:

  function Sandy(val){

  var value = val;

  this.getValue = function(){

  return value;

  };

  this.setValue = function(val){

  value = val;

  };

  }

  //usage

  var sandy = new Sandy("test");

  sandy.value

  // => undefined

  sandy.setValue("test2")

  sandy.getValue

  下面是JavaScript权威指南(中文第五版)中P152页使用闭包的一个例子.

  

复制代码 代码如下:

  function makeProperty(o, name, predicate) {

  var value; //This is property value;

  //The setter method simply returns the value

  o['get' + name] = function() { return value;};

  //The getter method stores the value or throws an exception if

  //the predicate rejects the value

  o['set' + name] = function(v) {

  if (predicate && !predicate(v) {

  throw 'set' + name + ': invalid value ' + v;

  } else {

  value = y;

  }

  }

  }

  //The following code demenstrates the makeProperty() method

  var o = {}; // Here is an empty object

  //Add property accessor methods getName and setName

  //Ensure that only string values are allowed

  makeProperty(o, 'Name', function(x) { return typeof x == 'string'; });

  o.setName('Frank');   //Set the property value;

  print(o.getName());   //Get the property value

  o.setName(0); //Try to set a value of the wrong type

  第二种方法是使用__defineSetter__与__defineGetter__来实现accessor,看下划线就知道它们并非标准,适用于Firefox 2.0+, Safari 3.0+, Google Chrome 1.0+ 和 Opera 9.5+ ,方法使用见MDN.

  

复制代码 代码如下:

  function Sandy(val){

  var value = val,

  _watch = function(newVal) {

  console.log('val is Changed to : ' + newVal);

  }

  this.__defineGetter__("value", function(){

  return value;

  });

  this.__defineSetter__("value", function(val){

  value = val;

  _watch(val);

  });

  }

  var sandy = new Sandy("test");

  sandy.value

  // => test

  sandy.value = "test2";

  // => 'val is Changed to : test2'

  sandy.value

  // => "test2"

   除了__defineG/Setter__外, 你还可以使用'set'、'get'关键字在在原型对象上定义accessor,对于单个对象同样适用, 适用于Firefox 2.0+, Safari 3.0+, Google Chrome 1.0+ 和 Opera 9.5+.

  

复制代码 代码如下:

  function Sandy(val){

  this.value = val;

  }

  Sandy.prototype = {

  get value(){

  return this._value;

  },

  set value(val){

  this._value = val;

  }

  };

  //Or

  var sandy = {

  '_value' : 'sandy',

  get value() {

  return this._value;

  },

  set value(val) {

  this._value = val;

  }

  }

  最后一种方法,用到了Object的静态方法defineProperty,作用于单个对象,该方法应该属于ES5的范畴了,目前似乎只有Chrome 支持这种方法,其实Ie8也支持,但操作对象仅限于Dom节点(Dom node),见IEBlog,该方法的使用见MDN.

  

复制代码 代码如下:

  var sandy = {}, rValue;

  Object.defineProperty(sandy, 'value' ,

  {

  'set' : function(val) {

  rValue = val;

  },

  'get' : function() {

  return rValue;

  },

  'enumerable' : true,

  'configurable' : true

  }

  )

  //Ie8+

  Object.defineProperty(document.body, "description", {

  get : function () {

  return this.desc;

  },

  set : function (val) {

  this.desc = val;

  }

  });

  document.body.description = "Content container";

  // document.body.description will now return "Content container"

  ‘enumerable','configuralbe' 属于ES5规范中的Property Attributes(属性特性),在这里就不做讨论了,有兴趣的Google或者直接去看ES5的文档. ^ ^