How can I get parent options?
I would like to access a global myObject options
var myObject = {
method: function(){
this.options = {};
},
property: {
propertyMethod: function(){
alert(this.options);
}
}
}
myObject.method();
myObject.property.propertyMethod();
If you mean, you want to access myObject's options property from within property.propertyMethod, there's no way to do that except by taking advantage of the fact that propertyMethod is a closure over the myObject variable, e.g.:
var myObject = {
method: function(){
this.options = {};
},
property: {
propertyMethod: function(){
alert(myObject.options); // <=== Change is here
}
}
}
myObject.method();
myObject.property.propertyMethod();
...which isn't usually a good idea. :-) Instead, you may want to design your object differently. For instance:
var myObject = (function() {
var obj = {
method: function(){
obj.options = {};
},
property: {
propertyMethod: function(){
alert(obj.options);
}
}
};
return obj;
})();
myObject.method();
myObject.property.propertyMethod();
That way, you're using the execution context of the call to the function. But if you're going to do that, maybe take it to the next step:
function makeObject() {
var obj = {
method: function(){
obj.options = {};
},
property: {
propertyMethod: function(){
alert(obj.options);
}
}
};
return obj;
}
var myObject = makeObject();
myObject.method();
myObject.property.propertyMethod();
...so you can make more than one. Or even make a true constructor:
function MyObject() {
var obj = this;
obj.method = function(){
obj.options = {};
};
obj.property = {
propertyMethod: function(){
alert(obj.options);
}
};
}
var myObject = new MyObject();
myObject.method();
myObject.property.propertyMethod();
...although since you're not leveraging the prototype, there's no much reason to make it a constructor function.
You can use call to bind this to myObject
myObject.property.propertyMethod.call(myObject);
Related
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"
I'm not sure on the best approach to have object properties that are individual for each object in a OLOO inheritance chain.
Check this fiddle or consider the following code:
http://jsfiddle.net/HB7LU/19413/
Parent = {
array: [],
add: function(element) {
this.array.push(element + this.array.length.toString());
return this;
},
getAll: function() {
return this.array;
}
};
Child = Object.create(Parent, {
removeAllButOne: { value: function() {
this.array.splice(1);
return this;
}}
});
foo = Object.create(Parent);
foo.add('foo');
bar = Object.create(Child);
bar.add('bar');
In the fiddle a click on the foo or bar text will call the foo.add(...) or bar.add(...) function to add an element to the objects array, resulting in one extra <p> tag in the output.
The result is not what I want. Both foo and bar share the same array. But its easy to understand what happens, if we look up the object inheritance we can see the following:
Ok then, what can I do go get around this? There were two options that came to my mind:
Option 1)
http://jsfiddle.net/HB7LU/19419/
Parent = function() {
return {
array: [],
add: function(element) {
this.array.push(element + this.array.length.toString());
return this;
},
getAll: function() {
return this.array;
}
};
};
Child = Object.create(Parent(), {
removeAllButOne: { value: function() {
this.array.splice(1);
return this;
}}
});
foo = Object.create(Parent());
foo.add('foo');
bar = Object.create(Child);
bar.add('bar');
This would create a new Parent object, creating all the functions of the Parent object each time a Parent object is created or a child "inherits" from a (new) Parent object. While this solves the problem I had, it seems like a bad idea to always recreate the same functions over and over again for each child type object.
Option 2)
http://jsfiddle.net/HB7LU/19420/
Parent = Object.create({
add: function(element) {
this.array.push(element + this.array.length.toString());
return this;
},
getAll: function() {
return this.array;
}
}, {
ctor: { value: function(someArgs) {
this.array = [];
// maybe use someArgs
return this;
}}
});
Child = Object.create(Parent, {
removeAllButOne: { value: function() {
this.array.splice(1);
return this;
}}
});
foo = Object.create(Parent).ctor();
foo.add('foo');
bar = Object.create(Child).ctor();
bar.add('bar');
This seems to also solve the problem but avoids the recreation of the Parent object and its functions. So is this the way to go? What if I had multiple children in the inheritance chain that also have private properties?
Something like this?
Child = Object.create(Parent, {
ctor: { value: function(someArgs) {
this.__proto__.ctor(someArgs);
this.otherPrivate = {};
// maybe use someArgs
return this;
}},
removeAllButOne: { value: function() {
this.array.splice(1);
return this;
}}
});
Children would be shadowing the parent ctor with their own function... but in their ctor function they could call the parents ctor to not break functionality.
Thoughts and advice is highly appreciated, thanks!
Easiest way is to use Constructors so array is always created as an own property on the instance
// define Parent
function Parent() {
this.array = []; // array will be an instance property
}
Parent.prototype = {}; // inherit all the goodies from Object.prototype
Object.assign(Parent.prototype, { // using `Object.assign` for shorthand
add: function (element) {
this.array.push(element + this.array.length.toString());
return this;
},
getAll: function () {
return this.array;
}
});
// define Child
function Child() {
Parent.apply(this); // apply Parent constructor to the instance
}
Child.prototype = Object.create(Parent.prototype); // inherit Parent's prototype chain
Object.assign(Child.prototype, {
removeAllButOne: function () {
this.array.splice(1);
return this;
}
});
Now have
var a = new Child(),
b = new Child();
a.array === b.array; // false
You could also write this using ES 6's classes, but that is just syntactic sugar for what I've written above and will result in the same structures.
OLOO favours composition over inheritance. You could use a factory method pattern with Object.assign to compose objects with simple prototype delegation:
// Composable prototype objects, or "traits"
var base = {
add: function(element) {
this.array.push(element + this.array.length.toString());
return this;
},
getAll: function() {
return this.array;
}
};
var canRemoveAllButOne = {
removeAllButOne: function() {
this.array.splice(1);
return this;
}
}
// Factory functions
// You could think of these like external constructors
function createBase() {
return Object.assign({}, base, {
array: []
})
}
function createComposed() {
var base = createBase();
return Object.assign(base, canRemoveAllButOne)
}
// Test
function log(s) {
document.write(s + "<br>");
}
var b1 = createBase();
var b2 = createBase();
var c1 = createComposed();
var c2 = createComposed();
b1.add(1);
b1.add(2);
b2.add(9);
c1.add('a');
c2.add('b');
log(b1.getAll());
log(b2.getAll());
log(c1.getAll());
log(c2.getAll());
Sorry, I don´t know the name of this.
I want to have a function and an object with properties in only one variable.
Here is how it works:
var obj = function() {
return "foo";
};
obj.prop = "bar";
obj(); // => "foo"
obj.prop; // => "bar"
This works fine, but I would like to change the order of this:
var obj = { prop: "bar" };
obj = function() {
return "foo";
};
obj(); // => "foo"
obj.prop; // => undefined
Is there a way to do this?
I want do do this because I have a lot of properties to add to the object:
var obj = function() {
return "foo";
};
obj.prop1 = "bar1";
obj.prop2 = "bar2";
obj.prop3 = "bar3";
obj.prop4 = "bar4";
obj.prop5 = "bar5";
obj.prop6 = "bar6";
obj.prop7 = "bar7";
//...
This isn't possible because when you do:
obj = function() {
return "foo";
};
...you're assigning the variable obj to the new function, so it no longer points to the original object you created ({ prop: "bar" }) at all.
So if you want to add properties to a function object, you must always create the function first, then add properties.
As an alternative, you could do something like this:
var props = {
prop1: "bar1",
prop2: "bar2"
};
var obj = function() {
return "foo";
};
for (var key in props) {
obj[key] = props[key];
}
Or if you happen to have jQuery available (and don't have Object.assign available):
jQuery.extend(obj, props);
(Of course there are shims available for Object.assign, which would allow #Pointy's answer to work in older browsers.)
If you want to do this with one statement, ES2015 (and some libraries) let you do:
var obj = Object.assign(
function() { /* ... */ },
{ "hello": "world" }
);
Which will give you obj as a function with the property "hello". Note that this is really just the same thing as the separate assignment, but it's all wrapped up as one overall expression, which is nice because it means you can do something like
return Object.assign(function() { /* whatever */ }, {
prop: whatever,
// ...
});
I also agree with Grundy, but you could do something like that:
var x = function(){
var obj = {};
return {
objToReturn: obj,
objFunction: function(){return 'foo';},
addItemsToObject: function (key, value) {
obj[decodeURIComponent(key)] = value;
}
}
};
I honestly don't know if that's what you really want, but in that case you can execute the "x" function and after you can access the
"objFunction", the "objToReturn" or the "addItemsToObject" function.
So it will be something like that:
var y = x();
for (propertie in yourProperties){
y.addItemsToObject
(propertie, yourProperties[decodeURIComponent(propertie)]);
}
And then:
y.objFunction();
'foo'
Hope that helps.
I have a bunch of JSON string returned from an ajax call in a specific format and when starting to convert them all into my own Javascript object, I start to wonder if there is any easier way since we're talking Javascript here.
I'll have var manyOfThem = [ { name: 'a' }, { name: 'b' }, { name: 'c' } ];
And I'd like to easily associate each of these objects with my functions so that I can do things like:
myClass.prototype.doSomething = function() {
// do something to this.name
};
$.each(manyOfThem, function(index, item) {
item.doSomething();
});
I guess my concern is, I would not want to (because its repetitive) do this:
var myClass = function(item) {
this.name = item.name;
// do the same for the rest of item's potentially 20 properties
};
var oneOfThem = new myClass(manyOfThem[0]); // I think this is redundant....
oneOfThem.doSomething();
Anyhow, if there is also (security?) reasons why I'd just have to suck it up and do them all manually please share as well, thanks!
You mean, something like (see jsfiddle) :
var MyClass = function() {};
MyClass.prototype = {
doSomething: function() {
alert(this.name);
}
};
Then
var manyObj = $.map(manyOfThem, function(obj) {
return $.extend( new MyClass(), obj );
});
So you can call :
manyObj[0].doSomething(); // alert("a")
However, this approach will not preserve a direct copy with the manyOfThem object. (In the example above, changing manyOfThem[0].name = "foo"; will not affect manyObj[0] and a call to manyObj[0].doSomething(); will still alert "a". To preserve a direct reference to your object, do this :
var manyObj = $.map(manyOfThem, function(obj) {
function F() {};
F.constructor = MyClass;
F.prototype = obj;
$.extend(F.prototype, new MyClass());
return new F();
});
manyObj[0].doSomething(); // alert("a")
manyOfThem[0].name = "foo"; // modify the referenced object
manyObj[0].doSomething(); // alert("foo") ..also modifies the behaviour of the instance
One solution without using a class is
var manyOfThem = [ { name: 'a' }, { name: 'b' }, { name: 'c' } ];
function doSomething(){
console.log(this.name)
}
$.each(manyOfThem, function(index, item) {
doSomething.call(item);
});
Demo: Fiddle
If you want to create an instance of type MyClas then
var manyOfThem = [ { name: 'a' }, { name: 'b' }, { name: 'c' } ];
function MyClass(item){
$.extend(this, item);
}
MyClass.prototype.doSomething = function(){
console.log(this.name)
}
$.each(manyOfThem, function(index, item) {
var obj = new MyClass(item);
obj.doSomething()
});
Demo: Fiddle
You can do
var myClass = function(item){
for( i in item){
if (item.hasOwnProperty(i)){
this[i] = item[i];
}
}
};
This should reduce the repetitive assignments in myClass constructor.
Given the following:
var someObject = {};
someObject.prototype.a = function() {
};
someObject.prototype.b = function() {
//How can I call someObject.a in this function?
};
How can I call someObject.a from someObject.b? Thanks.
This will work:
someObject.prototype.b = function() {
this.a();
};
However your definition of someObject is slightly wrong, it should be:
var someObject = function() {};
Test script:
var someObject = function() {};
someObject.prototype.a = function() {
alert("Called a()");
};
someObject.prototype.b = function() {
this.a();
};
var obj = new someObject();
obj.b();
I think you probably meant to do this:
function Thingy() {
}
Thingy.prototype.a = function() {
};
Thingy.prototype.b = function() {
this.a();
};
var someObject = new Thingy();
It's constructor functions, not plain objects, that have a special prototype property. The prototype of a constructor function is assigned to all objects created with that constructor via the new keyword as their underlying prototype, which gives them default properties (which may reference functions, as they do above).