如何将getter添加到对象

时间:2015-11-23 00:31:39

标签: javascript

这可能有一个事先的答案,但我还没有找到它。

我有一些代码从数据库获取数据并返回一个实体,例如:

   var customer1 = {first: "Greg", last: "Gum"};

如何向此对象添加一个getter,以便我可以调用FullName getter:

   var theFullName = customer1.fullName;

我不明白的是将吸气剂添加到物体和将吸气剂添加到"类"之间的区别。这样它就可以用于该类型的所有未来对象。问题是创建对象的代码是一个黑盒子,所以我不能真正访问该代码。我不知道解决这个问题的最佳方法。

4 个答案:

答案 0 :(得分:4)

如果您只想在已返回的对象文字上定义属性,只需使用Object.defineProperty

var cdata = {first: 'Foo', last: 'Bar'}
Object.defineProperty(cdata, 'fullName', {
  get: function() { return this.first + ' ' + this.last; }
});

console.log(cdata.fullName); // Foo Bar

但是,如果要从返回的文字创建新对象,则可以使用以下方法:

function Customer(data) {
  var k;
  for (k of Object.keys(data)) {
    Object.defineProperty(this, k, {
      value: data[k]
    });
  }

  Object.defineProperty(this, 'fullName', {
    get: function() { return this.first + ' ' + this.last; }
  });
}

var cdata = {first: 'Foo', last: 'Bar'};
var customer = new Customer(cdata);

console.log(customer.fullName); // Foo Bar

但更有效的内存方法是:

function Customer(data) {
  var k;
  for (k of Object.keys(data)) {
    Object.defineProperty(this, k, {
      value: data[k]
    });
  }
}

Customer.prototype = {
  get fullName() {
    return this.first + ' ' + this.last;
  }
};

var cdata = {first: 'Foo', last: 'Bar'};
var customer = new Customer(cdata);

console.log(customer.fullName); // Foo Bar

第一个Customer定义添加了一个实例属性fullName,它将为每个创建的Customer实例消耗内存。第二个定义将fullName属性定义为原型属性,从而节省了少量内存。

答案 1 :(得分:3)

编辑:您正在寻找:

var customer1 = {first: "Greg", last: "Gum"};
Object.defineProperty(customer1, "fullName", {
  get: function() { return this.first + ' ' + this.last; }
});

var theFullName = customer1.fullName;

更普遍的方法:

function addGetter(obj, name, func) {
    Object.defineProperty(obj, name, {
      get: func
    });
}

var customer1 = {first: "Greg", last: "Gum"};
addGetter(customer1, "fullName", function() { return this.first + ' ' + this.last; } )

var theFullName = customer1.fullName;

你甚至可以将对象原型归类为customer1.getter("fullName", function() { return this.first + ' ' + this.last; } )

OLD: 我有一个很好的方法用TypeScript做它,它编译成这个JavaScript:

var Customer = (function () {
    function Customer(first, last) {
        this.first = first;
        this.last = last;
    }
    Object.defineProperty(Customer.prototype, "fullName", {
        get: function () { return this.first + " " + this.last; },
        enumerable: true,
        configurable: true
    });
    return Customer;
})();
var customer1 = new Customer("Greg", "Gum");
var theFullName = customer1.fullName;

然而,TypeScript看起来更好:

class Customer {
    first: string
    last: string

    constructor(first: string, last: string) {
        this.first = first
        this.last = last        
    }

    get fullName() { return this.first + " " + this.last }
}

var customer1 = new Customer("Greg", "Gum")
var theFullName = customer1.fullName

你可以玩它here

答案 2 :(得分:0)

您可以解决此问题的一种方法是创建自己的包装类Customer,它包装接收到的对象并添加getter。

此外,您希望在Costumer类的原型上添加getter,以便它只定义一次并可用于所有将来的实例。类似的东西:

function Customer(c) {
    this.firstName = c.first;
    this.lastName = c.last;
}

Customer.prototype.getFullName = function() {
    return this.firstName + " " + this.lastName;
}

你将使用它:

var c = getCustomerFromBlackBox();
var customer = new Customer(c);

如果您使用的是ES6,那么您可以利用其更强大的语法:

class Customer {

  constructor(c) {
    this.firstName = c.first;
    this.lastName = c.last;
  }

  fullName() { 
    return this.firstName + " " + this.lastName;
  }
}

根据你想要编辑收到的对象本身的评论,那么你可以这样做:

var c = getCustomerFromBlackBox();

if(typeof c === 'object' && c !== null) {     // make sure c is an object
    c.getFullName = function() {              // add a getter
        return this.first + " " + this.last;
    }
}

请注意,这会将getter代码添加到您收到的每个对象,从而占用更多内存。

此外,由于您不知道如何创建此对象,因此您可能需要添加检查以确保firstlast字符串实际存在,并且可能会添加特定值以防它们“T

修改

由于您在评论中说您知道您的firstlast名称将从不更改,并且您想要一个属性而不是一个getter函数,可以在每次阅读客户时添加此属性:

var c = getCustomerFromBlackBox();
c.fullName = c.first + " " + c.last; // Can also add same checks to make sure c is an object and c.first and c.last are strings

同样,这被添加到每个对象,并且具有与添加直接getter函数(而不是原型)相似的内存开销

我错过的一个好方法是使用Object.defineProperty中显示的James Sumner's answer

Object.defineProperty(c, 'fullName', {
  get: function() { return this.first + " " + this.last; }
});

此方法直接在对象(而不是原型)上添加属性,并且还使属性不可变意味着您不会意外删除它。

答案 3 :(得分:0)

您必须创建一个构造函数以在JavaScript中使用原型继承。

E.g。如下。检查JS Fiddle

var customer1Data = {first: "Greg", last: "Gum"};

var Customer = function(customerData ) {
    this.first = customer1Data.first;
    this.last = customer1Data.last;
}

Customer.prototype.fullName = function() {
   return this.first + ' '+this.last;
}

var customer1 = new Customer(customer1Data );