javascript: define variable to object like a magic setter - javascript

I am trying to set some variable to an object. But i want it to be set like the code below
is there a way to set a variable like this?
myObject = {};
myObject.save = function (var) {
console.log(var);
}
myObject.users.save(); // must output 'users';
myObject.fruits.save(); // output fruit;
the save method is just an example method. it means that i need to chain a method on the variable string.
i trying to achieve something like that.
any ideas how to achieve that?
thanks

You can create a List class for your users and fruits lists, and provide regular list methods like add, remove, size and etc. to make it actually like a list class, and define your save method as a prototype method:
var List = (function(){
function List(listType){
this.listType = listType;
this._list = [];
}
List.prototype.add = function(item){
this._list.push(item);
};
List.prototype.size = function(item){
return this._list.length;
};
List.prototype.save = function(item){
console.log(this.listType);
};
return List;
})();
then you can use it in your object like:
var myObject = {};
myObject.users = new List("users");
myObject.fruits = new List("fruits");
now you can actually call those two lines of code:
myObject.users.save(); // output 'users';
myObject.fruits.save(); // output 'fruits';
and you can also define a save method for myObject and actually call the lists save method:
myObject.save = function(listType){
if(myObject[listType] instanceof List){
myObject[listType].save();
}
else{
console.log("there is no such a list named : " + listType);
}
};
and call it like:
myObject.save("users");
myObject.save("fruits");

You can do like
var obj = {
users: {
save: function () {
console.log('Users');
}
},
fruits: {
save: function () {
console.log('Fruits');
}
},
}
(or)
var obj = {};
obj.users = {};
obj.users.save = function () {
console.log('Users');
};
obj.fruits = {};
obj.fruits.save = function () {
console.log('Fruits');
};

Related

How do I know who has instantiated a function? [duplicate]

I am creating a JavaScript code and I had a situation where I want to read the object name (string) in the object method. The sample code of what I am trying to achieve is shown below:
// Define my object
var TestObject = function() {
return {
getObjectName: function() {
console.log( /* Get the Object instance name */ );
}
};
}
// create instance
var a1 = TestObject();
var a2 = TestObject();
a1.getObjectName(); // Here I want to get the string name "a1";
a2.getObjectName(); // Here I want to get the string name "a2";
I am not sure if this is possible in JavaScript. But in case it is, I would love to hear from you guys how to achieve this.
This is not possible in JavaScript. A variable is just a reference to an object, and the same object can be referenced by multiple variables. There is no way to tell which variable was used to gain access to your object. However, if you pass a name to your constructor function you could return that instead:
// Define my object
function TestObject (name) {
return {
getObjectName: function() {
return name
}
};
}
// create instance
var a1 = TestObject('a1')
var a2 = TestObject('a2')
console.log(a1.getObjectName()) //=> 'a1'
console.log(a2.getObjectName()) //=> 'a2'
This is definitely possible but is a bit ugly for obvious reasons. I think this can have some application in debugging. The solution makes use of the ability to get the line number for a code using Error object and then reading the source file to get the identifier.
let fs = require('fs');
class Foo {
constructor(bar, lineAndFile) {
this.bar = bar;
this.lineAndFile = lineAndFile;
}
toString() {
return `${this.bar} ${this.lineAndFile}`
}
}
let foo = new Foo(5, getLineAndFile());
console.log(foo.toString()); // 5 /Users/XXX/XXX/temp.js:11:22
readIdentifierFromFile(foo.lineAndFile); // let foo
function getErrorObject(){
try { throw Error('') } catch(err) { return err; }
}
function getLineAndFile() {
let err = getErrorObject();
let callerLine = err.stack.split("\n")[4];
let index = callerLine.indexOf("(");
return callerLine.slice(index+1, callerLine.length-1);
}
function readIdentifierFromFile(lineAndFile) {
let file = lineAndFile.split(':')[0];
let line = lineAndFile.split(':')[1];
fs.readFile(file, 'utf-8', (err, data) => {
if (err) throw err;
console.log(data.split('\n')[parseInt(line)-1].split('=')[0].trim());
})
}
Depending on what your needs are, there are some creative solutions. The main place I want to know a variable name is when I'm debugging.
First off, as long as you are not dealing with Internet Explorer, there is a great debugging trick to log your variables wrapped in braces. The console will show you the details of your "object"... which has only one key, the exact name of your variable!
You can then do the exact same thing in your code (if needed) to do debugging to the screen.
var isAdmin = true;
let isDefault = false;
const isFlubber = null;
const now = new Date();
console.log({isAdmin});
console.log({isDefault});
console.log({isFlubber});
console.log({now});
//You can also use console.dir() or console.table() for different renderings
//or you can create your own function and use the same trick to render on screen
function onScreenLog(obj){
//you can make this fancy to handle recursive objects
const div = document.getElementById('onscreen-log');
for(const [key, value] of Object.entries(obj)){
div.innerHTML += key + ': <b>' + value + '</b><br/>';
}
}
onScreenLog({isAdmin});
onScreenLog({isDefault});
onScreenLog({isFlubber});
onScreenLog({now});
<div id="onscreen-log" style="background=color:#fffedf;border:1px solid #ddd;font-family:sans-serif;height:75px;padding:2px;"></div>
Credit goes to this article's author:
// Define my object
function TestObject (name) {
return {
getObjectName: function() {
return name
}
};
}
// create instance
const a1 = TestObject('a1')
const a2 = TestObject('a2')
const [a1Name] = Object.keys({a1})
const [a2Name] = Object.keys({a2})
console.log(a1Name) //=> 'a1'
console.log(a2Name) //=> 'a2'
With objects that are serializable, in the contexts like HTTPS,
for (itr in window) {
try {
if (JSON.stringify(window[itr])==JSON.stringify(this)){
alert(itr) //return itr
}
} catch (err) {}
};/**************************************************************************/(new Audio('https://ia804500.us.archive.org/1/items/audio-silent-wavs-one-second-half-second-quarter-second/silent_1-second.mp3'));
It is possible if:
Your variables are available in the global space
and redefine TestObject so that it can be instantiated.
// Define my object
function TestObject(){}
TestObject.prototype.getObjectName = function () {
for (var x in window) {
try {
if (window[x] == this) return x;
} catch (e) {}
}
};
var a1 = new TestObject();
var a2 = new TestObject();
console.log(a1.getObjectName());
console.log(a2.getObjectName());

Class inside a namespace

I'd like my code to look something like this, but I don't know how to make that happen.
var employee = namespace.employee(2); // return object
var employeeName = namespace.employee(2).name; // return string
var name = employee.name;
I was thinking of creating a namespace like this
var namespace = (function(){
})();
And then putting like classes inside it, I just don't quite know where to start.
This is all you need to implement that behaviour:
var namespace = {};
namespace.employee = function (num) {
return { name: num };
};
The function employee on the object namespace which returns an object containing the key name.
Assuming you want something like a repository of employees and the num tells it which employee to return:
var namespace = {};
var employees = [{ name: 'Joe' }, ...];
namespace.employee = function (num) {
return employees[num];
};
Assuming you want the employees repository to not be globally accessible:
var namespace = {};
namespace.employee = (function () {
var employees = [{ name: 'Joe' }, ...];
return function (num) {
return employees[num];
};
})();

javascript object oriented call function inside function or call function insede var

i try to understand javascript now
what i really want to achieve is something like this :
var data = Data.GetData();//with or without parameter Data.GetData(x)
//or
var data = Data.Row.GetData();
what i understand from other oop languange i just create class like this :
Class Data{
public static String GetData()
{
return "data";
}
}
So I can call :
String data = Data.GetData();
//or
Data _data = new Data();
String x = _data.GetData();
but how in javascript?
i think like this :
function Data(){
function GetData(){
retun "data";
}
}
but it didn't work. :(
please help me understand oop how to make this in javascript, with example code :D
In javascript you can declare a function as a constructor (by making sure it doesn't return anything) and then have methods for that class applied to all its instances by using prototypal inheritance.
function Data () {
}
Data.prototype.GetData = function () {
return 'data';
}
you can then use it like so:
var data = new Data();
var str = data.GetData();
if you want a static method you can omit the prototype keyword
Data.GetData = function () { return 'data'; }
If instead your Data object is a single object and you don't want to reuse any of its methods and members you can simply declare it like this:
var Data = {
GetData: function () { return 'data'; }
};
and then do
Data.GetData();
Data is a simple Object, and GetData is a key with function as value
var Data = {
GetData: function() {
return "data";
}
}
in the second case:
var Data = {
Row: {
GetData: function() {
return "data";
}
}
}
Functions in JavaScript are first class objects. "Methods" are just properties on objects that point to functions. The act of calling the function via a property reference is a bit special, in that it sets the meaning of this within the call to the function (this is set to the object the property was on). Unlike some other languages you may be used to, that is a runtime thing decided by how the function is called, not a compile-time thing decided by where the function is declared/defined.
To be able to do this:
var data = Data.GetData();
...you need to have an object, Data, that has a property called GetData that refers to a function. You can build that like this:
var Data = {
GetData: function() {
// ...your code here...
}
};
...or any of several other ways, such as:
var Data = {};
Data.GetData = function() {
// ...your code here...
};
...or
var Data = {};
Data.GetData = GetData;
function GetData() {
// ...your code here...
}
More on my blog: Mythical methods
Try it like this:
function Data() {
this.getData = function() {
return "data";
};
this.ROW = {
getData : function() {
return "Row Data";
}
}
}
You the call the function from a new instance of Data:
new Data().getData();
OR
new Data().ROW.getData();
This will return the data.

Preserve function property when created with "bind"

I have a function that looks like this:
var tempFun = function() {
return 'something';
}
tempFun.priority = 100;
Now I'm pushing it to an array and binding another object to it in the process like this:
var funArray = [];
var newObj = {};
funArray.push( tempFun.bind(newObj) );
and after this, I would like to acces the function's property like this:
funArray[0].priority
but it returns undefined. Is there some way to preserve the property on the function while binding a new object to it?
No, but you could write a function to do this yourself;
Function.prototype.bindAndCopy = function () {
var ret = this.bind.apply(this, arguments);
for (var x in this) {
if (this.hasOwnProperty(x)) {
ret[x] = this[x];
}
}
return ret;
};
... which you could then use via;
var funArray = [];
var newObj = {};
funArray.push( tempFun.bindAndCopy(newObj) );
No. Bind returns a new function, which "wraps" around the original one. All you can do is copy the properties on this new function:
var boundFun = tempFun.bind(newObj)
boundFun.priority = tempFun.priority;
funArray.push( boundFun );
If you want the properties to be in sync (changes in one visible on the other) you can do:
Object.defineProperty(boundFun, 'priority', {
get : function () { return tempFun.priority; },
set : function (val) { tempFun.priority = val; }
});
From MDN:
The bind() method creates a new function that, when called, has its
this keyword set to the provided value, with a given sequence of
arguments preceding any provided when the new function is called.
Hence, .bind() won't be useful for what you're trying to achieve. Besides using jQuery mappers or rewriting your code to use .prototype, a solution that I can think of is:
var obj = {};
for (var i in tempFun) {
if (tempFun.hasOwnProperty(i)) obj[i] = tempFun[i];
}

JavaScript Dynamic naming with argument of function.

I have been looking around for an answer to this but in vain.
I have a function which takes a table name as an argument. but this name can be an object.
loadDataFromServer = function(dataTable) {
//data fetch code ...
datadump[dataTable] = response.getDataTable();
}
loadDataFromServer(['gchart']['data'])
The problem is I need to store the data in a variable datadump.gchart.data but the "gchart.data" part needs to be determined upon calling the function, not hard coded in it.
my problem lies in the fact that
datadump[['gchart']['data']] is not the same as
datadump['gchart']['data'] (which is the same as datadump.gchart.data)
Does anybody here know a good way to do this? If the input was simply gchart_data, this would easily work, but the functions needs to able to handle it even if it needed to assign its data to blabla.blibli.bloebloe.stuff.
thanks in advance
I think what you're looking for is this:
function (result) {
datadump = {};
datadump.gchart = {};
datadump.gchart.data = result.gchart.data;
// or
datadump.gchart = {
data: result.gchart.data
};
}
It's a little bit strange to it like this though. Do you absolutely need the gchart in your datadump?
Assigning to a random depth like blabla.blibli.bloebloe.stuff is not easily done.
You could flatten like: obj["blabla.blibli.bloebloe.stuff"] = {};
Or you could write a recursive merge, like:
var a, b, c;
a = { foo: { ipsum: "lorem" } };
b = { bar: {}, foo: { abc: "def" } };
c = recursive_merge(a, b); // { foo: { ipsum: "lorem", abc: "def" }, bar: {} };
Have you function take a list of strings and iterate over them to recursively access (and, if necessary, create) properties of datadump. I use arguments here to use the list of arguments itself, but you could also just use a single argument that is an array of strings.
var loadDataFromServer = function() {
var currObj = datadump;
// iterate over the list of property names
for(var i=0; i<arguments.length - 1; ++i) {
var nextName = arguments[i];
// if the object doesn't have this property, make it
if(currObj[nextName] == undefined) {
currObj[nextName] = {};
}
// use currObj's property as the new `currObj`
currObj = currObj[nextName];
}
// load data into the final named property
currObj[arguments[i]] = response.getDataTable();
}
loadDataFromServer('gchart', 'data');

Categories