Call each function in a literal object (Javascript) - javascript

How can I call each function in this object?
var obj = {
hey1: function() {
alert('hey');
},
hey2: function() {
alert('hey2');
},
hey3: function() {
alert('hey3');
}
}
I'd like each function to run one after the other. I'm looking for something like:
for (var hey in obj) {
hey();
}
But obviously that doesn't run (otherwise I wouldn't be asking this question).
Thanks guys!!!

for (var hey in obj) {
obj[hey]();
}
In a situation where it is not guaranteed that each property will be a function, you can weed out other properties:
for (var hey in obj) {
if (typeof obj[hey] == "function") {
obj[hey]();
}
}
To further restrict it to only immediate properties of the object (and not the ones inherited from its prototype):
for (var hey in obj) {
if (typeof obj[hey] == "function" && obj.hasOwnProperty(hey)) {
obj[hey]();
}
}

Lopping will give you they keys, not the values. Use the key to get the value:
for (var hey in obj) {
obj[hey]();
}
jsfiddle.net/s8tbr/
Note: Depending on from where you get the object, you might want to check that the properties are members of the object itself, not inherited from a prototype:
for (var hey in obj) {
if (obj.hasOwnProperty(hey)) {
obj[hey]();
}
}

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...

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.

Automatically wrapping dynamically added object properties (functions) in a wrapper function

I use this setup to add properties to an object:
var obj = {
extend: function(key, obj){
this[key] = obj;
}
}
This works well. However, in some cases i want to add sub-objects as properties:
obj.extend('new', {
test: function(){
console.log('test called');
}
});
I would like to automatically wrap all functions occurring in the object passed (as second parameter) to obj.extend() in a function which in itself wraps the actual call of the function in $(document).ready(function(){})
My approach was this:
extend: function(key, obj){
for(var prop in obj){
if(typeof prop == 'function') {
console.log(prop + ' is a function'
} else
console.log(prop + ' is NOT a function');
}
}
this[key] = obj;
}
But typeof prop seems to return string and not 'function'. I have checked a variety of articles and posts but the approach:
typeof propertyOfObject == 'function'
seems totally valid.
What am i doing wrong here? Why does typeof propertyOfObject give me 'string'? How can i check if prop is a function?
Because you're just iterating over the Object keys, not its properties.
You need to fully qualify the property to access it:
if( typeof obj[ prop ] === 'function' ) { }

Affecting Object's Properties Inside Callbacks in Node.js

I'm in the process of writing a simple prototype in Node.js with some helper methods that I'll probably need in objects using that prototype. One method that I'd like to have is an implementation of jQuery's .each(). I've looked at jQuery's implementation in their development release, and tried to emulate it in my simplified version here.
// Loop through the object using a callback
BaseProto.prototype.each = function (cb, args) {
var obj = this.get(), // Get our object as a plain object
prop;
/** Code to make sure the the args passed are actually an array **/
if (typeof cb === "function") {
// For each property in our object
for (prop in obj) {
// Apply the callback to the object's property and pass
// the index, the property, and whatever else as arguments
if (cb.apply(obj[prop], [ prop, obj[prop] ].concat(args)) === false) {
// Get out if the function returns false
break;
}
}
}
// Reset our object with the new one
return this.reset(obj);
};
The problem is that while the callback is definitely being fired, it doesn't have any effect on the object's property. No matter what I do inside the callback, the changes stay inside the callback's scope.
Here is an example of a simple callback that I've been testing with.
var BaseProtoTestObj = new BaseProto();
/** Set some properties to BaseProtoTestObj **/
function cb1 ( key, val ) {
var prop;
key = key.toString() + " Callbacked";
val = val.toString() + " Callbacked";
for (prop in this) {
this[prop] = this[prop].toString() + " Callbacked";
}
}
// Doesn't have any effect on BaseProtoTestObj
BaseProtoTestObj.each(cb1);
I can see that there is a lot more going on in jQuery's .each(), but from what I can gather it's for optimization and the ability to iterate over arrays as well as objects.
In the end, my question is simple. What is it that jQuery is doing to affect the properties, that I'm not in my .each()?
Edit
I suppose another question to ask would be if my logic is fundamentally wrong, and you can't modify an object's properties this way.
You don't need a custom method:
for(var prop in object) {
var value = object[prop];
// do something with value and/or prop
}
Although if you really needed .each(), you could do something like this:
Object.prototype.each = function(cb) {
for(var propName in this) {
cb(propName, this[propName]);
}
}
var foo = { prop: 'value', prop2: 'value2' };
foo.each(function(key,value) {
// do something here
});
Since you need to modify the actual values of the properties, try this:
Object.prototype.mutate = function(cb) {
for(var propName in this) {
this[propName] = cb(propName, this[propName]);
}
}
var obj = {
a: 'foo',
b: 'bar',
c: 'baz'
};
obj.mutate(function(propName, propValue) {
return propName + '-' + propValue;
});
/*
obj will now be:
var obj = {
a: 'a-foo',
b: 'b-bar',
c: 'c-baz'
};
*/

In Javascript, if there is an object with a lot of properties that are functions, how do you convert them to array of strings (of the function names)?

In Javascript, if an object has lots of properties that are functions:
var obj = { foo: function() { ... },
bar: function() { ... },
...
}
then how can you get an array of names of those functions? That is, an array
["foo", "bar", ... ]
thanks.
var names = [];
for( var k in obj ) {
if(obj.hasOwnProperty(k) && typeof obj[k] == 'function') {
names.push(k);
}
}
var functions = [];
for (var prop in obj) {
if ((typeof obj[prop]) == 'function') {
// it's a function
functions.push(prop);
}
}
Edit: I've slightly misread the question, you want to extract the names of only the properties that are function objects:
function methods(obj) {
var result = [];
for (var prop in obj) {
if (obj.hasOwnProperty(prop) && typeof obj[prop] == 'function') {
result.push(prop);
}
}
return result;
}
var obj = {
foo: function() { },
bar: function() { },
};
methods(obj); // ["foo", "bar"]
I'm using the hasOwnProperty method, to ensure that the enumerated properties in fact exist physically in the object.
Note that this approach and all other answers have a small problem IE.
The JScript's DontEnum Bug, custom properties that shadow non-enumerable properties (DontEnum) higher in the prototype chain, are not enumerated using the for-in statement, for example :
var foo = {
constructor : function() { return 0; },
toString : function() { return "1"; },
valueOf : function() { return 2; }
toLocaleString : function() { return "3"; }
};
for (var propName in foo ) { alert(propName); }
The object foo clearly has defined four own properties, but those properties exist in Object.prototype marked as DontEnum, if you try to enumerate the properties of that object with the for-in statement in IE, it won't find any.
This bug is present on all IE versions, and has been recently fixed in IE9 Platform Preview.
To complete other answers: you can also use instanceof:
var obj = { foo: function() { ... },
bar: function() { ... },
...
},
fnArr = [];
for (var label in obj){
if (obj[label] instanceof Function){
fnArr.push(label)
}
}
With ES5:
var obj = {
foo: function() {},
bar: function() {},
baz: true
};
function getMethods(object) {
return Object.keys(object).filter(function(key) {
return typeof object[key] == 'function';
});
}
getMethods(obj); // [foo, bar]
Object.keys(<object>) returns the names of all enumerable properties of an object as an array, of which the non-functions are filtered out.
Example - works on Chrome release and nightly builds of Webkit and Tracemonkey (Firefox).

Categories