17

来自 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;
    }
}
4

7 回答 7

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;
    }
});
于 2010-12-15T15:54:22.773 回答
9

我认为你没有抓住重点。(或者其他回答者可能没有抓住重点。)ECMAScript 提供了一个“幕后”的 getter/setter 机制,因此

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

真的翻译成(有点)

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

wherePutValueGetValue是未命名的,属性的 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

语法是(或至少到目前为止)特定于浏览器的。尤其是缺少 Internet Explorer,至少根据这个 SO question

ECMAScript 标准的第 5 版似乎对这种机制进行了标准化。请参阅有关 getters 和 setters 的 SO 问题


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

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
于 2010-12-15T14:58:44.320 回答
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 方法作用于一个私有对象,该对象用于存储无法从任何其他方法访问的属性。因此,例如,您可以实现一个 setter(或 getter),在修改属性时记录或执行 ajax 或其他任何操作(getter/setter 方法的目的之一)。

于 2010-12-15T14:38:00.567 回答
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;
    }
  }
};
于 2013-07-12T03:03:16.500 回答
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
    };
}
于 2014-03-20T22:54:49.613 回答
0

Getter 和 setter 不是特性,而是不支持属性语法的语言的“设计模式”(在这种情况下是代码膨胀)。

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

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

我们都是同意这里的成年人

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

报价可以在这里找到。

了解该语言为您提供什么,并接受它的文化和规则。

于 2010-12-15T14:34:24.263 回答
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!"]
于 2015-08-04T15:10:19.950 回答