Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/471.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
javascript属性访问器_Javascript_Accessor - Fatal编程技术网

javascript属性访问器

javascript属性访问器,javascript,accessor,Javascript,Accessor,在Javascript中,使用属性访问器似乎并不常见(不像其他OO语言,例如Java) 如果我有一个名为的Person对象,定义为 function Person(name) { this.name = name; } 一个人的名字不会改变,但我确实希望能够在需要时访问它,因此我可以执行以下操作: function Person(name) { var name = name; this.getName = function() { return name;

在Javascript中,使用属性访问器似乎并不常见(不像其他OO语言,例如Java)

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

function Person(name) {
   this.name = name;
}
一个人的名字不会改变,但我确实希望能够在需要时访问它,因此我可以执行以下操作:

function Person(name) {
   var name = name;
   this.getName = function() {
      return name;
   }
}
Person = function(){
    new LocalFields({
        id:     { type: "number" },
        name:   { type: "string" },
    }, this);
}
即使在动态语言中,我认为使用getter和setter的原则也适用于静态类型的OO语言(例如封装、添加验证、限制访问等)

这个问题可能是主观的,但我很好奇为什么这种行为不经常出现(例如,如果一切都是公开的,Java开发人员会发疯)


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

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


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

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

虽然可以创建类结构(如您的示例中所示),但它们并不真正像java类,作为程序员,您最终会遇到细微差别

但是,如果您接受javascript的原型特性,那么您将得到一种不同的、有凝聚力的、简单的语言结构

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

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


我知道这个答案不是决定性的,但希望其中有一些想法能帮助你找到你想要的答案。

我知道我对这个问题的看法

成功者和成功者都是邪恶的

等等!真正地请等我一会儿,让我解释一下

仅使用方法获取和设置值是。。好。。有点无意义。它不能保护你,不是真的,你投入的是你得到的

另一方面,我比较喜欢先输入信息,然后再输出信息的方法。但这里是神奇的部分!这是不同的信息。不直接

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 */ };
}
但大多数时候,我只是将静态数据推入并取出静态数据。把它藏在能手和二传手后面有什么意义


第二个原因是,在处理DOM和大多数主机对象时,需要设置属性。你不能和接球手和二传手一起比赛。不使用它们符合JS程序员的其他“风格”。

如果我没有正确理解这个问题,我很抱歉,但是自动执行函数是让成员公开/私有的一种方法

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

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

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

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);
}
现在,对于每个类,我可以称之为:

function Person(name) {
   var name = name;
   this.getName = function() {
      return name;
   }
}
Person = function(){
    new LocalFields({
        id:     { type: "number" },
        name:   { type: "string" },
    }, this);
}
然后像VS getter和setter一样,您将调用:

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

我认为这可能部分与减少带宽负载的愿望有关。额外的标记意味着导线上的额外位。在这样一个小例子中,它可能看起来不相关,但在一个跨越数万行的健壮应用程序中,它可能变得重要。额外的定义还意味着客户端上额外的内存使用,与我之前的评论相同。我认为已经给出的答案表明,这不是一个好问题,因此很容易得到基于观点的答案。@Billymon——不知道他是否可以将用户名更改为“Javascript传教士”,谢谢你的解释。我认为这不是javascript的“味道”这一事实是我在这里真正得到的。我的问题是想知道这些东西是函数还是属性。有时,这似乎相当武断。Person.firstName有效,但Person.firstName()无效,相反,我需要使用Person.fullName()而不是Person.fullName…@CuddleBunny我明白你的意思。您可以始终使用
typeof
运算符,查看它是否是一个函数<例如,code>console.log(typeof Person.firstName)。当然,我可以做到。我总是使用VisualStudio在JS中进行开发,它往往会告诉我它是什么。我只是喜欢一致性。在实践中,这种情况经常出现吗?或者您通常会看到直接属性访问吗?除非您需要修改访问器逻辑,否则您将使用直接属性访问:然后您将使用拦截。您可能需要问自己,如果getter和setter不起任何作用,为什么要在Java中使用它们:封装原则背后的实际原因是什么。理论上,这个想法是,如果您想在getter或setter中添加一些其他行为(例如日志记录、验证等)。但事实上,这种情况在简单属性上并不经常发生,因此它更像是一种Java约定(我更喜欢groovy的做法,即不显式声明getter和setter,而是生成并自动调用它们,但允许编写直接属性访问的语法),客户端代码中可维护的更改。在Java(和类似的语言)中,使用直接属性访问会使内部更改和Decorator等模式复杂化。也许不经常需要,但小的投资可以带来大的回报。语言提供了一种更灵活的连接方式(包括