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

发布于 2024-10-07 22:10:51 字数 1190 浏览 7 评论 0原文

来自 C#/PHP,我希望在使用 Javascript 创建的类(函数)上有完整的 getters/setters。

然而,在我遇到的大部分 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;
    }
}

Coming from C#/PHP, I would like to have full getters/setters on the classes (functions) that I create with Javascript.

However, in much of the Javascript code I have encountered, getters and setters are not used, rather simple public variables.

I was pleased to find John Resig's article on getters and setters, but some comments on it which state that some browsers "do not support getters and setters" which is confusing to me since they are not a "feature" of Javascript but more of a simple pattern which uses basic Javascript syntax. This article was also written in 2007 so it could be outdated by now.

What is the current state of getters and setters in Javascript? Are they indeed "supported" by all browsers today (whatever that means)? Are they a useful programming pattern for Javascript or are Javascript classes (being functions) better off with public variables? Is there a better way to implement them than the following?

$(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;
    }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

叹倦 2024-10-14 22:10:51

Firefox、Safari、Chrome 和 Opera(但不包括 IE)都具有相同的非标准 getter 和内置的 setter 机制。ECMAScript 5 包含不同的语法,即 目前正在进入浏览器,并将成为未来的标准。 IE 8 已经具有此功能,但仅限于 DOM 节点,而不是常规的原生 JavaScript 对象。语法如下:

var obj = {};

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

Firefox, Safari, Chrome and Opera (but not IE) all have the same non-standard getter and setter mechanism built in. ECMAScript 5 includes a different syntax that is currently making its way into browsers and will become the standard in future. IE 8 already has this feature, but only on DOM nodes, not regular native JavaScript objects. This is what the syntax looks like:

var obj = {};

Object.defineProperty(obj, "value", {
    get: function () {
        return this.val;
    },
    set: function(val) {
        this.val = val;
    }
});
梦冥 2024-10-14 22:10:51

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

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

实际上可以转化为(某种程度上)

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

其中 PutValueGetValue 是未命名的、无法直接访问属性的 setter 和 getter 的函数。 (请参阅 ECMAScript 标准,第三版,第 8.7.1 节和 8.7.2 节)第三版似乎没有明确定义用户如何设置自定义 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 问题

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

You're missing the point, I think. (Or maybe the other answerers are missing the point.) ECMAScript provides a "behind-the-scenes" getter/setter mechanism, so that

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

really translates into (sort of)

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

where PutValue and GetValue are unnamed, not directly accessible functions for setters and getters for properties. (See the ECMAScript standard, 3rd ed., section 8.7.1. and 8.7.2) The 3rd edition doesn't seem to explicitly define how users can set up custom getters and setter functions. Mozilla's implementation of Javascript did and still does, e.g. (this is in JSDB which uses 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

The syntax is (or at least has been so far) browser-specific. Internet Explorer in particular is lacking, at least according to this SO question.

The 5th edition of the ECMAScript standard does seem to standardize on this mechanism. See this SO question on getters and setters.


edit: A more practical example, perhaps, for your purposes:

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
凌乱心跳 2024-10-14 22:10:51

怎么样:

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),每当修改属性时(getter/setter 方法的目的之一),它就会记录或执行 ajax 或其他操作。

How about:

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];
    }
}

The getter and setter methods here act on a private object used to store properties that cannot be accessed from any other methods. So you could, for example, implement a setter (or getter) that logs or does ajax or whatever, whenever a property is modified (one of the purposes of getter/setter methods).

泅渡 2024-10-14 22:10:51

实际上,您可以在 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;
    }
  }
};

You can actually define setters and getters in javascript and not just mimick them. I think it works on every browser except IE8 and below.

$(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;
    }
  }
};
稀香 2024-10-14 22:10:51

我喜欢这个:

//  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
    };
}

I like this :

//  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
    };
}
网名女生简单气质 2024-10-14 22:10:51

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

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

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

我们都是同意的成年人

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

。可以在此处找到该引用。

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

Getters and setters aren't features, but "design patterns" (code bloat in this case) for languages that don't support property syntax.

Since Javascript doesn't need getters and setters, you don't want to write them. Use the language features that are available to you and idioms that work great in one languages don't work so well in another.

One of my favorite quotes comes from Python's community:

We're all consenting adults here

when discussing why private variables and information hiding isn't needed.

The quote can be found here.

Learn what the language offers you and embrace its culture and rules.

疯到世界奔溃 2024-10-14 22:10:51

我喜欢的一种可靠的语义方式是使用 setter getter。例如,我创建了以下对象:

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!"]

One reliable, semantic way I've favored is to use setters and getters. For example, I created the following object:

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;
  }
}

In here, whenever you read or modify the value of o, the behavior is customized. Take, for example, the following line of code and its console output:

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

Then, in this example, attempting to read the value results in this:

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

And, in this example, each new value you set is logged:

myComplexObject.o = "Oh no!";
console.log(myComplexObject.changelog.o);
set o to Oh no!
["oxygen", "Oh no!"]
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文