I'm creating a GAS Spreadsheets Service based app that reads/writes & updates a row of data. I have a key-value object that represents a row of data, like the example data provided in snippet.
Use case:
var exampleData = [{weekendVolume=5186270,midweekVolume=16405609}];
// tuple length 2 of two known values
function _DataRecordObject( exampleData ) {
this._endOfWeek = new Date().endOfWeek();// Date.prototype method
}
var _DataRecordMethods = {
weekEnding: function() {
return this._endOfWeek.formatDateString()
},
weekMonth: function() {
return this._endOfWeek.getMonthLabelShort()
},
/* Processed volume */
weekendVolume: function() {
return 'weekendVolume'
},
midweekVolume: function() {
return 'midweekVolume'
},
totalVolumeProcessed: function() {
return _SumTotal(
this.weekendVolume(),
this.midweekVolume()
)
}
}
_DataRecordObject.prototype = _DataRecordMethods;
The new DataRecordObject
is prototype of a Sheet object that provides other helpful properties. _SumTotal
is a helper function.
My question:
When I call a new DataRecordObject with sheet range as argument, how do I update the exampleData object with the new properties such as totalVolumeProcessed
?
For example:
var foo = new _DataRecordObject( exampleData );
Console.log( foo );
//[{weekEnding='Aug-17',weekMonth=4,weekendVolume=5186270,midweekVolume=16405609,totalVolumeProcessed=21591879}]
I'd like the flexibility of using constructor-prototype inheritence, but using a boilerplate style template like Object-literals. My intuition suggests that I need to pass the data object keys when constructing a new dataRecordObject.
I'm a newcomer to JavaScript and have not yet gotten my head around inheritance, prototypes, and respective design-patterns. Factories and Modules, or perhaps Observers seem like appropriate patterns but my limited experience with JS is a limiting factor to solving my problem.
This might work for you.
1) Define the prototype as an object literal:
var methods = {
sayName: function() {
return "My name is " + this.name;
},
sayAge: function() {
return "I am " + this.age + " years old";
}
};
2) You can either make the 'methods' variable global or define it inside the following function. The function creates a new object using 'methods' variable as a prototype and populates it with values from the 'data' argument.
function createNewObj (data) {
var data = data || null;
var result = Object.create(methods);
for (var key in data) {
if (data.hasOwnProperty(key)) {
result[key] = data[key];
}
}
return result;
}
3) Bringing things together
function test() {
var data = {name: "John", age: "32"};
var row = createNewObj(data);
Logger.log(row.name); //logs 'John'
Logger.log(row.age); //logs '32'
Logger.log(row.sayName()); //logs 'My name is John'
Logger.log(row.sayAge()); //logs 'I am 32 years old'
Logger.log(Object.getPrototypeOf(row)); // returns contents of the 'methods' object literal
Logger.log(row.hasOwnProperty("sayName")); //logs 'false' because 'hasOwnProperty' doesn't go up the prototype chain
Logger.log("sayName" in row); //logs 'true' because 'in' goes up the chain
}
I suggest you take a look at this blog post by Yehuda Katz that dives deeper into prototypes http://yehudakatz.com/2011/08/12/understanding-prototypes-in-javascript/ It has examples of much cleaner code that might be helpful.
I've found a solution, which expands on @Anton-Dementiev 's response. His suggestion to read the Yehudi Katz was also most helpful.
The create new object function, _DataRecordObject
is where the solution lies..
function _DataRecordObject( RowDataObject ) {
this._endOfWeek = new Date().endOfWeek();// Date.prototype method
var data = RowDataObject || null;
var result = Object.create( _DataRecordMethods );
for (var key in data) {
if ( data.hasOwnProperty( key ) ) {
// if value is present in the RowDataObject,
// then assign its value to the result
result[key] = data[key];
} else {
// if not, the value is a method function,
// which should be evaluated in that context,
// and then return the method value as result
var foo = Object.getPrototypeOf( result )[ key ];
result[key] = foo.call( data );
}
}
return result;
}
//simples
Since the methods are passed as property functions, they need to be called as functions in that context.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.