javascript declaring key value pair in a function - javascript

let us say i have a object in which there is a function and inside the function i have declared some key values.
if every function is an function object in javascript then it is totally legal to declare key value pair in it.
var a ={
a: "shiv",
b: "shiv1",
c: function(){
L:"shiv1",
console.log(L);
}
}
how can i access these keys. in what scenarios i need to add key value pairs to a function. what does this signify. For Example in this function, how can i access L key.
Edit 1:
Console.log line will through err.
let say we have only this code
var a ={
a: "shiv",
b: "shiv1",
c: function(){
L:"shiv1",
}
}
what does declaring a key in function signify. if i need to access L key how can i

You every function is also an object, meaning that you can indeed set properties to it. In fact every function has length property, which denotes the number of formal arguments this function accepts.
However the syntax you are using to set function properties is not how you should do it. Even though you are using perfectly valid syntax, this is label statement, not property definition syntax. If you wanted to set a property to a function object in your case you would do it like this:
function c() {
console.log(c.L) // => "I'm a property of c function"
}
c.L = "I'm a property of c function";
var a = {
a: "shiv",
b: "shiv1",
c: c
}
When it can be useful? Like I said there is a limited use for it, like length property of the function, but in many cases you would not need setting properties on a function level directly.

This has to be throwing errors:
L:"shiv1",
console.log(l);
You probably want:
c: function(){
return {L:"shiv1"};
}
And then access it as:
a.c().L;
Full example here:
var a ={
a: "shiv",
b: "shiv1",
c: function(){
return {L:"shiv1"}
}
}
alert(a.c().L);

You can't declare keys like you did inside the function.
This doesn't work:
c: function(){
L:"shiv1", //Declaration don't work in this context
console.log(l); //Don't work
}
Try this (Please, remove the "function" statement):
c: {
L:"shiv1"
}
Also, you can do this:
c: function() {
var test = "shiv1";
return test;
}
If you want to work with parameters:
c: function(a, b) {
var test = a + " shiv1 " + b;
return test;
}
Or:
c: function(a, b) {
var total = a + b;
return total;
}

Related

Javascript object with shared name

So, I'm trying to create an object like:
var a = {
b: "object_id",
b: function(){ return c(this.b); }
}
var c = {
"object_id": {
foo: "bar"
}
}
But it only registers the last value for the key 'b'. But I think I've seen something like this used before and it would really help me if I could call a.b().foo or if I just want ID a.b
Is there any way to make this happen or will I have to rename value and/or method?
You're looking for the Object Getter/Setter notation.
var o = {
_b: 7,
get b() {
return this._b + 1;
},
}
That being the case, you CAN'T use the same object id, and should store the internal variable for b in a closure, if you need it to be totally private.

Deleting an object-property passed as a function argument

I'm trying to delete an object property:
var test = {abc: 1};
console.log(delete test.abc); //works fine and returns 'true'
The following construct drives me crazy
function deleteNode(_node) {
console.log(delete _node);
}
deleteNode(test.abc); // does not work and returns 'false'
Why? I read many questions on stackoverflow regarding trouble with delete and read most of the typical links provided. But I can't find a solution to this simple problem...
Deleting dynamic props of an object could be achieved like this:
function deleteNode(obj, key) {
delete obj[key]
}
See the delete docs for more details.
When having a "path" like "a.b.c" you can use lodash unset which deletes nested entries:
var object = { 'a': { 'b': { 'c': 7 } } };
_.unset(object, 'a.b.c');
Use of eval is discouraged .
var test = {abc: 1};
function deleteNode(_node) {
console.log(delete _node);
}
deleteNode(test.abc);
When you invoked deleteNode above, test.abc already resolved to 1 before being passed to function. deleteNode is technically invoking delete 1. And according to ES standard, deleting a function argument directly results in false or gives an error in strict mode.
"use strict";
var test = {a: 1};
function del(a) {
console.log(delete a);
}
del(test.a);
You will need to pass the object and key as different arguments to method.
var test = {abc: {a: 1, b: 2, c: {d: 1}}};
function deleteNode(obj, key) {
console.log(eval('delete obj.' +key));
}
deleteNode(test, 'abc.c.d');
console.log('test is', test)

setting javascript object properties from constructor default values using parameter destructuring

This is a bit of a tricky question regarding ES6 destructuring with default usage in a javascript object constructor.
I would like to receive a destructured parameters object with default values for my object constructor
so what i did was this
function bla({a=3,b=6}={}){
this.a=a;
this.b=b;
console.log(`this.a::'${this.a}' this.b::'${this.b}' a::'${a}' b::'${b}'`);
}
let myObject= new bla({a:1});
console.log(`myObject.a::'${myObject.a}' myObject.b::'${myObject.b}'`); // only a got overriden with value "1" and b remained its defauly value "6"
I know that what i did works. However, you can see that this is a bit of a code smell, because every time i need to add a new parameter to the constructor (for example {newParameter=3}) i also need to go down and add a matching line like this in the constructor body
this.newParameter=newParameter;
Is there any more elegant way to add a destructured parameter with default value which automatically is attached to "this."
I personally think your current approach is the most readable, but you can technically also do
function bla(obj = {}){
({
a: this.a = 3,
b: this.b = 6,
} = obj);
console.log(`this.a::'${this.a}' this.b::'${this.b}'`);
}
Don't know if this is best, but you could use Object.assign.
function bla(props={}) {
Object.assign(this, {a:3,b:6}, props);
console.log(`this.a::'${this.a}' this.b::'${this.b}'`);
}
let myObject= new bla({a:1});
console.log(`myObject.a::'${myObject.a}' myObject.b::'${myObject.b}'`); // only a got overriden with value "1" and b remained its defauly value "6"
You lose the parameter names, but it could be argued that this is better so that you don't accidentally mutate the parameter when you meant to mutate the object property.
I follow more a functional style to avoid the new on object creation and this keyword.
Explanation
You could simply write a function that retuns an object and takes several arguments with default values.
Thanks of the object literal property value shorthand you have less to write.
Code
function returnObject(a = 1, b = 2, c = 3) {
return {
a,
b,
c
}
}
console.log(returnObject())
If the objective is to use the variable names exactly once then this is what I'd do:
const foo = new Foo({ a: 1 });
console.log(`foo { a: ${foo.a}, b: ${foo.b} }`);
function Foo(config = {}) {
const defaults = { a: 3, b: 6 };
for (const [key, val] of Object.entries(defaults))
({ [key]: this[key] = val } = config);
}
Now, you only need to update the defaults object and you're done.
Actually, let's make a constructor constructor by abstracting this pattern:
const Foo = defcons({ a: 3, b: 6 });
const foo = new Foo({ a: 1 });
console.log(`foo { a: ${foo.a}, b: ${foo.b} }`);
function defcons(defaults) {
return function (config = {}) {
for (const [key, val] of Object.entries(defaults))
({ [key]: this[key] = val } = config);
};
}
Now, you can easily create as many such constructors as you want.

Why can't I use a defined function inside another defined function,when creating an js object?

The code goes like this
var ob = {
a: function() {
b()
},
b: function() {
console.log("hi")
}
};
As you can see, you can't do
ob.a() //returns error
Can someone explain the reason in depth?
Becuase b does not exist in the current scope (which is the global one in this case).
This works, however:
var ob = {
a: function () {
this.b()
},
b: function () {
console.log('hi')
}
};
because this refers to the ob object.
There is no function b defined anywhere, it's a property of object ob, so you can refer it as this.b from inside a:
var ob = {
a: function () {
this.b();
},
b: function () {
console.log("hi");
}
};
ob.a();
You could also access b as ob.b().
The b is a property of the object called ob. That being said, if you use
ob.b
instead of b you will solve your problem.
var ob = {
a:function(){
ob.b()
},
b:function(){
console.log("hi")
}
};
Another way to do achieve this is to use the this operator.
var ob = {
a:function(){
this.b()
},
b:function(){
console.log("hi")
}
};
The this holds a reference to the object you define. Hence using it you can access is properties. It is a better way that the first way, because if you decide later to alter the name of ob to obj, you will not have change it in two places.

JavaScript does not define a method within an array

I have the following situation:
var a = {
b: function() {
alert('hi');
},
c: [{m: this.b}]
};
alert(typeof a.c[0].m);
The output is "undefined". What is the reason for this?
Because you are using this keyword inside an object. In that case this.b is referring to something undefined which should be a property of window.
Read this article, it is very useful to understand scopes.
In this case, you should declare your variable like this:
b = 't'; //note there is not keywork var, it is a window global variable
var a = {
c: [{
b: 'a',
m: this.b //is 't'
}],
b: function() {
alert('hi');
}
};
alert(a.c[0].m); //will display 't'
Because (assuming you are executing this in the context of a browser) this is window and you haven't defined window.b.
The value of this is determined by the way you execute the current function, not by an object literal.
MDN has further reading about this.
When the value for a.c[0].m is run, this doesn't refer to a, it refers to the entire scope.
If you want the behaviour you are after, you need to change it to:
var a = { b: function() { alert('hi'); }, c: [{}] };
a.c[0].m = a.b;

Categories

Resources