Getting Object Key Name from inside function? - javascript

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"

Related

Javascript + Angular + Prototype clear object properties

I am a bit confused, I would like to have a function that clears all the properties of an object which is available to all the instances of an object. So, I have added a prototype clear() function. This is the following code:
(function () {
Supplier.$inject = [];
angular.module('webclient').factory('Supplier', Supplier);
function Supplier() {
Supplier.prototype = {
clear: function () {
for (var key in this) {
//skip loop if the property is from prototype
if (this.hasOwnProperty(key))
continue;
console.log("key:" + key);
this[key] = undefined;
}
},
}
return Supplier;
};
})();
So, I would like to be able to clear all the properties of the current supplier object. So, if the supplier object had the following properties:
SupplierID:21,
Email:None
I would like to set the properties to undefined. I would use the class as following:
var supplier = new Supplier();
supplier.SupplierID = 21;
supplier.Email = "None";
And to set each property to undefined I would
supplier.clear();
Any ideas?
Thanks
try this: (plnkr)
function Supplier() {
var supplier = function() {};
supplier.prototype.clear = function() {
for (var key in this) {
if (!this.hasOwnProperty(key))
continue;
delete this[key];
}
};
return supplier;
}
hasOwnProperty return true if key is not in the prototype also prototype should be set outside of constructor, so your code should look like this:
function Supplier() { }
Supplier.prototype = {
clear: function () {
for (var key in this) {
if (this.hasOwnProperty(key)) {
console.log("key:" + key);
this[key] = undefined;
}
}
},
}
Don't set properties to undefined, just delete() them:
delete this[key];
And #jcubic is right, hasOwnProperty returns true if key is not in the prototype...

Creating a function with properties

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.

Underscorejs changes function to object

Edit: I realized I passed MyConstructorFunc.prototype to `_.extend().
I ran into an interesting implementation detail when I wanted to extend a function with Underscore.
I built a function constructor,
var MyConstructorFunc = function() {
...
}
then I returned the result of
return _.extend(MyConstructorFunc.prototype, {
\\ ...some properties...
}
What I got back was a typeof MyConstructorFunc == "object"! If _.extend is merging properties into a function why does it return an object?
Looking at the _.extend function I don't see where that happens...
_.extend = function(obj) {
if (!_.isObject(obj)) return obj;
var source, prop;
for (var i = 1, length = arguments.length; i < length; i++) {
source = arguments[i];
for (prop in source) {
if (hasOwnProperty.call(source, prop)) {
obj[prop] = source[prop];
}
}
}
return obj;
};
If I do MyConstructorFunc["someProp"] = someObject["someProp"] and return MyConstructorFunc, I returned a JavaScript object?
I'm missing something...
You are probably passing in a Function object to _.extend. Your sample code does not show it, but if you are making a new instance of your MyConstructorFunc using the "new" keyword, then the result will be an object.
var MyConstructorFunc = function() {
}
var foo = _.extend(MyConstructorFunc, {a:1});
console.log(typeof foo); // function
var funcObj = new MyConstructorFunc();
console.log(typeof funcObj); //object
Extending the MyConstructorFunc itself will return a function type. It's once you use the contructor to create a new function that you are given an object.

How do get the name of a calling function in Javascript?

Consider the following example.
var obj = function(){};
function apply(target, obj) {
if (target && obj && typeof obj == "object") {
for (var prop in obj) {
target[prop] = obj[prop];
}
}
return target;
}
apply(obj.prototype, {
firstFunction: function (){
this.secondFunction();
},
secondFunction: function (){
// how do I know what function called me here?
console.log("Callee Name: '" + arguments.callee.name + "'");
console.log("Caller Name: '" + arguments.callee.caller.name + "'");
}
});
var instance = new obj();
instance.firstFunction();
UPDATE
Both answers are really awesome. Thank you. I then looked into the problem of calling a recursive, or parent function within an object and found a solution here. This would allow me to retrieve the function name without using the arguments.callee/caller properties.
https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Operators/function
A function's name is an immutable property of that function, set in the initial function expression.
var notTheName = function thisIsTheName() { ... }
someObj.stillNotTheName = function stillTheName() { ... }
If your function expression does not have a name, there is (unsurprisingly) no way to identify it by name. Assigning a function to a variable does not give it a name; if that were the case, you could not determine the name of an expression assigned to multiple variables.
You should set firstFunction's name property by expressing it as
firstFunction: function firstFunction(){
this.secondFunction();
}
Also, arguments.callee is deprecated. See Why was the arguments.callee.caller property deprecated in JavaScript? for a very good explanation of the history of arguments.callee.
Give name to the functions
like:
var obj = function(){};
function apply(target, obj) {
if (target && obj && typeof obj == "object") {
for (var prop in obj) {
target[prop] = obj[prop];
}
}
return target;
}
apply(obj.prototype, {
firstFunction: function firstFunction(){
this.secondFunction();
},
secondFunction: function secondFunction(){
// how do I know what function called me here?
console.log("Callee Name: '" + arguments.callee.name + "'");
console.log("Caller Name: '" + arguments.callee.caller.name + "'");
}
});
var instance = new obj();
instance.firstFunction();
take a look on this question

JavaScript Hashtable / Dictionary

Consider the following article explaining hashtables / dictionaries in JavaScript:
Can anyone recommend a good Hashtable implementation in Javascript?
Given the accepted answer, I want to be able to do this:
var instance = new Dictionary();
instance['key1'] = 'Foo';
instance['key2'] = 'Bar';
instance['key3'] = 123;
instance['key4'] = true;
but I want the key/value pairs to point to an object within the Dictionary internally. consider the following code structure
var Dictionary = function() {
var dictionary; // <-- key value pairs should point to this, not to the Dictionary function;
this.setValue = function(key, value) {
dictionary[key] = value;
}
this.getValue = function() {
return dictionary[key];
}
}
Is this possible?
EDIT:
One way I thought of designing the Dictionary object was like so:
var Dictionary = function() {
this.setValue = function(key, value) {
this[key] = value;
}
this.getValue = function(key) {
return this[key];
}
}
The problems with this are:
I can assign like so instance['key1'] = 'foo'; and read like this instance.key1; I don't want this!!
I can assign this instance['getValue'] = null; and then cannot get a value back because the function is now null!!
Neither of the above should occurr, hence the reason that the set and get functionality should apply to the internal object, not to the dictionary itself.
function Dictionary()
{
this.store = {};
this.setValue = function(key, value) {
store[key] = value;
}
this.getValue = function(key)
{
return store[key];
}
return this;
}
//Testing
var dict = Dictionary();
dict.setValue('key','value');
alert(dict.getValue('key'));//displays "value"
alert(dict.getValue('unassignedKey'));//displays "undefined"
alert(dict['key']);//displays "undefined" (an unfortunate lack of syntactic convenience, we have to go through getValue).
alert(dict.key);//displays "undefined"
var dict2 = Dictionary();
dict2.setValue('key2', 'value2');
alert(dict2.getValue('key'));//displays "undefined"
alert(dict2.getValue('key2'));//displays "value2"

Categories