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

Edw*_*uay 17 javascript oop getter-setter

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

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

我很高兴找到John Resig关于getter和setter 的文章,但是有些评论说它有些浏览器"不支持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;
    }
}
Run Code Online (Sandbox Code Playgroud)

Tim*_*own 15

Firefox,Safari,Chrome和Opera(但不是IE)都内置了相同的非标准gettersetter机制.ECMAScript 5包含一种不同的语法,目前正在进入浏览器并将成为未来的标准.IE 8已经具有此功能,但仅限于DOM节点,而不是常规的本机JavaScript对象.这是语法的样子:

var obj = {};

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


Jas*_*n S 9

我想你错过了这一点.(或者其他的应答者都缺少了这一点.)的ECMAScript提供了一个"背后的幕后"的getter/setter机制,使

x.foo = 3;
y = x.foo;
Run Code Online (Sandbox Code Playgroud)

真的翻译成(有点)

x.PutValue("foo",3);
y = x.GetValue("foo");
Run Code Online (Sandbox Code Playgroud)

where PutValueGetValue是未命名的,不是属性的setter和getter的直接访问函数.(参见ECMAScript标准,第3版,第8.7.1节和第8.7.2节)第3版似乎没有明确定义用户如何设置自定义getter和setter函数.Mozilla的Javascript实现确实做到了,例如(这是在使用Javascript 1.8的JSDB中):

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
Run Code Online (Sandbox Code Playgroud)

语法是(或至少到目前为止)浏览器特定的.特别是缺少Internet Explorer,至少根据这个SO问题.

第5版ECMAScript标准似乎确实标准化了这种机制.在getter和setter上看到这个问题.


编辑:一个更实际的例子,也许,为了您的目的:

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
Run Code Online (Sandbox Code Playgroud)

  • 这可能是它们在内部处理的方式,但从技术上讲,如果我无法控制对它们的访问,它们仍然是"公共变量".getter和setter对我来说的优势在于我可以确定例如"Salary"属性只能在内部更改,或者例如在更改时,(a)记录更改,(b)并触发事件,除非我有getter/setter访问器方法,否则我无法为我的类定义这一功能层. (2认同)
  • 啊 - 但这里有一个微妙的; 如果你有能力使用自定义getter/setter方法,那么你可以.我会编辑我的答案. (2认同)

sje*_*397 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];
    }
}
Run Code Online (Sandbox Code Playgroud)

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

  • 这没有提供任何有用的功能.setProperty和getProperty是公共函数,因此这只是增加了一个间接层.它不会添加调用私有getter和setter函数的功能. (2认同)

Pue*_*Pop 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;
    }
  }
};
Run Code Online (Sandbox Code Playgroud)


dar*_*ioo 0

getter 和 setter 不是功能,而是不支持属性语法的语言的“设计模式”(在本例中为代码膨胀)。

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

我最喜欢的引言之一来自 Python 社区:

我们都是同意的成年人

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

可以在此处找到报价。

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

  • -1 属性修改器对于正确封装至关重要。允许对象进入另一个对象的内部会导致可怕的错误!它无法保持其内部状态的一致性。此外,该语言本身也支持 getter 和 setter。 (2认同)