How convert Object to Function in javascript - javascript

How do I convert the Object into a function
var FRUIT = {};
FRUIT.color={
name: "",
foo: function(){
return this.name;
},
yellow: {
yellow1: 0,
yellow2: 0
}
};
var castFunction = function(){};
$.each( FRUIT.color, function(i, prop){
castFunction.prototype[i] = prop;
});
var classSmall = new castFunction();
var classBig = new castFunction();
classSmall.name="Yellow small Fruit";
classBig.name="Yellow big Fruit";
classSmall.yellow.yellow1=100;
classBig.yellow.yellow1=10000;
console.log( classSmall.foo() );//Yellow small Fruit ==> OK
console.log( classBig.foo() );//Yellow big Fruit ==> OK
console.log( classSmall.yellow.yellow1 );//10000 ==> why
I set it 100 instead of 10000
why first class value can be changed from the second class.
Actually, the above problem is not a problem if I use the function but I just wanted to know where the errors above or indeed it could not be done.

Try this way
var A = function(foo) {
var B = function() {
return A.prototype.constructor.apply(B, arguments);
};
B.prototype = A.prototype;
return B;
};

Related

javascript failed to set private variables

I have created a class-like structure with a private variable. The code is as follows:
   
var sinan = function(){
var a = {ssss: 1};
return {
get: function(){
return a;
},
set: function(s){
a = {ssss: s}
}
}
}
When I do
sinan().get(); // outputs {ssss: 1}
sinan().set(2);
sinan().get(); // outputs {ssss: 1}
It didn't output {ssss: 2}. Does anyone know what is happening? Thanks.
Since your "class" is not singleton sinan() constructs new instance every time with a.sss being equal to 1.
What you want to do is to create only once instance and use it:
var s = sinan();
console.log( s.get() );
s.set(2);
console.log( s.get() );
Of course you can make sinon singleton too if you want. For example, here is a simple implementation with instance stored in closure:
var sinan = function () {
var instance;
return function () {
if (!instance) {
instance = function() {
var a = {ssss: 1};
return {
get: function () {
return a;
},
set: function (s) {
a.ssss = s
}
}
}();
}
return instance;
};
}();
So in this case sinan() === sinan(), i.e. sinan() returns the same object every time.
Demo: http://jsfiddle.net/r07wgyjt/
Your problem is that each time you call sinan(), a new sinan instance is created, so it's the same as :
var s1 = sinan();
s1.get(); // 1
var s2 = sinan() ;
s2.set(2); // 2
var s3 = sinan();
s3.get(); // 3
You should be doing :
var s1 = sinan();
s1.get(); // 1
s1.set(2); // 2
s1.get(); // 2

Can a JavaScript function know its own name, including object it is contained within

I need a number of JavaScript functions to know their own names, including the object they are contained within. I can't seem to find a way to do this. All the examples on SO don't quite fit my use case. Here is a fiddle of what I'm looking for: http://jsfiddle.net/amczpro7/5/
window.myMainNameSpace = {};
myMainNameSpace.y = {
z: function(funcToCall) {
var x = eval("new " + funcToCall);
}
}
myMainNameSpace.a = {
b: function(args) {
alert('I want to alert: myMainNameSpace.a.b');
/*
var myName = arguments.callee.toString();
myName = myName.substr('function '.length);
myName = myName.substr(0, myName.indexOf('('));
alert(myName);
console.log(arguments.callee);
console.log(this.constructor);
console.log(this.name);
console.log(this);
console.log(this.constructor.toString());
*/
}
}
myMainNameSpace.y.z('myMainNameSpace.a.b({arg1:123})');
I would like to be able to make a function that would return myMainNameSpace.a.b or myMainNameSpace.a.b() so that I could place it in a handful of functions. Is this possible? Thanks!
You could do it without eval, you just have to iterate over each letter until aimSign is reached. In each iteration you put a new object within last nested object:
function callObjTail(obj){
var lastObj;
var lastSign;
for(var i='a'.charCodeAt(); true; i++){
console.log(i);
if(obj[String.fromCharCode(i)]){
lastObj = obj;
lastSign = i;
obj = obj[String.fromCharCode(i)];
}
else{
break;
}
}
if(lastObj){
lastObj[String.fromCharCode(lastSign)]();
}
else{
obj[Object.keys(obj)[0]]();
}
}
function buildObj(aimSign){
var obj = {};
var head = obj;
var nests = '';
for(var i='a'.charCodeAt(); i < aimSign.charCodeAt(); i++){
obj[String.fromCharCode(i)] = {};
obj = obj[String.fromCharCode(i)];
}
return { head : head, tail: obj };
}
var obj = buildObj('e');
console.log(obj.head); // { a: { b: { c: { d: {}}}}
console.log(obj);
obj.tail.e = function(){ console.log('tail called');};
console.log(obj.head.a.b.c.d.e());
console.log(obj.tail.e());
// call tail at the end
callObjTail(obj.head);
callObjTail(obj.tail);

Javascript, implementing custom Object.Create

I need to implement inheritance tree in JavaScript where each node can have more than 1 parent. We have to implement Object.Create and Object.call methods on our own. We are specifically not allowed to use new keyword. Here is what I have so far:
var myObject = {
hash:0,
parents: [],
create: function(args){
//TODO check if not circular
if(args instanceof Array){
for(i=0;i<args.length;i++){
this.parents.push(args[i]);
}
}
return this;
},
call : function(fun,args){
//TODO: dfs through parents
return this[fun].apply(this,args);
},
}
var obj0 = myObject.create(null);
obj0.func = function(arg) { return "func0: " + arg; };
var obj1 = myObject.create([obj0]);
var obj2 = myObject.create([]);
obj2.func = function(arg) { return "func2: " + arg; };
var obj3 = myObject.create([obj1, obj2]);
var result = obj0.call("func", ["hello"]);
alert(result);
//calls the function of obj2 istead of obj0
The problem with this code is that I get a call to obj2's function instead of obj0's. I'm suspecting that create() function should not return this, but something else instead (create instance of itself somehow).
In your current solution, you are not actually creating a new object with your myObject.create() function, you are just using the same existing object and resetting it's parent array. Then, when you define .func() you are overriding that value, which is why func2: appears in your alert.
What you need to do is actually return a brand new object. returning this in your myObject.create() will just return your existing object, which is why things are getting overridden.
To avoid using the new keyword, you'll want to do either functional inheritance or prototypal inheritance. The following solution is functional inheritance:
function myObject (possibleParents) {
//create a new node
var node = {};
//set it's parents
node.parents = [];
//populate it's parents if passed in
if (possibleParents) {
if (possibleParents instanceof Array) {
for (var index = 0; index < possibleParents.length; index++) {
node.parents.push(possibleParents[index]);
}
} else {
node.parents.push(possibleParents);
};
}
//
node.call = function(fun,args) {
return this[fun].apply(this,args);
};
return node;
};
var obj0 = myObject();
obj0.func = function(arg) { return "func0: " + arg; };
var obj1 = myObject([obj0]);
var obj2 = myObject();
obj2.func = function(arg) { return "func2: " + arg; };
var obj3 = myObject([obj1, obj2]);
var result = obj0.call("func", ["hello"]);
alert(result); // this will successfully call "func0: " + arg since you created a new object
I managed fix this problem only by using function instead of variable.
function myObject () {
this.parents = [];
this.setParents = function(parents){
if(parents instanceof Array){
for(i=0;i<parents.length;i++){
this.parents.push(parents[i]);
}
}
};
this.call = function(fun,args) {
return this[fun].apply(this,args);
};
}
var obj0 = new myObject();
obj0.func = function(arg) { return "func0: " + arg; };
var obj2 = new myObject();
obj2.func = function(arg) { return "func2: " + arg; };
var result = obj0.call("func", ["hello"]);
alert(result);

Getting a reference to the object that holds a property that is a constructor

The title is really confusing, I couldn't find a better one.
Suppose I have:
var A = function (){
this.pa = { x: 1 };
};
A.prototype.B = function (){
this.pb = /* a reference to { x: 1 } */;
};
var a = new A ();
var b = new a.B ();
console.log (b.pb.x); //should print 1
a.pa.x = 2;
console.log (b.pb.x); //should print 2
I want to save in pb a reference to the pa object. Is it possible?
A function used as a constructor has only a reference to the new instance, inheriting from its prototype.
To make it maintain a reference to the original A instance, you will need to put the B constructor in a closure:
function A() {
var that = this;
this.pa = { x: 1 };
this.B = function() {
this.pb = that.pa;
};
};
var a = new A ();
var b = new a.B ();
console.log (b.pb.x); // does print 1
a.pa.x = 2;
console.log (b.pb.x); // does print 2
However, this has the disadvantage of creating a new B constructor (with its own prototype object) for every single A instance. Better would be something like
function A() {
this.pa = { x: 1 };
}
A.B = function() {
this.pb = null;
};
A.prototype.makeB = function() {
var b = new A.B();
b.pb = this.pa;
return b;
};
// you can modify the common A.B.prototype as well
var a = new A ();
var b = a.makeB();
console.log (b.pb.x); // does print 1
a.pa.x = 2;
console.log (b.pb.x); // does print 2
Yet, we could mix the two approaches so that you have only one prototype but different constructors:
function A() {
var that = this;
this.pa = { x: 1 };
this.B = function() {
this.pb = that.pa;
};
this.B.prototype = A.Bproto;
}
A.Bproto = {
…
};
var A = function (){
this.pa = { x: 1 };
};
A.prototype.B = function (a){
this.pb = a.pa;
};
var a = new A ();
var b = new a.B(a);
console.log(b.pb.x); //should print 1
a.pa.x = 2;
console.log(b.pb.x);
Well, it's not exactly what I want but it's very close:
var A = function (pa){
this.pa = pa;
};
A.prototype.B = function (a){
if (this instanceof A.prototype.B){
if (!a) throw "error";
this.pb = a.pa;
return;
}
return new A.prototype.B (this);
};
var a = new A ({ x: 1 });
var b = a.B ();
console.log (b.pb.x); //1
a.pa.x = 2;
console.log (b.pb.x); //2
new a.B () //throws "error"

Javascript and module pattern

i think i did not understand javascript module pattern.
I just create this module:
var mycompany = {};
mycompany.mymodule = (function() {
var my = {};
var count = 0;
my.init = function(value) {
_setCount(value);
}
// private functions
var _setCount = function(newValue) {
count = newValue;
}
var _getCount = function() {
return count;
}
my.incrementCount = function() {
_setCount(_getCount() + 1);
}
my.degreeseCount = function() {
_setCount(_getCount() - 1);
}
my.status = function() {
return count;
}
return my;
})();
var a = mycompany.mymodule;
var b = mycompany.mymodule;
console.debug(a, 'A at beginning');
console.debug(a, 'B at beginning');
a.init(5);
b.init(2);
console.log('A: ' + a.status()); // return 2 (wtf!)
console.log('B: ' + b.status()); // return 2`
Where is the mistake?
I thought that my code would have returned to me not 2 value, but 5.
What's the reason?
a and b are the exact same objects.
var a = mycompany.mymodule;
var b = mycompany.mymodule;
What you want to do is create two different objects which have the same prototype. Something similar to this:
mycompany.mymodule = (function () {
var my = function () {};
my.prototype.init = function (value) {
_setCount(value);
};
my.prototype.incrementCount = ...
// ...
return my;
}());
a = new mycompany.mymodule();
b = new mycompany.mymodule();
a.init(5);
b.init(2);
For more info, research "javascript prototypal inheritance"
In JavaScript, objects are passed by reference, not copied.
To explain further, here is a simplified version of your code:
var pkg = (function () {
var x = {};
return x;
}());
var a = pkg;
var b = pkg;
You do not create two separate objects but only reference the object pointed at by pkg from both a and b. a and b are exactly the same.
a === b // true
This means that calling a method on a you are ultimately doing the same to b (it points to the same object—x.)
You don't want to use the module pattern for this. You want the usual constructor+prototype.
function Pkg() {
this.count = 0;
};
Pkg.prototype.init = function (count) { this.count = count; };
var a = new Pkg();
var b = new Pkg();
a === b // false
a.init(2);
a.count === 2 // true
b.count === 2 // false
Here is a good read about module pattern.

Categories

Resources