Store a function in IndexedDb datastore - javascript

Is it possible in any way to store a function in an IndexedDB datastore? I have done some searching and found nothing on the data types that IndexedDB supports. I tried simply adding a function and the instance of a function to an object store as follows, but it didn't work.
var myclass = function () {
self = this;
self.name = 'Sam';
self.hello = function () {
console.log('Hello ' + self.name);
};
}
var transaction = db.transaction(['codeobject'], 'readwrite');
var store = transaction.objectStore('codeobject');
var request = store.put({ 'classname': 'someclass', 'object': myclass });
And I have tried.
var request = store.put({ 'classname': someclass', 'object': new myclass() });
I would really like to be about to store a class in object db. Even if I had to store it as some type of blob and then serialize it back into a function on its way out.
Thank you

If I get your question right, what you want to do is serialize the entire object including functions?
This is possible to do, you only need to make it possible to serialize functions. For more information about it, see my blogpost about it.
function serialize(key, value) {
if (typeof value === 'function') {
return value.toString();
}
return value;
}
function deserialize(key, value) {
if (value && typeof value === "string" && value.substr(0, 8) == "function") {
var startBody = value.indexOf('{') + 1;
var endBody = value.lastIndexOf('}');
var startArgs = value.indexOf('(') + 1;
var endArgs = value.indexOf(')');
return new Function(value.substring(startArgs, endArgs), value.substring(startBody, endBody));
}
return value;
}
var jsonObj = {
func: function(){ return ""; }
}
// Turns an object into a json string including functions
var objectstring = JSON.stringify(jsonObj, serialize);
// Turns an object string in JSON into an object including functions.
var object = JSON.parse(objectstring , deserialize);
The objectstring you get can then be saved into the indexeddb.

You can store the function as a string:
store.put({ 'classname': 'someclass', 'object': myclass.toString() });
And then deserialize it back into a function via eval:
var myclass = Function('"use strict";return ' + functionString);

Related

How can create own call function in javascript?

As of my knowledge, in javascript there are three concepts; call, apply and bind
I want to create these function with similar behavior.
Here is a polyfill for them (not accurate though, just what came into my mind):
Function.prototype.call = function(context, ...args) {
const fn = Symbol();
try {
context[fn] = this;
return context[fn](...args);
} catch(e) {
// Turn primitive types into complex ones 1 -> Number, thanks to Mark Meyer for this.
context = new context.constructor(context);
context[fn] = this;
}
return context[fn](...args);
};
Function.prototype.apply = function(context, args) {
return this.call(context, ...args);
};
Function.prototype.bind = function(context, ...args) {
return (...args2) => this.call(context, ...args, ...args2);
};
The only thing that is impossible to polyfill is fn.call(null), as that primitive can't be turned into a complex type, only native code can do this
Add your own call function like "_call"
Function.prototype._call = function(newcontext, ...arg){
var demoFn = new Function('tempfuncton', 'tempthis','arg' , '{ tempthis["f"]=tempfuncton; return tempthis.f(arg);}');
demoFn(this,newcontext,arg);
}
write a demo function
function anyfunction(args){
console.log(this,args)
}
call it like previous. First argument should be an object. Otherwise write a code to convert it into object.
anyfunction._call({'mm':'my provided this object'},"arg1","arg2")
function B(a,b,c){
console.log(a,b,c)
}
Function.prototype.OwnCallFunction = function(){
if( this.length == arguments.length)
this(...arguments)
else
console.error('Signature does not match')
}
B.OwnCallFunction(323,34,34)
I followed this approach to create own call function. With help of Function
Constructor, I add a function to it and it worked on firefox.
New approach, with more clarity
Function.prototype.call2 = function(context, ...args){
console.log(context)
const fn = Symbol();
context[fn] = this;
context[fn](...args);
}
In above answers I can see that spread operators has been used, but if we really want to make pollyfill of call then we should avoid spread
operator and latest concept of es6.I am sharing solution without es6.
Call Function:-
Function.prototype.myCall = function(obj) {
obj = obj || global;
var id = "00" + Math.random();
while (obj.hasOwnProperty(id)) {
id = "00" + Math.random();
}
obj[id] = this;
let arg=[];
for(let i=1;i<arguments.length;i++){
arg.push("arguments[" + i + "]");
}
result= eval("obj[id]("+arg+")");
delete obj[id];
return result;
}
Apply function:-
Function.prototype.myApply = function(obj, argArr) {
obj = obj || global;
var id = "00" + Math.random();
while (obj.hasOwnProperty(id)) {
id = "00" + Math.random();
}
obj[id] = this;
let arg=[];
let result
if(!argArr){
result= obj[id].fn();
}
else{
for(let i=0;i<argArr.length;i++){
arg.push("argArr[" + i + "]");
}
result= eval("obj[id]("+arg+")");
delete obj[id];
}
return result;
}
Bind function:-
Function.prototype.myBind2= function(){
let obj1= this;
const obj= Array.prototype.slice.call(arguments,0,1);
const arg= Array.prototype.slice.call(arguments,1);
return function(){
const arg2= Array.prototype.slice.call(arguments);
obj1.apply(obj[0],Array.prototype.concat(arg, arg2));
}
Another solution Bind: we can pass object argument of function
Function.prototype.myBind2 = function(obj) {
let fn = this;
const arg = Array.prototype.slice.call(arguments, 1);
return function() {
const arg2 = Array.prototype.slice.call(arguments);
fn.apply(obj, Array.prototype.concat(arg, arg2));
}
While each browser has its own source code for implementing Javascript, you can find how many of the native Javascript functions are implemented with the ECMA specifications found here:
http://www.ecma-international.org/ecma-262/10.0/index.html#sec-properties-of-the-function-prototype-object
For specs of apply, see: 19.2.3.1
For specs of bind, see: 19.2.3.2
For specs of call, see: 19.2.3.3
If you're interested for example, how Node implemented apply, you can dig into their source code on Github here: https://github.com/nodejs/node
Here is my sweet and simple solution. We are adding the ObjRef in prototypal chain to avoid any name conflicts with other properties
Function.prototype.call2 = function (objRef, ...args) {
otherObj = Object.create(objRef)
otherObj[this.name] = this;
otherObj[this.name](...args);
}
I don't think using Object.create makes sense here as when you will console this inside the function you won't see the desired object.
Here is my try(not accurate though) but will work.
Function.prototype.myCall = function (thisContext, ...param) {
let name = this.name;
thisContext[name] = this;
thisContext[name](...param);
}
Function.prototype.mycall = function(context, ...args){
context.fun= this; //add personal function to context
context.fun(...args);
}
function personal (msg){
alert(this.name + " " + msg);
}
let obj = {
name:'Ajinkya'
}
personal.mycall(obj,'Khandar'); // pass object and args in mycall

Getting Object Key Name from inside function?

Say I have an object like below:
var obj = {};
obj.test = function() { console.log(?); }
Is there anyway to print out "test", the key that this function is value of, but not know the obj name in advance?
Not really. Relationships in JS are one-way.
You could search for a match…
var obj = {};
obj.not = 1;
obj.test = function() {
var me = arguments.callee;
Object.keys(obj).forEach(function(prop) {
if (obj[prop] === me) {
console.log(prop);
}
});
};
obj.test();
But look at this:
var obj = {};
obj.not = 1;
obj.test = function() {
var me = arguments.callee;
Object.keys(obj).forEach(function(prop) {
if (obj[prop] === me) {
console.log(prop);
}
});
};
obj.test2 = obj.test;
obj.test3 = obj.test;
window.foo = obj.test;
obj.test();
The same function now exists on three different properties of the same object … and as a global.
Might be a bit of a convoluted solution, but this might be useful -
You can have a method that will add functions to your object at a specific key. Using the bind method, we can predefine the first argument to the function to be the key that was used to add it.
The function that I am adding to the key is _template, it's first argument will always be the key that it was added to.
var obj = {};
function addKey(key) {
obj[key] = _template.bind(null, key)
}
function _template(key, _params) {
console.log('Key is', key);
console.log('Params are',_params);
}
addKey('foo')
obj.foo({ some: 'data' }) // this will print "foo { some: 'data' }"
Reference - Function.prototype.bind()
try this Object.keys(this) and arguments.callee
var obj = {};
obj.test = function() {
var o = arguments.callee;
Object.values(this).map((a,b)=>{
if(a==o){
console.log(Object.keys(this)[b])
}
})
}
obj.one = "hi"
obj.test()
You can get the name of the method called with
arguments.callee.name
var a ={ runner_function : function(){ console.log(arguments.callee.name ); } };
a.runner_function() //It will return "runner_function"

How to access form data from a setter without using object literal values?

I need to add setter to the below JavaScript Module:
In the below code I am simply returning the form data to the module object.
I need to add setter functionality so that I can do minimal check on the user input.
var Mod = (function(){
var module = {};
var element = document.forms.[0];
Object.defineProperty(module, 'Country', {
get: function () {
return element.txtCountry.value;
}
});
Object.defineProperty(module, 'City', {
get: function () {
return element.txtCity.value;
}
});
return module;
})();
However, all of the examples I have come across, including those on MDN shows an object with literal values:
Like this one:
var module = {
Country: "United States",
get function() {
return this.Country;
},
set function(x) {
this.Country = x + ' ' + somethingElse;
}
};
How do I add the setter to return data to the object without literal object members?
Finally I am calling the module like this:
var btn = document.getElementById( 'btnDataEntry' );
var result = document.getElementById('result');
btn.addEventListener('click', function(e) {
var t = document.createTextNode(Mod.Country + ',' + Mod.City);
result.appendChild(t);
e.preventDefault();
}, false);
Update (Additional Info):
In the most simplest form I want to perform checks in the setter, something like this:
var Mod = (function(){
var module = {};
var element = document.forms.dataEntry;
Object.defineProperty(module, 'Country', {
get: function () {
return Country;
},
set: function(val) {
if( val == 'A') {
val = element.txtCountry.value;
}
}
});
return module;
})();
Update: (Solution).
So as simple as this may seem, it can become confusing because JavaScript is more abstract when it comes to how one can accomplish certain task.
The problem is, when using setter in an Object.defineProperty() method, you have to pass the value using a dot notation to the object, and by also using a variable within the scope of the function to emulate a private member.
If you look at my previous code, you will see that I was passing the form data directly within the getter, this defeats the entire purpose of having a getter/setter.
Here is a complete working code: Based on readings and example from the following book: The Principles of Object-Oriented JavaScript: By Nicholas C. Zakas.
Code:
var LocationData = (function(){
var location = {};
//Private member to eliminate global scope
var _country;
Object.defineProperty(location, "Country", {
get: function() {
return this._country;
},
set: function(value) {
if(value === 'A') {
this._country = value;
} else {
this._country = 'X';
}
}
});
return location;
})();
var btn = document.getElementById( 'btnDataEntry' );
var result = document.getElementById('result');
btn.addEventListener('click', function(e) {
var element = document.forms[0];
//Pass the value to the method
LocationData.Country = element.txtCountry.value;
var t = document.createTextNode(LocationData.Country);
result.appendChild(t);
e.preventDefault();
}, false);
Define the setter in the same defineProperty call where you define the getter:
Object.defineProperty(module, 'City', {
get: function () {
return element.txtCity.value;
},
set: function (value) {
// do minimal check
element.txtCity.value = value;
}
});

A javascript function that has a defined function

I am trying you get a better understanding of JavaScript, especially the prototype functionality. I am having trouble with this case:
I am trying to define a function someObject with a type function so that it will behave like the following:
var myTestObject = someObject();
If I call:
myTestObject() ===> "The object is initailType"
and then when this is called
myTestObject.type() ===> "InitialType"
Then if I make this call
myTestObject.type("newtype")
myTestObject.type() ===> "newType"
A call to
myTestObject() ===> "The Object is newType".
I have tried both this How does JavaScript .prototype work?
and this How do you create a method for a custom object in JavaScript?
,but I am getting several different errors depending on how it is implemented, mostly this though (Uncaught TypeError: Object myTestObject has no method 'type'). I feel like I am making this harder then it should be.
edit: more code.
function box(){
var _current = "initialType"
Object.defineProperty(this, "current", {
get: function(){return _current;},
set: function(value){
if(arguments.length === 1){
_current = value;
} }
})
return "The Object is " + this.type(this.current)
}
box.prototype.type = function(newValue){
var type = null;
if(arguments.length == 0){
type = "initialType";
}else {
type = newValue
}
return type
}
I would use something like this:
function Box(){}
Box.prototype.type = "initialType";
Box.prototype.toString = function() {
return "The Object is " + this.type + ".";
};
And use it like this:
var b = new Box();
b.type; // "initialType"
b + ''; // "The Object is initialType."
b.type = 'otherType'; // "otherType"
b.type; // "otherType"
b + ''; // "The Object is otherType."
This does what you've asked, but I don't understand what you want to do with the prototype, so this code doesn't use that. For example, the sample code doesn't use new, so the return value of someObject won't use its prototype.
function someObject()
{
var currentType = "initailType";
var formatter = function() {
return "The object is " + currentType;
};
formatter.type = function(value) {
if (arguments.length == 0) {
return currentType;
} else {
currentType = value;
}
};
return formatter;
}
var myTestObject = someObject();
myTestObject(); // => "The object is initailType"
myTestObject.type(); // => "initialType"
myTestObject.type("newType");
myTestObject.type(); // => "newType"
myTestObject(); // => "The object is newType".
see demo
Edit: example using prototype and new.
function Box() { // class name starts with a capital letter
this._type = "initialType"; // set up default values in constructor function
} // no "return" in constructor function, using "new" handles that
Box.prototype.type = function(value) { // adding method to the prototype
if (arguments.length == 0) { // magic arguments local variable...
return this._type; // initially returns the value set in the constructor
} else {
this._type = value; // update the stored value
}
};
Box.prototype.format = function() // another method on the box, rather than a return from the constructor
{
return "The object is " + this.type(); // could use this._type instead
};
var box = new Box(); // instance variable with lowercase name
console.log(box.type()); // read the default value
console.log(box.format()); // print the message with the initial value of type
box.type("another type"); // set the type property, no return value
console.log(box.format()); // print the new message

JavaScript Hashtable / Dictionary

Consider the following article explaining hashtables / dictionaries in JavaScript:
Can anyone recommend a good Hashtable implementation in Javascript?
Given the accepted answer, I want to be able to do this:
var instance = new Dictionary();
instance['key1'] = 'Foo';
instance['key2'] = 'Bar';
instance['key3'] = 123;
instance['key4'] = true;
but I want the key/value pairs to point to an object within the Dictionary internally. consider the following code structure
var Dictionary = function() {
var dictionary; // <-- key value pairs should point to this, not to the Dictionary function;
this.setValue = function(key, value) {
dictionary[key] = value;
}
this.getValue = function() {
return dictionary[key];
}
}
Is this possible?
EDIT:
One way I thought of designing the Dictionary object was like so:
var Dictionary = function() {
this.setValue = function(key, value) {
this[key] = value;
}
this.getValue = function(key) {
return this[key];
}
}
The problems with this are:
I can assign like so instance['key1'] = 'foo'; and read like this instance.key1; I don't want this!!
I can assign this instance['getValue'] = null; and then cannot get a value back because the function is now null!!
Neither of the above should occurr, hence the reason that the set and get functionality should apply to the internal object, not to the dictionary itself.
function Dictionary()
{
this.store = {};
this.setValue = function(key, value) {
store[key] = value;
}
this.getValue = function(key)
{
return store[key];
}
return this;
}
//Testing
var dict = Dictionary();
dict.setValue('key','value');
alert(dict.getValue('key'));//displays "value"
alert(dict.getValue('unassignedKey'));//displays "undefined"
alert(dict['key']);//displays "undefined" (an unfortunate lack of syntactic convenience, we have to go through getValue).
alert(dict.key);//displays "undefined"
var dict2 = Dictionary();
dict2.setValue('key2', 'value2');
alert(dict2.getValue('key'));//displays "undefined"
alert(dict2.getValue('key2'));//displays "value2"

Categories