在Javascript中创建类getter / setter的最佳方法?

时间:2010-12-15 14:29:32

标签: javascript oop getter-setter

来自C#/ PHP,我想在我用Javascript创建的类(函数)上有完整的getter / setter。

但是,在我遇到的大部分Javascript代码中,都没有使用getter和setter,而是使用简单的公共变量。

我很高兴在getter和setter上找到John Resig's article,但有些评论说它有些浏览器“不支持getter和setter”这让我感到困惑,因为它们不是我的“功能” Javascript,但更多的是一个使用基本Javascript语法的简单模式。这篇文章也是在2007年写的,所以它现在可能已经过时了。

Javascript中getter和setter的当前状态是什么?今天所有浏览器确实“支持”它们(无论这意味着什么)?它们是Javascript的有用编程模式还是Javascript类(函数)更好地使用公共变量?有没有比以下更好的方法来实现它们?

$(document).ready(function() {
    var module = new Module('idcode');
    module.set_id_code('new idcode');
    module.set_title('new title');
    $('body').html(module.get_id_code()+': '+module.get_title());
});

function Module(id_code, title) {
    var id_code = id_code;
    var title = title;

    //id_code
    this.get_id_code = function() {
        return id_code;
    }
    this.set_id_code = function(value) {
        id_code = value;
    }

    //title
    this.get_title = function() {
        return title;
    }
    this.set_title = function(value) {
        title = value;
    }
}

7 个答案:

答案 0 :(得分:15)

Firefox,Safari,Chrome和Opera(但不是IE)都内置了相同的非标准gettersetter机制.ECMAScript 5包含不同的语法currently making its way into browsers并将成为未来的标准。 IE 8已经具有此功能,但仅限于DOM节点,而不是常规的本机JavaScript对象。这就是语法:

var obj = {};

Object.defineProperty(obj, "value", {
    get: function () {
        return this.val;
    },
    set: function(val) {
        this.val = val;
    }
});

答案 1 :(得分:9)

我想你错过了这一点。 (或者其他的回答者可能会忽略这一点。)ECMAScript提供了一个“幕后”的getter / setter机制,所以

x.foo = 3;
y = x.foo;

真正转化为(某种)

x.PutValue("foo",3);
y = x.GetValue("foo");

其中PutValueGetValue未命名,而不是属性的setter和getter的直接可访问函数。 (参见ECMAScript standard, 3rd ed.,第8.7.1节和第8.7.2节)第3版似乎没有明确定义用户如何设置自定义getter和setter函数。 Mozilla的Javascript实现确实如此,例如, (这是JSDB使用Javascript 1.8):

js>x = {counter: 0};
[object Object]
js>x.__defineGetter__("foo", function() {return this.counter++; });
js>x.foo
0
js>x.foo
1
js>x.foo
2
js>x.foo
3
js>x.foo
4

语法是(至少到目前为止)浏览器特定的。特别缺乏Internet Explorer,至少根据this SO question

第5版ECMAScript标准似乎确实标准化了这种机制。请参阅this SO question on getters and setters


编辑:这个更实际的例子可能是出于您的目的:

function makePrivateObject()
{
   var state = 0;
   var out = {};
   out.__defineSetter__("foo", function(x) {});
   // prevent foo from being assigned directly
   out.__defineGetter__("foo", function() { return state; });
   out.count = function() { return state++; }
   return out;
}

js>x = makePrivateObject()
[object Object]
js>x.foo
0
js>x.foo = 33
33
js>x.foo
0
js>x.count()
0
js>x.count()
1
js>x.count()
2
js>x.foo
3

答案 2 :(得分:5)

怎么样:

function Module(id_code, title) {
    var id_code = id_code;
    var title = title;

    var privateProps = {};

    this.setProperty = function(name, value) {
      // here you could e.g. log something
      privateProps[name] = value;
    }

    this.getProperty = function(name) {
      return privateProps[name];
    }
}

此处的getter和setter方法作用于私有对象,该私有对象用于存储无法从任何其他方法访问的属性。例如,只要修改了属性(getter / setter方法的目的之一),就可以实现一个setter(或getter)来记录或执行ajax或其他任何东西。

答案 3 :(得分:5)

您实际上可以在javascript中定义setter和getter,而不仅仅是模仿它们。我认为它适用于除IE8及以下版本的所有浏览器。

$(document).ready(function() {
  var module = new Module('idcode');
  module.id = 'new idcode';
  module.title = 'new title';
  $('body').html(module.id + ': ' + module.title);
});

function Module(id, title) {
  return {
    id_code: id_code,
    _title: title,

    get id() {
      return id_code;
    },
    set id(value) {
      id_code = value;
    },

    get title() {
      return _title;
    },
    set title(value) {
      title = value;
    }
  }
};

答案 4 :(得分:2)

我喜欢这个:

//  Module
var Module = function() {

    // prive getter/setter value
    var __value;

    // private getter/setter method
    var _value = function() {
        if(!arguments.length) return __value;
        else __value = arguments[0];
    };

    // output/public     
    return {
        value: _value
    };
}

答案 5 :(得分:1)

Getters和setter不是功能,但是对于不支持属性语法的语言,“设计模式”(在这种情况下代码膨胀)。

由于Javascript不需要getter和setter,因此您不想编写它们。使用您可以使用的语言功能和在一种语言中运行良好的习语在另一种语言中效果不佳。

我最喜欢的一句话来自Python的社区:

  

我们都同意成年人

讨论为什么不需要私有变量和信息隐藏。

可以找到引用here

了解语言为您提供的内容并接受其文化和规则。

答案 6 :(得分:0)

我赞成的一种可靠的语义方式是使用settersgetters。例如,我创建了以下对象:

var myComplexObject = {
  changelog: {},
  log: function(name, val) {
    console.log("set " + name + " to " + val);
    if (!this.changelog[name])
      this.changelog[name] = [];
    this.changelog[name].push(val);
  },
  set o (val) {
    this.log("o", val);
  },
  get o () {
    console.log("You will never know the true value!");
    return 42;
  }
}

在这里,每当您阅读或修改o的值时,行为都会自定义。例如,以下代码行及其控制台输出:

myComplexObject.o = "oxygen";
set o to oxygen

然后,在此示例中,尝试读取值会导致:

var read = myComplexObject.o;
console.log(read);
You will never know the true value!
42

并且,在此示例中,将记录您设置的每个新值:

myComplexObject.o = "Oh no!";
console.log(myComplexObject.changelog.o);
set o to Oh no!
["oxygen", "Oh no!"]