Web 技术研究所

我一直坚信着,Web 将会成为未来应用程序的主流

普及一下JS1.8中的get和set关键字

  你们知道“薛定谔的猫”吗?这个理论的核心思想就是观测者的观测这个动作会使被观测对象发生改变。如果薛猫的例子让你疑惑的话我就再举个例子。在暗室里有一个底片,现在需要做的是用肉眼观测它。但是在暗室中是一片漆黑的,如果不开灯就看不见任何东西。但是一旦开灯底片就会曝光而使观测结果发生偏差。这就意味着,在现实中,观测这个动作本身是会对被观测对象造成影响的。现在,我们用JavaScript来模拟一个类似的对象。 //定义对象
var obj=(function(){
  //私有成员i
  var i=0;
  return {
    //公共成员i
    get i(){return ++i}
  };
})();

//观测
console.log("张三说obj.i的值是"+obj.i);
console.log("李四说obj.i的值是"+obj.i);
console.log("王五说obj.i的值是"+obj.i);

console.log("(画外音:于是它们打起来了。)");

  这个就是一个使用get关键字把函数定义到属性上的例子。但是也许有人会觉得这个例子太麻烦,直接获取直接加不就行了?比如 //定义对象
var obj={i:0};

//观测
console.log("张三说obj.i的值是"+(++obj.i));
console.log("李四说obj.i的值是"+(++obj.i));
console.log("王五说obj.i的值是"+(++obj.i));
  是的,这样的代码也是一样的结果,但是有一点不同。这样输出的话它们仨就不会打起来了,因为结果毫无争议。这样的代码,i的递加变成在外部操作,耦合度就大大增加。这就会造成很多问题,比如把递加修改成每次加2就需要去寻找所有使用到的地方并修改。不过这个耦合度问题很容易解决,比如把代码这样改 //定义对象
var obj=(function(){
  //私有成员i
  var i=0;
  return {
    //公共成员getI
    getI:function(){
      return ++i;
    }
  };
})();

//观测
console.log("张三说obj.i的值是"+obj.getI());
console.log("李四说obj.i的值是"+obj.getI());
console.log("王五说obj.i的值是"+obj.getI());
  这个方法是使用函数来访问私有变量,这是个好方法,C++里经常这么用。但是这么用问题就绕回来了,因为这个代码比我第一次给出的代码还复杂。既然有简单的方法,为什么不用呢?
  上面这些就是get关键字的用法,其实说了get,set也自然会明白,因为基本是一样的。比如现在有个对象,它有个name属性,现在要让这个name属性的值永远保持大写字母。这就可以在给name赋值的时候给它转换,所以可以直接使用set方法完成。
//定义对象
var obj=(function(){
  //私有成员name
  var name=0;
  return {
    //公有成员name
    get name(){return name},
    set name(e){name=e.toUpperCase()}
  };
})();

//设置
obj.name="i'am not lower case letters.";

//输出
console.log(obj.name);
  输出结果自己猜,我就不贴出来了。set的使用方法和get基本是一样的,只不过它多了个参数,这个参数就是赋值操作时候给属性赋的值了。到这里这两个方法就没啥好说的了的(其实一开始就没啥好说的)。除了它们之外,还有一对非标准的方法。__defineGetter__和__defineSetter__这两个方法也可以做到同样的功能,只是它们不是标准方法,IE一直都不兼容它。这个两个东西的用法和set、set关键字截然不同。下面就用这两个方法实现上面这转换大写个功能吧。
var Obj=function(){};
//定义私有成员name(其实只是加个下划线伪装下)
Obj.prototype._name="";
//定义set方法
Obj.prototype.__defineGetter__("name",function(){
  return this._name;
});
//定义get方法
Obj.prototype.__defineSetter__("name",function(e){
  this._name=e.toUpperCase();
});

//实例化对象
var obj=new Obj;

//设置
obj.name="i'am not lower case letters.";

//输出
console.log(obj.name);
  __defineGetter__和__defineSetter__这俩家伙是原型对象上的方法,参数是定义的属性名和关联的函数。用这个方法定义的属性可以在对象实例化时被继承。但是可惜的是IE不兼容这个。
网名:
34.203.245.*
电子邮箱:
仅用于接收通知
提交 悄悄的告诉你,Ctrl+Enter 可以提交哦
神奇海螺
[查看全部主题]
各类Web技术问题讨论区
发起新主题
本模块采用即时聊天邮件通知的模式
让钛合金F5成为历史吧!
次碳酸钴的技术博客,文章原创,转载请保留原文链接 ^_^