Getting the property key from within a property's value - javascript

Given the following javascript object:
var commands = {
back:{
command: "b",
aliases: ["back","go back","backwards"],
action: function(){
return this.key; //I want this to return "back" (the prop name)
},
desc: "goes back"
}
}
How can i access the Property Name which is "back" from within the action()?
I think it should be pretty simple, but if it isn't something simple than I'll add more details.
NOTE: aliases[0] is holding the name by chance, and it is not promised to hold it in the future or in other commands.
EDIT:
Sometimes we get to complicated while we can solve the problem pretty fast.
In this case i can just go ahead and return the string "back"
I'll leave the question and accept the answer that solves my question if there is such a solution.

Returning the string as you mentioned is definitely the easiest way. But I could see cases where someone might want to be able to get similar functionality with a dynamically created object in which the keys are not known until run-time.
A solution that would work in that case is exposing the commands object to the sub objects, so they can look themselves up:
var commands = {
back:{
command: "b",
aliases: ["back","go back","backwards"],
action: function(){
var commandKeys = Object.keys(commands);
for(var i=0; i < commandKeys.length; i++){
if(commands[commandKeys[i]] === this){
return commandKeys[i];
}
}
},
desc: "goes back"
}
};
In this case it may also make more sense to share the function across all those action objects:
var commands = {
back:{
command: "b",
aliases: ["back","go back","backwards"],
action: getAction,
desc: "goes back"
},
forward: {
//...
action: getAction,
//...
}
};
function getAction() {
var commandKeys = Object.keys(commands);
for(var i=0; i < commandKeys.length; i++){
if(commands[commandKeys[i]] === this){
return commandKeys[i];
}
}
}
Unless you need to perform some specific logic for each sub object.
EDIT: To improve efficiency, we can make it where the getAction function is not executed every call and add a property that will store the name. That way the lookup only occurs the first time.
var commands = {
back:{
command: "b",
aliases: ["back","go back","backwards"],
action: getAction,
desc: "goes back"
},
forward: {
//...
action: getAction,
//...
}
};
// Only needs to getKey the first time called.
function getAction() {
if(!this.key) this.key = getKey(this);
return this.key;
}
function getKey(obj) {
var commandKeys = Object.keys(commands);
for(var i=0; i < commandKeys.length; i++){
if(commands[commandKeys[i]] === obj){
return commandKeys[i];
}
}
}

When you call action as the following:
commands.back.action();
the scope of action is back. Sadly, the creation of the object that gets assigned to commands.back does not know that this inside of action is called "back". From my understanding, this is done because we could assign the object assigned to commands.back to another object with another name. As in:
var foo = { f: function(){console.log(this) } };
var bar = foo;
bar.f();
Or closer to what you have...
var foo = {
bar: {
f:function(){console.log(this)}
}
};
var other = { another: (foo.bar) };
The only way I know of where the object knows the name of what it was created within are functions. So, we can create a temp function that has the name back that will create an object as desired.
var commands = {
back:(new function back(){
// I prefer to assign to a variable to assist with the readability as to what "this" is:)
var self = this;
self.command = "b";
self.aliases = ["back","go back","backwards"];
self.action = function(){
// Can leave as "this" or change to "self".
return this.key;
};
self.desc = "goes back";
self.key = self.prototype.constructor.name;
})
}
Simplest Solution
But at that point might as well just add a property that already has the name. I would recommend doing a property called key or name rather than placing the name directly into the action function to make it easier to have multiple places where the name is used. Also, allows there to be a single place to change the name within the object if need be.
var commands = {
back:{
command: "b",
aliases: ["back","go back","backwards"],
action: function(){
return this.key;
},
desc: "goes back",
key: "back"
}
}
EDIT: Added this edit as another way to do this, but I would still do the previous way. We can utilize Object.keys to get the name of the property since back is being added as an enumerable property of commands.
var i = 0,
commands = { back: {
key: (function(id){return function(){return Object.keys(commands)[id]}})(i++)
}}
Then can get the key by the following:
commands.back.key();
Or within the action function as:
this.key();
Can add key to back as a get which would look like:
var i = 0,
commands = { back: {
id: (i++),
get key() {return Object.keys(commands)[this.id]}
}}
This will allow you to access the property as commands.back.key and within the action function as this.key.
Can also pre-define everything then can do the following:
var i = 0, commands = { back: undefined };
commands.back = { key: Object.keys(commands)[i++] };

You can add and also advisable to add a toString method for your every object like this.
var commands = {
back:{
command: "b",
name : "back",
aliases: ["back","go back","backwards"],
action: function(){
return this.toString();
},
desc: "goes back",
toString : function(){
return this.name;
}
}
}
console.log(commands.back.action()); // back
console.log(commands.back.toString()); // back

What you are having here, is a nested object, held on the property of an object.
You can not get that property by hand - unless you are doing some strange metaprogramming stuff, such as getting the AST parent node and trying to determine the property the object is held etc. The easiest way, is to hold the property name using a string i.e.: "back".
In simple terms, it is like holding the object to a var
var obj = {/*....*/};
And you are trying to get the var name from within the object.
Remember though that in JavaScript, you can access an object property, using both string and index notation, so commands.back can also be called using commands['back']. If I am guessing right, you are trying to make a sort of dispatching, so this notation can be useful for you.

If you've got that object (literal object) you can't use this keyword. You have two solutions:
return commands.back.aliases[0]
Or otherwise,you can construct the object as a prototype object and not literal object:
var commands = function() {
this.back = function() {
this.command = "b";
this.aliases = ["back","go back","backwards"];
this.action = function() {
return this.aliases[0];
};
this.desc = "goes back";
};
};
And initialize like this
var instance = new commands();
instance.action(); // it returns "back" string

Related

How do I assign argument properties to self?

Aim
I am aiming to emulate the Mongoose model "class" using an in-memory store. Here is an example of what that might look like:
var Book = require("./book");
var book = new Book({
title: "Hello"
});
Now, when I pass book to, for example, console.log the following output is returned:
console.log(book); // returns { title: "Hello" }
Problem
I made a function called MyBook that emulates the Mongoose model "class":
function MyBook(doc) {
this.doc = doc;
}
var book = new MyBook({title: "Hello"});
But when I pass book to console.log, the output is different:
console.log(book); // returns { doc: { title: "Hello" } }
This makes sense to me. I am assigning to doc so it makes sense that I have a property doc. This is not what I want, though. What I want is an output like the one Mongoose returns. I assign to doc because, when I assign to this:
function MyBook(doc) {
this = doc;
}
I get this error:
ReferenceError: Invalid left-hand side in assignment
Again, this makes sense to me. But the question remains: How do I (dynamically) assign properties of the given argument to the current object?
You can iterate over all the properties of doc with a for...in loop:
function MyBook(doc) {
for (var property in doc) {
if (doc.hasOwnProperty(property)) {
this[property] = doc[property];
}
}
}
var book = new MyBook({title: "Hello"});
Soon you'll be able to just do Object.assign(this, doc).
You can use extend function from util module to merge the passed arguments with the self this object
var extend = require('util')._extend
;
var MyBook = function(options) {
extend(this, options);
};
You could use JavaScripts arguments object. https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Functions/arguments
function MyBook() {
this.title = arguments[0];
this.other = arguments[1]
}
var book = new MyBook("Hello", "Other");
console.log(book); // returns - MyBook {title: "Hello", other: "Other"}
Though doing it this way you need to set up the properties you want on MyBook originally. This doesnt really match the "dynamic" element you were looking for but does match your aim, the idea of a "class"

Create JavaScript native objects dynamically

Quite a long question.But it basically describe pretty much describe what i want.This code here for creating any object according to user input to a input text field.If i want to create Number,String or Object, i just have to write Number/String/Object in the text field.
a button has been introduced to call createObj.getObjName and get input from the text field.It tries to match the input for any three type of object which are Number/String/Object.Then it calls a bool function [problem lies here i think] which iterate over **list_keys array** using Array.prototype.some which is created using a json object that holds different object name.They are assigned with objects created using new keyword.
problem is to call check function i tried to forced the THIS keyword to indicate createObj object inside it instead of window object.I tried to console.log(this) it gives me this output which is the input html button element.
<input type='button' id='btn' value="create">
But i want THIS to refer to the createObj itself.Why it is referring to HTML element ??How can i solve this?
Full Code:
(function() {
var list = {
"Number": new Number(),
"String": new String(),
"Object": new Object(),
"Array": new Array()
}
var list_keys = Object.keys(list);
var createObj = {
re: null,
text: null,
match: null,
newObj: null,
getObjName: function() {
this.re = /Number|Object|String/;
this.text = document.getElementById('text').value;
this.match = this.text.match(this.re);
var bool = check.call(this);
if (bool) {
this.makeObj(list.this.match[0]);
}
},
makeObj: function(obj) {
this.newObj = obj;
}
};
function check() {
console.log(this);
return list_keys.some(function(el, indx, arr) {
return this.match[0] === el;
});
}
document.getElementById('btn').addEventListener('click', createObj.getObjName);
})();
You can just bind the object, like this
createObj.getObjName.bind(createObj)
This will return a new function, with this referring createObj inside getObjName.
Also, what if there is no match at all?
return this.match[0] === el;
this will fail at run time, since this.match will be null. So you might want to do something like this
return this.match && list_keys.some(...);
If I were to write the same code, in a better way, I would do something like this
(function() {
var MyObject = {
newObject: null,
createObject: function() {
var text = document.getElementById('text').value;
if (window.hasOwnProperty(text)) {
this.newObject = new window[text];
}
}
}
document.getElementById('btn').addEventListener('click',
MyObject.createObject.bind(MyObject));
})();
when you bind a function to an event, this refers to the html node the event was bound to. You can get around this in a variety of ways. The first that comes to mind is referencing createObj directly:
getObjName: function() {
createObj.re = /Number|Object|String/;
createObj.text = document.getElementById('text').value;
createObj.match = this.text.match(createObj.re);
var bool = check.call(createObj);
if (bool) {
this.makeObj(list.createObj.match[0]);
}
},
this is less than ideal, because it references the object by name, which means if you change the object's name, you'll have to change all references to it. It also presents a problem if you (or another developer working with your code) defines a new createObj down the line. Since it is referencing the object by name it would start using the newly declared object instead of yours. An improvement would be to create an alias for the object (typically called that):
getObjName: function() {
that.re = /Number|Object|String/;
that.text = document.getElementById('text').value;
that.match = this.text.match(that.re);
var bool = check.call(that);
if (bool) {
this.makeObj(list.that.match[0]);
}
},
...
var that = createObj
the problem with this is that that is usually meant to reference this in a scope where the context is lost, not an arbitrary object (in this case createObj).
Furthermore, I'm not sure that function belongs as a method of the createObj, or at least to the struct containing your data. Separation of concerns is important, and while
var createObj = {
re: null,
text: null,
match: null,
newObj: null,
is concerned with the data you're manipulating, getObjName and makeObj are concerned with event handling and fabricating an object using the collected data. I'd extract a struct out to hold the data, which I'd then use in my other objects:
var descriptors = {
re: null,
text: null,
match: null,
newObj: null
}
var getObjName = function() {
descriptors.re = /Number|Object|String/;
descriptors.text = document.getElementById('text').value;
descriptors.match = descriptors.text.match(descriptors.re);
var bool = check.call(descriptors);
if (bool) {
makeObj(list.descriptors.match[0]);
}
}
var makeObj = function(obj) {
this.newObj = obj;
}
function check() {
console.log(this);
return list_keys.some(function(el, indx, arr) {
return this.match[0] === el;
});
}
document.getElementById('btn').addEventListener('click', getObjName);
this separates struct from functionality, and better conveys the intent of the parts (descriptors holds all data, getObjName handles the event, and makeObj instantiates the new object).
there's still one issue with this though, from a design perspective, getObjName violates the Single Responsibility Principle. It is tasked with handling an event and getting the object's name. I'd refactor the event handling portion out to stay true to getObjName's intent:
var getObjName = function(descriptors) {
descriptors.re = /Number|Object|String/;
descriptors.text = document.getElementById('text').value;
descriptors.match = this.text.match(descriptors.re);
return check.call(descriptors);
}
document.getElementById('btn').addEventListener('click', function() {
if (getObjName(descriptors)) {
makeObj(list.descriptors.match[0]);
}
});

How do I create an unitialized object in javascript?

I'm working on a wizard that uses javascript to change the page in an iframe. I'd like to create an object for each page of the wizard with references to a next & previous page.
Edit: The code posted below does not work. actionOne.nextAction is equal to {} after execution.
var actionOne = {};
var actionTwo = {};
actionOne = {
url: 'actionOneUrl.htm',
prevAction: null,
nextAction: actionTwo,
doDisplay: function(){
$('.label').html('Action One');
}
}
actionTwo = {
url: 'actionTwoUrl.htm',
prevAction: actionOne,
nextAction: null,
doDisplay: function(){
$('.label').html('Action Two');
}
}
The problem is that I can't figure out how to properly set up the next and previous references. There is likely a relatively simple solution, but I'm not sure what to search for. I am able to set the references after creating all the pages, but it feels very clunky to do so. Is there a way to do it while creating the objects?
For what you're trying to do, you're going to need to use an Object Oriented approach in JavaScript. This will allow you to assign a reference to new instances of your object. For example this works:
http://jsfiddle.net/Gq7vQ/
function Action(url, name){
this.url = url;
this.prevAction = null;
this.nextAction = null;
this.name = name;
}
Action.prototype.doDisplay = function(){
$(".label").html(this.name);
}
var actionOne = new Action('actionOneUrl.html', 'Action One');
var actionTwo = new Action('actionTwoUrl.html', 'Action Two');
actionOne.nextAction = actionTwo;
actionTwo.prevAction = actionOne;
console.log(actionOne.nextAction);
EDIT: So the OP asked for an implementation that automatically sets up these links between newly added actions. So here is a doubly-linked list implementation:
http://jsfiddle.net/wXC9B/1/
function ActionList(){
this.head = null;
this.tail = null;
}
ActionList.prototype.doDisplay = function(index){
var node = this.getNode(index);
console.log(node.name);
}
ActionList.prototype.getNode = function(index){
var current = this.head,
c = 0;
while(c < index && current !== null){
current = current.nextAction;
c++;
}
return current;
}
ActionList.prototype.add = function(url, name){
var node = {
url: url,
name: name,
nextAction: null,
prevAction: null
};
if(this.head === null){
this.head = node;
this.tail = node;
}
else{
this.tail.nextAction = node;
node.prevAction = this.tail;
//move tail to new node
this.tail = node;
}
}
var actionList = new ActionList();
//Each add automatically sets up links between the two
actionList.add('actionOneUrl.html', 'Action One');
actionList.add('actionTwoUrl.html', 'Action Two');
console.log(actionList.getNode(1));
actionList.doDisplay(1);
This is a very simplified example, but something like the following structure would prevent the need to manually reference your next/prev actions...let the application logic go find what to do based on the user's inputs.
UnderscoreJS's where function http://underscorejs.org/#where would be useful here
var dataFromServer = [
{id:"1", name: "First Page", nextId:"2"},
{id:"2", name: "Second Page", nextId:"3", prevId: "1"},
.....];
var actions = [];
var Action = function(data) {
this.doNextURL = function() {
//find action with id= data.nextId;
var actionToDo = _.where(actions, {id: data.nextId})[0];
window.location.href = actionToDo.url; //or something... a callback parameter, or returning the action rather than doing the 'ui logic' here would be better real world
}
}
for(var i = 0; i < dataFromServer.length; i+=1){
actions.push(new Action(dataFromServer[i]));
}
When you do
actionTwo = {
// ...
}
you are assigning a new value to actionTwo. It does not refer to the object anymore you assigned in var actionTwo = {}; and hence does not refer to the object you used in
actionOne = {
// ...
nextAction: actionTwo,
// ...
}
The easiest way would be to just initialise both objects and then assign them to the correct properties later on:
var actionOne = {
url: 'actionOneUrl.htm',
prevAction: null,
nextAction: null,
doDisplay: function(){
$('.label').html('Action One');
}
};
var actionTwo = {
url: 'actionTwoUrl.htm',
prevAction: null,
nextAction: null,
doDisplay: function(){
$('.label').html('Action Two');
}
};
actionOne.nextAction = actionTwo;
actionTwo.prevAction = actionOne;
If you want to do this for multiple actions, you should consider using constructor functions, so as joeltine shows in his answer.
To learn more about objects, have a look at MDN - Working with Objects.
When you use the {} object literal to define an object you are creating a new object instance with the Object constructor.
The following creates two new object instances from the Object constructor:
var actionOne = {}; // object instance 1
var actionTwo = {}; // object instance 2
This next part creates another new object instance (the third object instance) from the Object constructor and adds several properties. actionOne.nextAction points to the object instance of actionTwo (which doesn't have any of its own properties).
actionOne = {
url: 'actionOneUrl.htm',
prevAction: null,
nextAction: actionTwo,
doDisplay: function(){
$('.label').html('Action One');
}
} // object instance 3
So now when you declare actionTwo = {....} it creates a fourth object instance with a bunch of new properties. actionOne.prevAction still points to the second object instance you created (but are are no longer referencing with the the global variable actionTwo).
The key to remember is that the object literal {} creates new object instances with the Object constructor and the properties you create reference the object instance at the time they are declared.
Try this: don't create NEW objects for actionOne, actionTwo, instead leave your code as is - but assign to object properties of the already existing objects (which the first two lines create).
var actionOne, actionTwo;
actionOne = {
url: 'actionOneUrl.htm',
doDisplay: function(){
$('.label').html('Action One');
}
};
actionTwo = {
url: 'actionTwoUrl.htm',
doDisplay: function(){
$('.label').html('Action Two');
}
};
actionOne.prevAction = null; //could also be set above
actionOne.nextAction = actionTwo;
actionTwo.prevAction = actionOne;
actionTwo.nextAction = null; //could also be set above
Your question was a very good one - don't let anyone tell otherwise :) It is NOT obvious, even with quite a bit of JS background, that the object properties point to the objects the variables pointed to at the time the (literal) object creation statement was executed, rather than to the variable itself (in which case your example would have worked).
And please ignore the MVC pattern thing, even if it was even upvoted. Nothing wrong with MVC (sometimes), but this is a much, much MUCH more basic Javascript question, those pattern things come into play on a whole different (higher) level than your little interesting issue.
Some background: Deep inside the bowels of the Javascript execution engine variables that have an object as value are pointers (C/C++ background knowledge is good for understanding Javascript, because JS engines are written in it). So, when you assign the value of such a variable to an object property it will not point to the variable, but instead it will receive the pointer the variable has at value at the time. This means if the variable gets a new object assigned, pointing to another place in memory, the object property keeps pointing to the old object. If it pointed to the variable instead it would there find a pointer to the new object. As you can see, answering your question leads us deep inside how Javascript engines actually work on a very low level :)
All the other answers sure also solve your immediate issue, but I believe knowing this bit of background is much more fertile, in the end. Instead of trying to just give an answer that works it's sometimes worth investigating what's really going on... :)
Primitive types are stored in the variable directly, variables for objects are actually pointers. new String("foo") is an object (String), "foo" is a primitive type (string).
The exact same issue is important to keep in mind when calling functions in Javascript! It is call by value always, technically - but when the variable is a pointer to an object the value IS the pointer, which one must consider when assigning to variables the function gets as parameter.
Everyone seems to really be overcomplicating this.
function Wizard(o) {
return { url:o.url, doDisplay:function() { $('.label').html(o.html); } };
}
var wizards = [{url: 'actionOneUrl.html', html:'Action One'},
{url: 'actionTwoUrl.html', html:'Action Two'}].map(Wizard);
// wizards now contains an array of all your wizard objects
wizards.reduce(function(p,c) { c.prevAction = p; return p.nextAction = c; });
// prevAction and nextAction now point to the right places
No you can't, but you can keep the empty objects and just fill them:
var actionOne = {};
var actionTwo = {};
actionOne.url = 'actionOneUrl.htm';
actionOne.prevAction = null;
actionOne.nextAction = actionTwo;
...
But that's rather ugly. I would recommend filling in the links between them by using a function like this:
function chain() {
var i, prev, curr;
for(i = 0; i < arguments.length; i++) {
curr = arguments[i];
if(prev) {
prev.nextAction = curr;
curr.prevAction = prev;
}
else {
curr.prevAction = null;
}
prev = curr;
}
if(curr) curr.nextAction = null;
}
var actionOne, actionTwo;
actionOne = {
url: 'actionOneUrl.htm',
doDisplay: function(){
$('.label').html('Action One');
}
}
actionTwo = {
url: 'actionTwoUrl.htm',
doDisplay: function(){
$('.label').html('Action Two');
}
}
chain(actionOne, actionTwo);

Create a new unique global variable each time a function is run in javascript [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Javascript dynamic variable name
A very basic question. I want to create a new javascript global variable each time a function is called. The variable should contain the id of the element so that I can easily access it later.
id = 2347
//this function would be called multiple times, hopefully generating a new global each time
function (id)
{
var + id = something
// I want a variable that would be named var2347 that equals something, but the above line doesn't get it.
}
In a later function, I want to access the variable like so:
function two (id)
{
alert(var + id);
}
I'm sure I'm going to have a "doh!" moment when someone is kind enough to answer this.
How about...
var store = (function() {
var map = {};
return {
set: function ( name, value ) {
map[ name ] = value;
},
get: function ( name ) {
return map[ name ];
}
};
})();
Usage:
store.set( 123, 'some value' );
and then...
store.get( 123 ) // 'some value'
store.get( 456 ) // undefined
Live demo: http://jsfiddle.net/jZfft/
Programmers are highly advised to not declare global variables, since the browsers already ship with several hundreds of names in the global namespace. Using the global namespace for your own variables can lead to name-collisions which can then break the program or some of the browser's functionality. Creating new namespaces is free, so don't be shy to do it...
Global variables are properties of the window object, so window.lol and window['lol'] define a global variable lol which can be accessed in any of these ways.
The second, window['lol'], can also be used with variable names, like this:
var lol = 123;
var name = 'lol';
var content = window[name]; // window['lol'] == 123
content will now contain 123.
Pretty much anything can be put between square brackets [], so you can also do this:
var id = 123;
window['prefix' + id] = 'text';
var content = window['prefix' + id]; // prefix123 == text
Or, in your case:
var id = 2347;
function one(id) {
window['var' + id] = something;
}
function two(id) {
alert(window['var' + id]);
}
You can save your values to the global hash:
var g = {};
function (id)
{
g[id] = something;
}
function two (id)
{
alert(g[id]);
}
I would argue that you don't really want to be making lots of global variables. Rather, you can just make one global object or array and attach all your other variables to that. In this case, you probably want an object:
var myIds = {};
function makeSomething(id) {
// create something that goes with this id
myIds[id] = something;
}
Then, to fetch that information at some time later, you can retrieve it with this:
var something = myIds[id];
The reason for this suggestion is many-fold. First off, you want to minimize the number of global variables because every global is a chance for a naming collision with some other script you might be using. Second off, when keeping track of a bunch of related data, it's a better programming practice to keep it in one specific data structure rather than just throw it all in the giant global bin with all other data.
It's even possible to create an object that manages all this for you:
function idFactory() {
this.ids = {};
}
idFactory.prototype = {
makeSomething: function(id) {
// create something that goes with this id
this.ids[id] = something;
},
retrieveSomething: function(id) {
return(this.ids[id]);
},
clear: function() {
this.ids = {};
}
};
// then you would use it like this:
var myIds = new idFactory();
myIds.makeSomething(2347);
var value = myIds.retrieveSomething(2347);

Can I store JavaScript functions in arrays?

How can I store functions in an array with named properties, so I can call like
FunctionArray["DoThis"]
or even
FunctionArray[integer]
?
Note: I do not wish to use eval.
The important thing to remember is that functions are first class objects in JavaScript. So you can pass them around as parameters, use them as object values and so on. Value(s) in an array are just one example of that.
Note that we are not storing the functions in an array although we can do that and access them with a numeric index. We are storing them in a regular object keyed by the name we want to access that function with.
var functions = {
blah: function() { alert("blah"); },
foo: function() { console.log("foo"); }
};
call as
functions.blah();
or
functions["blah"]();
You want an object literal, not an array.
x = { 'dothis': function() { alert('hi'); } };
Object
x['dothis']()
You can also dynamically invoke
y = 'dothis';
x[y]()
Static/hard coded invocation:
x.dothis()
If you do want an array though:
x = [function(){alert('hi');}][0]()
You can actually do that. Just declare it outside the array, like so...
const your_function = function(){ console.log("I am your function") }
const group = [0, "lizard", false, your_function()]
group[3]
You may also change where it's called, if you want to...
const your_function = function(){ console.log("I am your function") }
const group = [0, "lizard", false, your_function]
group[3]()
Functions were named wrong :/ sry
You can store things directly in an array, but as an object, for example:
var Functions = { DoThis: function() { alert("do this"); } };
Functions['DoThis'](); //alerts "do this"
Functions.DoThis() //alerts "do this"
You can give it a try here.
You can access an object's properties through its name (x["A"]). If you want to assign indexes (0 = "A") you have to do this, and here is an example. (I'm not sure if the for loop will work on any browser; I've tested on Firefox, but you can get the idea.)
var x = {};
x.A = function() { alert("func 1"); };
x.B = function() { alert("func 2"); };
var i = 0;
for (a in x)
{
x[i] = x[a];
++i;
}
x[0](); // func 1
x[1](); // func 2
x["A"](); // func 1
x["B"](); // func 2
You even can use a function as the name of the property:
var func = function(a, b){alert(a+b)};
var obj = {};
obj[func] = 2;
Here is an array that contains various data types, including a function.
Although there is an object in this example, the function is not within the object.
If you replace this object with a string, the function will still work as planned.
I can call the function from within or without the array.
myArray = [
1,
true,
"String",
{
name: "trey",
age: 43,
},
[1,2,3,4],
myFunction = function(){
console.log("What\'s up!");
},
myArray[5](),
];
console.log(myArray);
myArray[5]();
Here is the output:
What's up!
[ 1, true, 'String', { name: 'trey', age: 43 }, [ 1, 2, 3, 4 ], [Function], undefined ]
What's up!
Basically, a function is a special type of object in JavaScript. And in JavaScript, in array you can store anything (not necessarily of the same type). So going by this, yes!, you can store a function, object, and primitive values in an array in JavaScript:
var arr = ["Hello", true, false, 1, {name: "Arshad"}, function(){}]
And you can mix the object and function to make the named function like:
{ callBythisname: function(){ .... }}
You can store this object in an array as well:
var arr = [{ callBythisname: function(){ .... }}];
If you want to call it, call like:
arr[0].callBythisname();
The answer is has a simple answer, but it doesn't to be simplified by the answers in this thread. The simple answer is yes you can place function in an array. In fact, can declare variables and reference them in your function.
Example:
let a = 1;
let b = 2;
let arr = [
a,
b,
function () {
return a + b;
},
];
console.log(arr[2]()); // return 3
console.log(typeof arr); // returns object

Categories

Resources