Creating object dynamically using Object.create() - javascript

I have a scenario, where I need to create objects dynamically.
In my example, an object meta contains the name for the constructor function to be used during initialization Object.create().
At the moment using the following code, I am able to create the objects dynamically but the property name is not defined.
I need that property on the result;
What is wrong in my script? Do you know a better way to achieve the same result?
(function () {
var costructors = {
A: function () {
this.name = 'A';
console.log(this.name);
},
B: function () {
this.name = 'B';
console.log(this.name);
},
C: function () {
this.name = 'C';
console.log(this.name);
}
},
meta = {
A: true,
B: true,
C: true,
},
result = [];
function createObjs() {
Object.keys(meta).forEach(function (type) {
var obj = Object.create(costructors[type].prototype);
result.push(obj);
}.bind(this));
}
createObjs.call(this);
console.log(result);
})();

You haven't defined a prototype for any of the constructors, so you're not creating the name in your instances, since you're creating an object from their prototype, not from their constructor. Try
Object.create(constructors[type])

An alternative without using Object.create would be:
var obj = new costructors[type]();
instead of:
var obj = Object.create(costructors[type].prototype);

Actually, Object.create does not call the constructor function, but only creates a new object from the given prototype. Any member variables can be provided via a property object:
var obj = Object.create(
constructors[type].prototype,
{ 'name' : { value: 'A', writable: true}}
);

Related

JavaScript: How to define methods dynamically?

Object.defineProperty can be used to define properties and getter / setters. But it doesn't seem to support setting properties that are functions (method). Why?
var obj = {};
Object.defineProperty(obj, 'myMethod', function () {
console.log('Hello!');
})
After this, obj.myMethod is undefined.
The third parameter you pass to Object.defineProperty should be an object with a value property, if you want to do something like this:
var obj = {};
Object.defineProperty(obj, 'myMethod', { value: function () {
console.log('Hello!');
}})
obj.myMethod();
This would throw if you tried to pass a non-function:
var obj = {};
Object.defineProperty(obj, 'myMethod', 'foo')
But functions are objects too, so in your original code, the defineProperty call silently fails.
You can use this pattern:
var obj = { c: 3 };
obj = Object.assign({}, obj, {
a: function(){
console.log("testing");
}
});
obj.a();
console.log(obj.c);
From the official documentation of MDN. I recommend you to read the issues related with creating dynamic functions before actually implementing one.
This aside here is an example:
function testMe () {
var obj = {}
obj.myFunc = new Function('a', 'b', 'return a + b');
var el = document.getElementById("test").innerHTML = obj.myFunc(1, 2);
}
<div id="test"></div>
<button onclick="testMe();">Try</button>
Before understanding some points
Syntax : Object.defineProperty(obj, prop, descriptor)
obj The object on which to define the property.
prop The name or Symbol of the property to be defined or modified.
descriptor The descriptor for the property being defined or modified.
const obj = {};
Object.defineProperty(obj, 'myobject', {
value: 20,
writable: false
});
obj.myobject = 10;
document.write(obj.myobject);

Advantages of extending prototype instead of declaring whole object

When should I use first notation:
var object = {
a: function() {
// object.a method body
},
b: function() {
// object.b method body
},
c: function() {
// object.c method body
},
};
and when the second one?
function Class() {};
Class.prototype.a = function() {
// object.a method body
};
Class.prototype.b = function() {
// object.b method body
};
Class.prototype.c = function() {
// object.c method body
};
var object = new Class();
The main advantage is that the functions are shared by all instances in second case, which makes the objects lighter. It explicitly defines the objects as instances of what is conceptually a class.
But the correct syntax is
function MyClass(){
}
MyClass.prototype.a = function(){
};
...
var o = new MyClass();
It also allows you to define an inheritance chain :
function OtherClass(){
}
OtherClass.prototype = new MyClass(); // makes OtherClass extend MyClass
OtherClass.prototype.b = function(){
};
...
var o2 = new OtherClass();
o2 has the functions of both OtherClass and MyClass.
The MDN gives more details in its Introduction to Object-Oriented JavaScript.

Is possible to pass to a function the properties of an object without the arguments defined and use them by the object's keys?

Quick and strange question:
I have an object (in this example is small but in the project is larger):
var myObject = {
hello: 1, // easier I think
'hey.ya': 5 // quite impossible but the first option is valid too
}
then I want to pass somehow to a function and use "hello" for example in a closure like this
function x(){
// my closure
return function(){this.init = function(){alert(hello)}, this.heyYa = function(){alert(/* I do not know how to call the other hey.ya variable */)}}
}
var myClass = x(), instance = new myClass(); instance.init();
thanks!
You need to use the myObject
var myObject = {
hello: 1,
'hey.ya': 5
}
function x(obj){
return function(){
this.init = function(){
alert(obj.hello)
},
this.heyYa = function(){
alert(obj['hey.ya'])
}
}
}
var myClass = x(myObject);
var instance = new myClass();
instance.init(); // alerts '1'
instance.heyYa(); // alerts '5'

How inherits from lazy instantiation object?

In my JavaScript code I have a lazy instantiation object AAA. I want make new object BBB and inherits from AAA.
How it's make?
standard javascript inheritance may be achieved with prototypes
BBB.prototype = new AAA();
But in this way you can not access parent methods if they are overridden. For this reason I'm using static property superclass e.g.
function AAA() {}
AAA.prototype = {
foo: function() {return 'foo';}
}
function BBB() {}
BBB.superclass = AAA.prototype;
BBB.prototype = {
foo: function() { return BBB.superclass.foo() + "bar";}
}
b = new BBB();
b.foo() //returns foobar
I like to cheat, this will create objects inheriting from a common o. I took the liberty of renaming variables you asked in your question.
var o = {
happy: true,
fun: true,
time: true
}
var AAA = {
happy: false
};
AAA.__proto__ = o;
console.log( 'happy', AAA.happy );
console.log( 'fun', AAA.fun );

How do you access the main obj from obj.foo.bar in javascript?

Objects in javascript throw me for a loop!
In this set up...
var obj = {
someVar: "my awesome variable",
foo: {
bar: function(){
alert(this.someVar);
}
}
};
How would I get obj.foo.bar to correctly alert the value of someVar?
Using a captured obj:
var obj = {
someVar: "my awesome variable",
foo: {
bar: function(){
alert(obj.someVar);
}
}
};
alert(obj.someVar);
There's no clever way to walk up the ancestor chain. Objects don't know where they're contained, if you're looking for some type of this.parent type of notation. There's nothing to say that an object even has a single "parent".
foo.foo = new Object();
bar.bar = foo.foo;
bar.bar.parent == ???
A function in Javascript is invoked only in the context of the object which the . operator was applied to. It is not possible to walk up the chain, since Javascript objects are not intrinsically aware of their parent objects.
The only way to do this is to have a separate reference to obj. (Either as a property of bar or a separate variable)
Here's a generalized pattern I just cooked up for upwards traversal. Depending on your needs/assumptions, you can probably drop some complexity.
var obj = (function (parent) {
var obj = {
foo: "foo",
up: function () {
return parent;
}
};
obj.bar = (function (parent) {
var obj = {
baz: function () {
alert(this.up().foo);
},
up: function () {
return parent;
}
};
return obj;
}(obj));
return obj;
}(window));
obj.bar.baz(); // "foo"
It's almost certainly more trouble than it's worth.

Categories

Resources