这可能有一个事先的答案,但我还没有找到它。
我有一些代码从数据库获取数据并返回一个实体,例如:
var customer1 = {first: "Greg", last: "Gum"};
如何向此对象添加一个getter,以便我可以调用FullName getter:
var theFullName = customer1.fullName;
我不明白的是将吸气剂添加到物体和将吸气剂添加到"类"之间的区别。这样它就可以用于该类型的所有未来对象。问题是创建对象的代码是一个黑盒子,所以我不能真正访问该代码。我不知道解决这个问题的最佳方法。
答案 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代码添加到您收到的每个对象,从而占用更多内存。
此外,由于您不知道如何创建此对象,因此您可能需要添加检查以确保first
和last
字符串实际存在,并且可能会添加特定值以防它们“T
修改强>:
由于您在评论中说您知道您的first
和last
名称将从不更改,并且您想要一个属性而不是一个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 );