javascript 属性访问器

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/12325791/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-26 15:55:47  来源:igfitidea点击:

javascript property accessors

javascriptaccessor

提问by Jeff Storey

In Javascript, it seems like using property accessors is not all that common (unlike in other OO languages such as Java for example).

在 Javascript 中,似乎使用属性访问器并不是那么常见(与其他 OO 语言(例如 Java)不同)。

If I have a Personobject with a name, defined as

如果我有一个Person带有名称的对象,定义为

function Person(name) {
   this.name = name;
}

A person's name is not going to change, but I do want to be able to access it when needed, so I could do something like:

一个人的名字不会改变,但我确实希望能够在需要时访问它,因此我可以执行以下操作:

function Person(name) {
   var name = name;
   this.getName = function() {
      return name;
   }
}

Even in a dynamic language, I think the principles of using getters and setters apply the same way they do to statically typed OO languages (e.g. encapsulation, adding validation, restricting access, etc)

即使在动态语言中,我认为使用 getter 和 setter 的原则也适用于静态类型的 OO 语言(例如封装、添加验证、限制访问等)

This question may get closed as subjective, but I'm curious as to why this behavior doesn't appear more often (e.g. Java developers would go crazy if everything was public).

这个问题可能会因为主观而被关闭,但我很好奇为什么这种行为不会更频繁地出现(例如,如果一切都是公开的,Java 开发人员会发疯)。

Is there a "standard" way to do this in javascript? I've seen Object.defineProperty, but not all browsers support that.

在javascript中是否有“标准”的方法来做到这一点?我见过Object.defineProperty,但并非所有浏览器都支持。

回答by Matt Whipple

Javascript has intercept-able property accessors:

Javascript 具有可拦截的属性访问器:

http://ejohn.org/blog/javascript-getters-and-setters/

http://ejohn.org/blog/javascript-getters-and-setters/

IMHO this is a far better solution to enforce the Uniform Access Principle than Java's more strict explicit getters, but that is also part of the simplicity and inflexibility of that language (Groovy for instance allows for similar interception).

恕我直言,这是一个比 Java 更严格的显式 getter 更好的执行统一访问原则的解决方案,但这也是该语言的简单性和不灵活的一部分(例如,Groovy 允许类似的拦截)。

回答by Jeremy J Starcher

I know my thoughts on the subject.

我知道我对这个主题的想法。

Getters and setters are evil.

getter 和 setter 是邪恶的。

Wait! Really! Bear with me a moment and let me explain.

等待!真的!请稍等,让我解释一下。

Just using a method to get and set a value is .. well .. kinda pointless. It doesn't protect, not really, and what you put in is what you get out.

只是使用一种方法来获取和设置一个值是.. 好吧.. 有点毫无意义。它不保护,实际上不是,你投入的就是你得到的。

On the other hand, I'm rather fond of methods that put information in, then get information back out. BUT here is the magic part! It isn't the same information. Not directly.

另一方面,我更喜欢将信息放入然后取出信息的方法。但这里是神奇的部分!这不是相同的信息。不直接。

function Person(name) {
  this.getFullName = function() {return this.firstName + " " + this.lastName;};
  this.setBirthday = function(date) { this.birthday = date; };

  this.getAge = function() { /* Return age based on the birthday */ };
  this.isOfLegalDrinkingAge function() { /* do your math here too */ };
}

But most of the time I'm just shoving static data in and getting static data out. What is the point of hiding it behind getters and setters?

但大多数时候我只是将静态数据放入并取出静态数据。将它隐藏在 getter 和 setter 后面有什么意义?

As a secondary reason, dealing with the DOM and most host objects, you set properties. You don't play with getters and setters. Not using them fits the rest of the 'flavor' of what JS coders do.

作为次要原因,处理 DOM 和大多数宿主对象时,您需要设置属性。你不玩 getter 和 setter。不使用它们符合 JS 编码人员所做的其余“风味”。

回答by Billy Moon

I think the answer is that emulating classes in javascript is not the common practice, because the language is actually prototypal.

我认为答案是在 javascript 中模拟类不是常见的做法,因为该语言实际上是原型。

Although it is possible to create class like structures (as in your example), they are not really like java classes, and as a programmer, you end up fighting with the nuances.

尽管可以创建类似结构的类(如您的示例中所示),但它们并不真正像 Java 类,并且作为程序员,您最终会与细微差别作斗争。

If however, you embrace the prototypal nature of javascript, you are rewarded by a different, yet cohesive, and simple structure for the language.

但是,如果您接受了 javascript 的原型性质,您将获得一种不同但有凝聚力且简单的语言结构。

It is not necessary to use getters and setters with prototypal structure, as you can simply set an object by, well, setting it to a value, and get it by, calling it as a value.

没有必要使用具有原型结构的 getter 和 setter,因为您可以简单地通过将对象设置为值来设置对象,然后通过调用它作为值来获取它。

Javascript does not force you to write structured code, and does not stop you from doing so. I think the culture that has grown up around javascript has developed a good coding style, that is perfectly valid, and different from any other language I use.

Javascript 不会强迫您编写结构化代码,也不会阻止您这样做。我认为围绕 javascript 发展起来的文化已经形成了一种很好的编码风格,这是完全有效的,并且不同于我使用的任何其他语言。

I know this answer is not definitive, and conclusive, but hopefully there are some ideas in there that help you to find the anser you are looking for.

我知道这个答案不是确定的和决定性的,但希望那里有一些想法可以帮助您找到您正在寻找的答案。

回答by labroo

I apologize if I dont understand the question correctly, but self executing functions are one way to make members public/private

如果我没有正确理解问题,我深表歉意,但自执行功能是使成员公开/私有的一种方式

var Person = function(){
  var _name = "Roger",
      self = { getName : function (){ return _name; }};
  return self;
}()

You can then access Person.getName() from anywhere , but not set _name.

然后您可以从任何地方访问 Person.getName(),但不能设置 _name。

回答by Morteza Tourani

This is what I used for local fields:

这是我用于本地字段的内容:

TYPE_DEFAULT_VALUE= {
    number: 0,
    string: "",
    array: [],
    object: {},
};

typeOf = function (object) {
    if (typeof object === "number" && isNaN(object))
        return NaN;
    try {
        return Object.prototype.toString.call(object).slice(8, -1).toLowerCase();
    }
    catch(ex) {
        return "N/A";
    };
};

getAccessor = function(obj, key, type, defaultValue) {
    if (defaultValue === undefined) 
        defaultValue =  TYPE_DEFAULT_VALUE[type] === undefined ? null : TYPE_DEFAULT_VALUE[type];
    return {
        enumerable: true,
        configurable: true,
        get: function () {
            if (obj[key] === undefined) 
                obj[key] = defaultValue;
            return obj[key];
        },
        set: function (value) {
            if (typeOf(value) === type)
                obj[key] = value;
        },
    };
}

LocalFields = function (fields, object) {
    /**
    * field properties
    * { 
    *   type: [ required ] ( number | string | array | object | ... ),
    *   defaultValue: [ optional ]
    * }
    */
    if (! fields)
        throw "Too few parameters ...";
    if (! object) 
        object = this;

    var obj = this;
    var fieldsAccessor = {};
    for(key in fields){
        field = fields[key];
        fieldHandler = key[0].toUpperCase() + key.substr(1);
        if(! field.type)
            throw "Type not set for field: " + key;

        fieldsAccessor[fieldHandler] = getAccessor(obj, fieldHandler, field.type, field.defaultValue)
    }
    Object.defineProperties(object, fieldsAccessor);
}

Now for each Class I can just call something like:

现在对于每个类,我可以调用类似的东西:

Person = function(){
    new LocalFields({
        id:     { type: "number" },
        name:   { type: "string" },
    }, this);
}

And then like VS getter and setter you'll call:

然后像 VS getter 和 setter 一样,你会调用:

var alex = new Person();
alex.Name = "Alex Ramsi";
console.clear();
console.info(alex.Name);