JS how to get a variable name inside of a objective variable? - javascript

I am a beginner of js. I tried find a solution over internet but I couldnt.
Is there a way to know what is the name of a variable??
On below, i will be the value of each parameter......, Please advice!!!
Object = { a: xxx, b : xxx };
for(var i in Object ) { if(/* i`s variable name is 'a'*/){ /* do something*/ } }

As per your example:
obj = { a: 'aaa', b: 'bbb' };
for (var i in obj) {
if (i === 'a') {
//do something
}
}
Another method without looping through the object:
obj = { a: 'aaa', b: 'bbb' };
if ('a' in obj) {
// do something
}

Related

How to create properties to and object dynamically based on another object in JavaScript?

I have a scenario where from a source object I need to create a new result object.
The object would need to have exactly all properties from source, with the addition of "methods", with naming based on the properties and code to be executed based on a template (in my case alert(this.x)).
Note: script should keep in consideration any number of properties from source
I would like to know:
Is it possible to do it in JS?
What the appropriate Technics?
Any examples?
FROM SOURCE OBJECT
var source = {
a: 'a',
b: 'b'
};
I NEED TO GET RESULT OBJ DYNAMICALLY CREATED (BY SOME FUNCTION)
var result = {
a: 'a',
b: 'b',
_setA: function(){
alert(this.a);
},
_setB: function(){
alert(this.a);
}
}
Note: result is created after processing the source object
EDIT:
final solution based on your answers
http://jsfiddle.net/kbnd6e5c/1/
You can first use $.extend method to copy properties, and then you need iterate through properties and create dynamic setters. For example like in below code:
var source = { a: 'a', b: 'b' };
var result = $.extend({}, source);
Object.keys(source).forEach(function(key) {
result['_set' + key[0].toUpperCase() + key.slice(1)] = function(value) {
alert(this.key);
this[key] = value;
}
});
Check the working demo below.
var source = { a: 'a', b: 'b', test: 'test' };
var result = $.extend({}, source);
Object.keys(source).forEach(function(key) {
result['_set' + key[0].toUpperCase() + key.slice(1)] = function(value) {
this[key] = value;
}
});
alert([ result.a, result.test ]);
result._setA('a1');
result._setTest('test1');
alert([ result.a, result.test ]);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
I'm not sure I have fully understanding your question but I think you should juste use that simple thing:
var copy = result
copy.example = {
x: Y,
z, T
}
copy.newFuntion = function(){...} //add your own function
This way you have everything that result have + your own things
You can do something like this:
var result = {
a: 'A',
b: 'B'
};
var copy = result;
Object.keys(result).forEach(function(key) {
Object.defineProperty(copy, "_set" + key, {
get: function() {
return result[key];
}
})
});
copy._seta;
copy._setb;
Source

Javascript create reference to an object property?

I understand that in javascript, primitives are passed by value and objects are passed by reference.
I'm interested in creating a workaround of some kind that would let me get a reference to an object property containing a primitive. For example, what I wish would work is:
var someObject = {a: 1, b: 2};
var myRef = someObject.b;
myRef ++;
someObject.b #=> 3
Of course, this doesn't work. I'm aware that you could create a getter and setter function instead, or use one object to reference another object, but what I'd really like is some kind of workaround that allowed me to define a variable as a reference to the property of another object, and so far it seems this just can't be done.
So, my question is simply: is this even possible, and if so, how?
Primitive types are immutable, so no, it's not possible. You can wrap your primitive type with an object, like this:
function MyNumber(n) { this.n = n; }
MyNumber.prototype.valueOf = function() { return this.n; }
var someObject = { a: 1, b: new MyNumber(2) };
var myRef = someObject.b;
MyNumber.call(myRef, myRef + 1);
console.log(+someObject.b); // convert to number with +
OR
var someObject = {
a: { value: 1 },
b: { value: 2 },
};
var myRef = someObject.b;
my_inc(myRef); // function my_inc (obj) { obj.value++; }
// someObject.b.value == 3
The React framework uses a very simple pattern to encapsulate values.
function Link(value, requestChange)
{
this.value = value;
this.requestChange = requestChange;
}
You can pass around the object, the current value can be accessed by inspecting the value property of the object, if you want to change it you can call requestChange with a new value, you can change the value. The advantage would be to have the actual "storage location" and the logic for changing the value decoupled from the value read and write access. Note that the values can also be complex objects.
You could also achieve something similar with closures:
var someObject = {
a: 1,
b: 2
};
function property(object, prop) {
return {
get value () {
return object[prop]
},
set value (val) {
object[prop] = val;
}
};
}
var ref = property(someObject, "b");
ref.value; // 2
++ref.value; // 3
someObject.b; // 3
This works because the getter and setter functions have access to whatever bindings were in scope at the time of their creation (object and prop). You can now pass ref around, store it in a data structure, etc.
No, there isn't a nice way to do it.
You can use a work-around if you want to. Something like wrapping all your primary data types with single element arrays:
var someObject = {a: [1], b: [2]};
var myRef = someObject.b;
myRef[0]++;
someObject.b[0]; // 3
That's less than ideal though, as you have to use [0] to access the property all the time. There are some cases where it can be useful though, and the default toString of a single element array is just the toString of its element, so you can use the property directly in a string context:
console.log('My value: ' + someObject.b); // 'My value: 3'
if you want to "link" or "synchronize" two properties , each of a different object, you could do it like this:
var someObject = {
a: 1,
b: 2
};
var linkedObject = {
a:1,
b:2
}
function property(object, prop) {
return {
get value () {
return object[prop]
},
set value (val) {
object[prop] = val;
}
};
}
var s_prop = 'b'
var o_ref = property(someObject, s_prop);
var tmp = linkedObject[s_prop];
Object.defineProperty(
linkedObject,
s_prop,
{
set: function(value) {
o_ref.value = value;
},
get: function() {
return o_ref.value
}
}
);
linkedObject[s_prop] = tmp
someObject.b = 333 /// linkedObject.b is also 333 now
console.log(someObject.b) // 333
console.log(linkedObject.b)// 333
linkedObject.b = {"test": 2}
console.log(someObject.b) // {test:2}
console.log(linkedObject.b)// {test:2}
someObject.b.test = 3
console.log(someObject.b) // {test:3}
console.log(linkedObject.b)//{test:3}
I don't know how satisfying this is, but you could do it if you were ok with wrapping the desired object in an object like so:
var a = {a:{a:1},b:2};
var b = a.a;
b.a++;
a.a.a //=> 2
It isn't exactly what you asked for, but it would work.

How to conditionally add properties to a javascript object literal

I am trying to do the following to satisfy the requirements of a code builder (Sencha Cmd to be specific).
This is the essence I what I need to do. The critical factor is that the function body MUST end with a return of an object literal. I cant return a variable due to restrictions in the builder. So, how to add a property 'b' at the point of the pseudo code below if the parameter 'includeB' is true, but NOT add a property AT ALL if it is false. ie b==undefined or b==null is not allowed.
Perhaps it is not possible.
function create(includeB) {
// Can have code here but the final thing MUST be a return of the literal.
// ...
return {
a : 1
// pseudo code:
// if (includeB==true) then create a property called b
// and assign a value of 2 to it.
// Must be done right here within this object literal
}
}
var obj = create(false);
// obj must have property 'a' ONLY
var obj = create(true);
// obj must have properties 'a' and 'b'
Thanks for reading and considering,
Murray
If you can use ES6, use the spread properties.
function create(includeB) {
return {
a : 1,
...(includeB ? { b: 2 } : {}),
};
}
You've pretty much shown a use case for a constructor function instead of using an object literal:
function CustomObject(includeB) {
this.a = 1;
if (includeB) {
this.b = 2;
}
}
//has `a` only
var obj1 = new CustomObject(false);
//has `a` and `b`
var obj2 = new CustomObject(true);
After re-reading your question it appears that you've got limited access in modifying the function. If I'm understanding your question correctly you can only change a limited portion of the script:
function create(includeB) {
// modifications may be done here
// the rest may not change
return {
a : 1
}
}
var obj = create(false);
// obj must have property 'a' ONLY
var obj = create(true);
// obj must have properties 'a' and 'b'
If that's the case, then you could simply skip the later part of the function:
function create(includeB) {
if (includeB) {
return {
a: 1,
b: 2
};
}
return {
a: 1
};
}
You cannot put boolean logic inside a javascript literal definition. So, if your builder requires the the returned object can ONLY be defined as a javascript literal, then you cannot define properties conditionally that way.
If you can create an object inside your function, modify that object using logic and then return that object, then that's pretty easy.
function create(includeB) {
var x = {
a: 1
};
if (includeB) {
x.b = 2;
}
return x;
}
Your other option would be to wrap the create function and do it outside the create function.
function myCreate(includeB) {
var x = create(includeB)
if (includeB) {
x.b = 2;
}
return x;
}
Or, you could even wrap the create function transparently so callers still use create(), but it's behavior has been altered.
var oldCreate = create;
create = function(includeB) {
var x = oldCreate(includeB);
if (includeB) {
x.b = 2;
}
return x;
}
I recently had to do this, and found you could use a self-calling function within an object's definition (if using ES6). This is similar to the accepted answer, but might be useful for others who need to do this without first defining a constructor function.
For example:
let obj = (() => {
let props = { a: 1 };
if ( 1 ) props.b = 2;
return props;
})();
makes the object: { a: 1, b: 2 }
It's handy for more complicated objects, keeping the construction continuous:
let obj = {
a: 1,
b: (() => {
let props = { b1: 1 };
if ( 1 ) props.b2 = 2;
return props;
})(),
c: 3
}
makes the object:
{
a: 1,
b: {
b1: 1,
b2: 2
},
c: 3
}
You could define it later:
var hasA = create(); // has hasA.a
var hasBoth = create();
hasBoth.b = 2; //now has both
Alternatively, using your argument in create:
function create (includeB) {
var obj = {
a : 1
};
if (includeB) {
obj.b = 2;
}
return obj;
}
Below should work. I hope this help.
function create(includeB){
var object = {
a: 1
};
if (includeB)
object.b = 2;
return object;
}
How about this:
function create(includeB) {
return includeB && { a:1, b:2 } || { a:1 };
}
When includeB is true, the create function will return {a:1, b:2}. If includeB is false, it will return whatever is after the or - in this case, the {a:1} object.
create(true) returns { a:1, b:2 }.
create(false) returns { a:1 }
If you would like to use a declaration to satisfy the same requirement once without too much bloat, you can also simply do the following:
var created = function(includeB) {
var returnObj = { a : 1 };
if(includeB) { returnObj.b = 2; }
return returnObj;
}}(); //automatically runs and assigns returnObj to created

Parse object dot notation to retrieve a value of an object

I'm finding myself struggling with a little problem.
Let's say I've got an object:
var foo = {
bar: {
baz: true
}
};
Now I also have a String 'foo.bar.baz'. I'd now like to retrieve the value from the object using the string.
Please note: This is just an example, the solution needs to be dynamic.
Update:
I need the variable name also to be dynamic and parsed from the string. Also I can't be sure that my variable is a property of the window.
I have already built a solution using eval, but this is pretty ugly I think:
http://jsfiddle.net/vvzyX/
For example,
function get(obj, path) {
return path.split('.').reduce(function(obj, p) {
return obj[p]
}, obj);
}
Demo:
tree = {
foo: {
bar: 1,
baz: { quux: 3 },
},
spam: 1
}
console.log(get(tree, 'foo.baz.quux')) // 3
Here is how you can do this:
function getValue(namespace, parent) {
var parts = namespace.split('.'),
current = parent || window;
for (var i = 0; i < parts.length; i += 1) {
if (current[parts[i]]) {
current = current[parts[i]];
} else {
if (i >= parts.length - 1)
return undefined;
}
}
return current;
}
var foo = {
bar: {
baz: true
}
};
console.log(getValue('foo.bar.baz')); //true
The first argument of the function is the namespace (dot separated values) and the second one is the parent object, if parent is not provided then window is used.
One more example using the parent argument:
var str = 'foo.bar.baz';
foo = {
bar: {
baz: true
}
};
result = getValue(str, foo);
console.log(result);
Here is an example in jsfiddle.
Similar approach is used in YUI. Their approach is called Namespace pattern. The main benefit is simulation of packages/namespaces. The only difference between this script and the namespace pattern is that the namespace function creates nested structure instead of only returning value.
Try this:
var name = [window].concat('foo.bar.baz'.split('.')).reduce(function(prev, curr) {
return prev[curr];
});
console.log(name);
// -> 'true'
What I can think of is using string split to split that string into an array first, and access the object via [] to access the attribute of that object with a loop

split '{a}{b}{c}'?

I have an object that looks like
var obj = {
a: {
a: {
a: 'value'
}
},
b: {
a: {
a: 'value2'
},
b: {
a: 'value3'
}
}
}
I have a function which gets given a mask that looks like {b}{a}{a} what I want to do is get the value at obj.b.a.a how can I do this?
Slice off the first and last character, split by }{, and then recursively access the object with each element in turn (since foo.bar and foo['bar'] are equivalent).
This will work if your mask always has three properties. If not, you can write a function that does something similar:
var mask = "{a}{b}{c}";
var props = mask.replace(/{|}/g, "");
obj[props[0]][props[1]][props[2]];
obj.getMask = function(s) {
var o=this, attrs=s.slice(1,s.length-1).split("\}\{");
while (attrs.length > 0) {
o = o[attrs.shift()];
if (!o) return null;
}
return o;
};
obj.getMask("{a}{a}{a}"); // => "value"
obj.getMask("{b}{a}{a}"); // => "value1"
obj.getMask("{x}{y}{z}"); // => null
Of course, you can change the signature to pass in "obj" instead of using this if you don't want to muck up the object itself.
You can use reduce rather than use recursion. Here's a one-liner:
function index(obj, indexList) {
return indexList.reduce(function(obj,x){return obj[x]}, obj);
}
function indexWithMask(mask) {
return index(obj, mask.slice(1,-1).split('}{'));
}
Here is my code without using eval. Its easy to understand too.
function value(obj, props) {
if (!props) return obj;
var propsArr = props.split('.');
var prop = propsArr.splice(0, 1);
return value(obj[prop], propsArr.join('.'));
}
var obj = { a: { b: '1', c: '2', d:{a:{b:'blah'}}}};
console.log(value(obj, 'a.d.a.b')); //returns blah
If you are still using the mask part, you can modify a bit on the code.
function value(obj, props) {
if (!props) return obj;
var propsArr = props.match(/\{[a-zA-Z1-9]+\}/g);
var prop = propsArr.splice(0, 1);
return value(obj[prop[0].replace('{', '').replace('}', '')], propsArr.join(''));
}

Categories

Resources