I have the following code :
function foo(){
this.bar = {
images: function() {
this.example = "string";
this.anotherFoo = true;
(...)
this.getBigPicturePositions = function(){};
return this;
},
search: function(){
this.thing = "string";
this.anotherBar = false;
(...)
this.newAjaxSearch = function(){};
return this;
}
}
}
And then, I have this declaration :
var foo = new foo();
foo.start({
bar: {
images: {
getBigPicturePositions: true
},
search: {
newAjaxSearch: true,
idontexist: true
}
}
});
How can I make a function like this who start the methods specified? I need this to start specific methods when i need to (if they exists of course). In my example, i need to get something like :
foo.bar.images().getBigPicturePositions();
foo.bar.search().newAjaxSearch();
Thank you for your help! I'm a newbie in javascript object.
UPDATE : The problem is solved with the solution presented by CrazyTrain but I have updated my code too. To view the result, please check this Fiddle
First, make the .start() method an inherited method for objects created from new foo()
foo.prototype.start = function(flags) {
// call our recursive invoker function
recursive_invoker(flags, this);
}
Then make a recursive function that iterates objects, and either recursively traverses nested objects when found, or invokes functions if a true value was given.
// holds the flags---v v---holds the methods
function recursive_invoker(flags, methods) {
// enumerate the properties of the `flags` object
for (var f in flags) {
if (typeof flags[f] === "object" && typeof methods[f] === "object") {
// objects were found, so make a recursive call with those objects
recursive_invoker(flags[f], methods[f]);
} else if (flags[f] === true && typeof methods[f] === "function") {
// `true` was found, so invoke the function on the "methods" object
methods[f]();
} else {
// Either we found `false`, or an object was not found, so do nothing.
// This `else` isn't really needed.
}
}
}
Related
I have two objects that are the same type and I want to copy the content of one of them to the other.
const Invoice1 = new InvoiceModel();
const Invoice2 = new InvoiceModel();
now in order to have something like : Invoice2 = Invoice1
After reading :
How do I correctly clone a JavaScript object?
I tried to use any of below commands but all of them say that invoice2 is not defined at runtime:
Invoice2 = { ...Invoice1 }; //OR
Invoice2 = Object.assign({}, Invoice1); //OR
Invoice2 = JSON.parse(JSON.stringify(Invoice1));
finally I used this function to copy the content of objects by reading this article (https://medium.com/#Farzad_YZ/3-ways-to-clone-objects-in-javascript-f752d148054d):
function CopyObject(src, target) {
for (let prop in src) {
if (src.hasOwnProperty(prop)) {
target[prop] = src[prop];
}
}
return target;
}
I wonder is there any cleaner way to do that except using above function?
I have read many post regarding this issue but all of them create a new object.
I recommend creating a method in the prototype in InvoiceModel that does this automatically for you.
class InvoiceModel {
constructor(num) {
this.num = num
}
duplicate() {
return Object.assign(Object.create(this), this)
}
}
const obj1 = new InvoiceModel(10)
console.log(obj1.num)
const obj1Copy = obj1.duplicate()
console.log(obj1Copy.num)
console.log(obj1Copy === obj1)
If the objects are just plain old data objects - with no methods or private state - you can just use a deep object clone method as specified here.
However, by the looks of things you are using classes with constructors, which implies you have methods and state. This is more tricky, because it suggests you may be relying on the constructor being re-run, e.g. to store private state in a closure, to allocate other resources, or rely on some kind of side effects. In that case you will need some kind of Invoice.prototype.clone method, that knows how to inject state into a new instance, and reruns the constructor function for the class - as per #andrew's answer.
I would avoid cloning objects with the syntax target = {...src}, which one commenter suggested. This will cause you trouble as soon as you have non-scalar reference members like sub-objects or arrays (as you will be copying pointers to the originals, not cloning their values). The same flaw applies to that CopyObject function you have picked up.
I have implemented a deep copier of objects, it does not override anything in the target option, but if you need that, you can achieve that as well:
var defaults = {
options: {
remove: true,
enable: false,
instance: {}
},
log: {
warn: true,
error: true
}
};
var config = {
options: {
remove: false,
instance: null
}
};
function applyDefaults(d, t) {
if ((typeof d !== "object") && (typeof d !== "array")) {
return d;
}
if (t === undefined) {
if (typeof d === "object") {
t = {};
} else if (typeof d === "array") {
t = [];
}
}
for (var key in d) {
if (t[key] === undefined) {
t[key] = d[key];
} else {
applyDefaults(d[key], t[key]);
}
}
return t;
}
applyDefaults(defaults, config);
console.log(config);
However, this will not copy "private" stuff, not defined as members of this.
I'm just trying to understand Javascript a little deeper.
I created a 'class' gameData that I only want ONE of, doesn't need a constructor, or instantiated.
So I created it like so...
var gameData = new function () {
//May need this later
this.init = function () {
};
this.storageAvailable = function () {
if (typeof (Storage) !== "undefined") {
return true;
}
else {
return false;
}
};
}
Realizing that the 'new' keyword doesn't allow it to be instantiated and makes it available LIKE a static class would be in C#.
Am I thinking of this correctly? As static?
No, it is not static because it still has a constructor property pointing to your "anonymous" function. In your example, you could use
var gameData2 = new (gameData.constructor)();
to reinstantiate a second object, so the "class" (instance actually) is not really "static". You are basically leaking the constructor, and possibly the data that is bound to it. Also, a useless prototype object (gameData.constructor.prototype) does get created and is inserted in the prototype chain of gameData, which is not what you want.
Instead, you might use
a single, simple object literal (as in Daff's answer). That means you don't have a constructor, no closure-scoped private variables (you have used none anyway) and no (custom) prototype.
the (revealing) module pattern (as in jAndy's answer). There you'd have an IIFE to create closure-scoped variables, and can return any kind of object.
an actual constructor ("class") that can be instantiated later (when needed), and yields the same singleton object always.
This is what the singleton pattern would look like:
function GameData() {
if (this.constructor.singleton)
return this.constructor.singleton;
else
this.constructor.singleton = this;
// init:
// * private vars
// * public properties
// ...
}
GameData.prototype.storageAvailable = function () {
if (typeof (Storage) !== "undefined") {
return true;
}
else {
return false;
}
};
var gameData = new GameData();
var gameData2 = new GameData();
gameData === gameData2 === GameData.singleton; // true
Yet, the prototype is quite useless because you have only one instance of GameData. It would only get interesting with inheritance.
There is no Class in ECMAscript, there is only Object.
When new is used to invoke a function, we call it a constructor function. This function somewhat auto returns a new object once it finished. Any data that is stored within that object using this (which references that newly created object) is returned as property of that object. Beside that, new sets a property called constructor to exactly this function.
In your case, you don't even really require the usage of new, you could easily re-write your code as follows:
var gameData = (function () {
var public = { },
private = { }; // any private data can get stored here
//May need this later
public.init = function () {
};
public.storageAvailable = function () {
if (typeof (Storage) !== "undefined") {
return true;
}
else {
return false;
}
};
return public;
}());
This is called the factory pattern, singleton pattern, module pattern, and there might be some other names.
I think what you are looking for is just a simple JavaScript object:
var gameData = {
//May need this later
init : function () {
},
storageAvailable : function () {
if (typeof (Storage) !== "undefined") {
return true;
}
else {
return false;
}
}
}
If you want to use private variables create a revealing module pattern style wrapper. This is basically what jAndy suggested:
var gameData = (function() {
var private = 'private variable';
return {
//May need this later
init : function () {
},
storageAvailable : function () {
if (typeof (Storage) !== "undefined") {
return true;
} else {
return false;
}
}
}
})();
I'm just trying to understand Javascript a little deeper.
I created a 'class' gameData that I only want ONE of, doesn't need a constructor, or instantiated.
So I created it like so...
var gameData = new function () {
//May need this later
this.init = function () {
};
this.storageAvailable = function () {
if (typeof (Storage) !== "undefined") {
return true;
}
else {
return false;
}
};
}
Realizing that the 'new' keyword doesn't allow it to be instantiated and makes it available LIKE a static class would be in C#.
Am I thinking of this correctly? As static?
No, it is not static because it still has a constructor property pointing to your "anonymous" function. In your example, you could use
var gameData2 = new (gameData.constructor)();
to reinstantiate a second object, so the "class" (instance actually) is not really "static". You are basically leaking the constructor, and possibly the data that is bound to it. Also, a useless prototype object (gameData.constructor.prototype) does get created and is inserted in the prototype chain of gameData, which is not what you want.
Instead, you might use
a single, simple object literal (as in Daff's answer). That means you don't have a constructor, no closure-scoped private variables (you have used none anyway) and no (custom) prototype.
the (revealing) module pattern (as in jAndy's answer). There you'd have an IIFE to create closure-scoped variables, and can return any kind of object.
an actual constructor ("class") that can be instantiated later (when needed), and yields the same singleton object always.
This is what the singleton pattern would look like:
function GameData() {
if (this.constructor.singleton)
return this.constructor.singleton;
else
this.constructor.singleton = this;
// init:
// * private vars
// * public properties
// ...
}
GameData.prototype.storageAvailable = function () {
if (typeof (Storage) !== "undefined") {
return true;
}
else {
return false;
}
};
var gameData = new GameData();
var gameData2 = new GameData();
gameData === gameData2 === GameData.singleton; // true
Yet, the prototype is quite useless because you have only one instance of GameData. It would only get interesting with inheritance.
There is no Class in ECMAscript, there is only Object.
When new is used to invoke a function, we call it a constructor function. This function somewhat auto returns a new object once it finished. Any data that is stored within that object using this (which references that newly created object) is returned as property of that object. Beside that, new sets a property called constructor to exactly this function.
In your case, you don't even really require the usage of new, you could easily re-write your code as follows:
var gameData = (function () {
var public = { },
private = { }; // any private data can get stored here
//May need this later
public.init = function () {
};
public.storageAvailable = function () {
if (typeof (Storage) !== "undefined") {
return true;
}
else {
return false;
}
};
return public;
}());
This is called the factory pattern, singleton pattern, module pattern, and there might be some other names.
I think what you are looking for is just a simple JavaScript object:
var gameData = {
//May need this later
init : function () {
},
storageAvailable : function () {
if (typeof (Storage) !== "undefined") {
return true;
}
else {
return false;
}
}
}
If you want to use private variables create a revealing module pattern style wrapper. This is basically what jAndy suggested:
var gameData = (function() {
var private = 'private variable';
return {
//May need this later
init : function () {
},
storageAvailable : function () {
if (typeof (Storage) !== "undefined") {
return true;
} else {
return false;
}
}
}
})();
Say i have a constructor, and some instance methods, like
function MyClass(name) {
this.name = name || '';
}
MyClass.prototype = {
constructor: MyClass,
isEmptyName: function() {
return this.name === '';
}
}
Now i can write
var myClass = new MyClass('Ben');
myClass.isEmptyName();
which would return false. Now if i make another method what would also return a Boolean
MyClass.prototype = {
constructor: MyClass,
isEmptyName: function() {
return this.name === '';
}
longerThan: function(len) {
return this.name.length > len;
}
}
i would like to chain these methods like this (somehow, thats my question :) )
myClass.isEmptyName().and.longerThan(2);
Just omit now the '.and.' part. I want the upper statement to finally return a value
false && true -> false
Or a more realistic sample:
myClass.notEmptyName().and.longerThan(4);
To summarize my problem i would say, i want my methods return a boolean value if they are called 'directly' myClass.notEmptyName() should return true, but work like i wrote in the samples, otherwise.
Other libraries do this somehow, but i can't guess how, npm's should is a good example:
user.should.have.property('pets').with.lengthOf(4);
user.pets.should.be.instanceof(Array).and.have.lengthOf(4);
Thanks
That's not possible. A method can't return either a boolean or be chainable depending on how it's used later on, because it doesn't know how it will be used later on.
You can chain methods that validate the object in different ways, but you need to get the result at the end if you want to use it in an expression, either by reading a property or calling a method:
function MyClass(name) {
this.name = name;
this.and = this;
}
MyClass.prototype = {
value: true,
isNotEmpty: function() {
this.value = this.value && this.name.length > 0; return this;
},
isLongerThan: function(len) {
this.value = this.value && this.name.length > len; return this;
},
evaluate: function() {
return this.value;
}
};
console.log(new MyClass('Adam').isLongerThan(2).evaluate());
console.log(new MyClass('Bob').isNotEmpty().and.isLongerThan(3).evaluate());
Demo: http://jsfiddle.net/Guffa/62e8dLwL/
Edit:
To allow evaluation more than once, you would reset the value in the evaluate method:
evaluate: function() {
var v = this.value;
this.value = true;
return v;
}
Sure, you can do that. We will define a new intermediate status object, called ChainResult, which remembers the underlying object, the current value, and a pending operation (a function to use to combine the next test). We give this object a valueOf method, so that when JS tries to evaluate it as a primitive, it "looks" like it has a value. To make this work, it turns out that ChainResult actually needs to be a function, and so we hang the necessary properties off the function.
function ChainResult(obj, val) {
function x() { }
x.obj = obj;
x.val = val;
x.op = null;
// the `valueOf` function spits out the current value when the object is evaluated
x.valueOf = function() { return this.val; };
// the test functions combine the results with the current value
// using the current operation as set by a preceding `and` or `or`
x.isEmptyName = function() {
x.val = x.op(x.val, x.obj._isEmptyName());
return this;
};
x.isLongerThan = function(len) {
x.val = x.op(x.val, x.obj._isLongerThan(len));
return this;
};
// we implement `and` and `or` via getters which set the operation
// on the ChainResult object, and return `this` so we can keep chaining
Object.defineProperties(x, {
and: {
get: function() { x.op = function(a,b) { return a && b; }; return x; }
},
or: {
get: function() { x.op = function(a,b) { return a || b; }; return x; }
}
});
return x;
}
The MyClass definition needs a bit of tweaking:
function MyClass(name) {
this.name = name || '';
}
MyClass.prototype = {
constructor: MyClass,
// we implement the testers as pseudo-private functions
_isEmptyName: function() { return this.name === ''; },
_isLongerThan: function(len) { return this.name.length > len; },
// when the public tester functions are invoked directly on the object
// (when they are the first link in the chain), we construct and return a
// ChainResult object with the initial value set correctly
isEmptyName: function() { return ChainResult(this, this._isEmptyName()); },
isLongerThan: function(len) { return ChainResult(this, this._isLongerThan(len)) }
};
Flow:
new MyClass('Bob') // create MyClass object
.isEmptyName() // create ChainResult object with value `false`
.or // remember `or` operation in ChainResult object
.isLongerThan(2) // update value of ChainResult object
; // JS tries to convert to scalar, calls valueOf
// true
This needs to be bullet-proofed and tightened up, but you get the idea.
i want my methods return a boolean value if they are called 'directly' myClass.notEmptyName() should return true
Your methods are always called directly on the instance, and would always need to return a primitive boolean value. By that, the context (myClass) is lost and you cannot have an and method (or property getter) on the result.
I would recommend you to have a look at functional programming, partial application and currying, which helps a lot with fluent interfaces like this. Given
function and(fn1, fn2) {
return function(val) {
return fn1(val) && fn2(val);
};
}
function or(fn1, fn2) {
return function(val) {
return fn1(val) || fn2(val);
};
}
function hasEmptyName: function(val) {
return val.name === '';
}
function hasNameLongerThan: function(len) {
return function(val) {
return val.name.length > len;
};
}
you could write
and(hasEmptyName, hasNameLongerThan(2))(myClass);
Making these functions methods of anything is complicated however. Maybe something like this:
function method(name) {
var args = Array.prototype.slice.call(arguments, 1);
return function(instance) {
return instance[name].apply(instance, args);
};
}
Function.prototype.and = function (fn2) {
var fn1 = this;
return function(val) {
return fn1(val) && fn2(val);
};
}
Function.prototype.or = function (fn2) {
var fn1 = this;
return function(val) {
return fn1(val) || fn2(val);
};
}
Object.defineProperty(Object.prototype, "test", function(pred) {
return pred(this);
});
Now you could write
myClass.test(method("notEmptyName").and(method("longerThan", 4)));
This is an answer (better call it to outcome) for my own question:
Finally i came out with another solution based on the responses in this thread (Thanks guys!) because the original problem can not be solved, since the javascript runtime can't find out wether to return a value, or return itself (the object) when chained. Explanation is messy, sorry :(
Check out my lib, where i have methods like:
check(value).isString() etc..
Originally i wanted to chain these like check(value).isString().and.not.empty() but this, in this way, can not be done. (Challenge me)
Finally i created tokens for chaining, so instead of
check(value).isString().and.not.empty()
I can write
check(value).isstring.and.not.empty.test()
Not nice, but still something.
check.js
For review, visit checkjs on my github repo.
Note: README is outdated.
If you use promises, you could write functions that return values and can be chained. Mind you, these are all asynchronous.
Find this JS plugin: Kris Owal's Q, or if you like to use a JS library, they usually contain deferred objects and promises.
I need to loop over the properties of a javascript object. How can I tell if a property is a function or just a value?
var model =
{
propertyA: 123,
propertyB: function () { return 456; }
};
for (var property in model)
{
var value;
if(model[property] is function) //how can I tell if it is a function???
value = model[property]();
else
value = model[property];
}
Use the typeof operator:
if (typeof model[property] == 'function') ...
Also, note that you should be sure that the properties you are iterating are part of this object, and not inherited as a public property on the prototype of some other object up the inheritance chain:
for (var property in model){
if (!model.hasOwnProperty(property)) continue;
...
}
Following might be useful to you, I think.
How can I check if a javascript variable is function type?
BTW, I am using following to check for the function.
// Test data
var f1 = function () { alert("test"); }
var o1 = { Name: "Object_1" };
F_est = function () { };
var o2 = new F_est();
// Results
alert(f1 instanceof Function); // true
alert(o1 instanceof Function); // false
alert(o2 instanceof Function); // false
You can use the following solution to check if a JavaScript variable is a function:
var model =
{
propertyA: 123,
propertyB: function () { return 456; }
};
for (var property in model)
{
var value;
if(typeof model[property] == 'function') // Like so!
else
value = model[property];
}