【问题标题】:object property function to generate setter and getter对象属性函数生成setter和getter
【发布时间】:2022-12-24 19:52:20
【问题描述】:
person = {
id: 1,
name: 'John',
phone: '123-456-789',
getSetGen: function(){

for(var key in this){
    this[`set${key}`]=function(value){
        this[key] = value;
        console.log(this[key]);
    }

    this[`get${key}`]=function(){
        console.log(this[key]);
        return this[key];
    }
    

// for(key in this){
//     console.log(this[key]);
//     if(key!='getSetGen'){
//         Object.defineProperty(this, `Set${key}`, {
//             set : function (value) {
//                 this[key] = value;
//             }
//         });

//         Object.defineProperty(self, `Get${key}`, {
//             get : function () {
//                 return this.key;
//             }
//         });
//     }
// }
}
}



person.getSetGen()

person.getname();

我正在尝试创建一个函数属性来为对象生成 getter 和 setter,并且可以与其他对象一起使用。

运行上面的代码后,setter 和 getter 不起作用,只是将函数作为“this[key]”而不是实际的属性和对象

【问题讨论】:

  • 让我们从为什么开始。如果他们所做的只是将操作转发给属性本身,为什么还需要这些“getters/setters”。为什么不直接使用该属性?在你的代码中,你混合了两种方法,正确的 getter/setter “看起来”像常规属性,并且像它们一样被访问。并获取/设置方法,这被称为非常相似的方法。你想要哪一个?
  • 这只是它可以做什么的模拟,但如果我想将属性设为私有,我将需要 setter 和 getter。对于第二个原因,生成 setter 和 getter 将允许将具有公共属性的对象转换为具有私有属性的对象,并改用 setter 和 getter。
  • 长话短说:我假设你来自不同的编程语言?您愿意跳多少个循环,您愿意承受多少性能影响才能拥有私有属性?是的 JS 最近获得了私有字段,在此之前我们已经用闭包模拟了它们,但在大多数情况下这是不值得的。我仍然认为按照惯例隐私是更好的选择。
  • 本来,这就是setter和getter的目的。此外,如果我想在添加属性之前向 setter 和 getter 添加一些代码并在不影响其余代码的情况下执行此操作,我可以通过 setter 和 getter 函数来完成。
  • 我想我发现了你的问题。 for(var key in this) 不是块范围的for(key in this) 甚至是一个全局变量),因此您的所有方法都指向您迭代的相同(最后一个)key。这里:What is the difference between "let" and "var"?。使用for(const key in this)

标签: javascript object getter-setter accessor


【解决方案1】:

编辑(现在我明白了OP的意图)

定义包装对象现有字段的属性。

  1. 遍历字段
  2. 使用字段名称为每个字段添加一个属性。

    像这样,看代码中的cmets:

    let myObj = {
        id: 1,
        name: 'tomato',
    };
    
    for(let fieldName of Object.keys(myObj)) {
        console.log(`fieldName = ${fieldName}`);
        Object.defineProperty(myObj, fieldName + "_property", {
            set: function(value) {
                this[fieldName] = value;
            },
            get: function() {
                return this[fieldName];
            }
        });
    }
    
    myObj.id_property = 55; // setting id_property will set id
    console.log(myObj.id); // so this will write 55
    
    myObj.id = 123; // setting id
    console.log(myObj.id_property); // this will write 123 because id_property returns id field
    

    [Obsolete("Previous answer")]

    在尝试定义属性的通用方法之前,让我们尝试定义一个普通的静态属性。例如,这里是一些名为 myObj 的对象上名为 Xyz 的属性的代码。

    如您所见,您可以在对defineProperty 的一次调用中定义getter 和setter。

    var myObj = {};
    Object.defineProperty(myObj, `Xyz`, {
        set: function (value) {
            this['_Xyz'] = value;
        },
        get: function() {
            return this._Xyz;
        }
    });
    

    另请注意,我在这里使用了一个名为 _Xyz 的“支持字段”。

    因此,为了使事物通用,我们要定义一个名为“Something”的属性并使用一个名为“_Something”的支持字段。

    然后您可以轻松地为此创建一个循环。

    然后当你运行循环时,你可以像上面这样访问属性:

    myObj.Xyz = 1; console.log(myObj.Xyz); // writes 1


    另请注意,当您设置和获取属性时,您不使用括号。例如。 myObj.myProperty() 不正确。通常,我们也不向属性名称添加 getset 前缀。我们只是说 myProperty 而不是 getMyProperty

【讨论】:

  • 我不明白定义新属性的意义。这里的问题是通过 setter 和 getter 函数获取和设置现有属性的值。换句话说“this[_Xyz] = value”,_Xyz 应该是现有属性而不是新属性
  • @IBdr 但是你没有做同样的事情,创建一个新领域this[`set${key}`] 作为(私有)支持字段 this[key] 的设置者。
  • 是的,新字段用于 setter 和 getter 方法,而不是新属性。就像在我的代码中一样,我有“id”属性,我将使用 setter 来更改它的值,而不是添加新属性
  • @IBdr 那是不可能的。你要么有一个存储值的数据属性,要么有一个带有 getter/setter 函数的访问器属性(需要将值存储在别处,无论是另一个属性还是局部变量),你不能同时拥有相同的属性名称。
  • @IBdr 我不确定你为什么要用属性包装字段,也许你希望它们执行代码,而不仅仅是在访问它们时设置/获取一个值......无论如何,我用你想要的更新了我的答案,请参阅示例和代码 cmets
猜你喜欢
  • 1970-01-01
  • 2010-09-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多