Javascript: Use function as variable - javascript

Is there a way to use a variable name which has a function assigned to it, for example, to get the actual width of an element?
var xvar = function(){ return $('#y').width()}
And use it as
console.log(xvar);
Instead of
console.log(xvar());

Not with variables, but it is possible with properties on objects. It's called a getter.
var obj = {
get xvar() { return $('#y').width(); }
};
Then you can use:
obj.xvar; // will run the above function
(Theoretically, a way to use a variable getter is when an object's properties reflect the variables. For example, the window object.)

As long as your function returns String or Number this could be an alternative for non-ES5 environments:
var xvar = new function(id){
this.toString =
this.valueOf = function(){
return $(id).width()};
}('#y');

If I not mistake it will work because xvar will store reference to result of immediately-invoked function:
var xvar = (function() { return $('#y').width(); })();
console.log(xvar);
But after it you can't use xvar() version.

Related

Possible to modify but not replace a method's prototype?

Let's say I have a method Object.getNumber() and I want to make a small change to the results of that method, for example add 1 to the result, and no I can't access that method's code.
Any way to do this with its prototype? I would need to access the method within the defineProperty call I suppose.
Object.defineProperty(Object.prototype, 'getNumber',{ get: function () { ... } });
You can always replace the original method in the prototype, but keep the original somewhere in the local variable. Something like this:
Object.prototype.getNumber = (function() {
let originalFn = Object.prototype.getNumber;
return function() {
let originalResult = originalFn.apply(this, arguments);
return originalResult + 1;
};
})();
A method is just a function that you can pass around so you can simply apply that function after another:
const getNumber = Object.prototype.getNumber;
Object.prototype.getNumber = function() {
const result = getNumber();
return result + 1;
};
But modifying a native prototype is not good practice, especially Object.prototype as that affects too many things.

Is it possible to use a constructor in a Javascript object literal to avoid instantiation?

I have an object that needs certain properties to be set by execution instead of assignment. Is it possible to do this using a literal object notation?
I would like to be able to access the object's properties using this:
myObject.propertyName
...rather than this:
objInstance = new myObject();
objInstance.propertyName;
EDIT: to clarify, based on Bergi's answer, this is what I'm aiming to do:
var myObj = {
myInfo: (function() { return myObj.getInfo('myInfo'); })(),
getInfo: function() {
/* lots of execution here that would be redundant if done within myInfo */
}
}
// access the calculated property value
myObj.myInfo;
But this gives me the error myObj is not defined
I guess what you want is an IEFE, which you can put inside an object literal:
var myObject = {
propertyName: (function() {
var it = 5*3; // compute something and
return it;
}()),
anotherFunction: function() {…}
};
myObject.propertyName // 15
Maybe you also want to use the module pattern. Have a look at Simplest/Cleanest way to implement singleton in JavaScript?.
Thanks to Bergi to finding this, here is a final example what I wanted to do:
myObj = {
init: function() {
this.oneProperty = anyCodeIWant...
this.anotherProperty = moreCodeIWant...
// and so on
return this;
}
}.init();
myObj.oneProperty;
myObj.anotherProperty;
// and so on

Declare variable name dynamically in javascript

In JavaScript I want to make a function which takes an argument and in this function a variable will be created whose name will be the value of the argument.
For example if user pass "jack" in the argument then in function I want a variable whose name is jack like:
var jack = "";
Typically, you won't need to do this. As Bergi pointed out, a local variable would usually suffice. However, in the event that you do need to use this technique, you could give the property to the window object:
function setVariable(userPassedString);
window[userPassedString] = "";
}
Don't use eval for this, ever, no matter how tempted you are to.
Creating local variables via a function is typically a bad idea. You could accomplish something similar by passing a local object around, e.g.
function setVar(o, name, value)
{
o[name] = value;
}
Then, inside your local scope:
var o = {};
setVar(o, 'jack', 123);
// o.jack contains 123
In this way, if the need would really arise (this is rarely required) to introduce global variables in this manner, you can always call the function like this:
setVar(window, 'jack', 123);
// now window.jack == jack == 123
The best that you can do about is to create an object and assigns the variable name to the keys of the created object like this -
var myvar={};
function create(var){
myvar[var]='values';
}
You could always use a dictionary. Here is a very simple stub:
function Dictionary(){
var container = {};
this.set = function(key, value){
container[key] = value;
}
this.get = function(key){
return container[key];
}
}
var vars = new Dictionary();
vars.set('foo', 'foo rocks');
vars.set('bar', 'bar rocks too');
console.log(vars.get('foo'));
console.log(vars.get('bar'));
To prevent using the window global array, you can create a local array which holds your variables.
function doSomething(var) {
var vars = {};
vars[var] = value;
}

Getting rid of eval

I have a name of a method as a string in javascript variable and I would like to get a result of its call to variable:
var myMethod = "methodToBeCalled";
var result;
eval("result = "+myMethod+"();")
This works and there are no problems. But this code is inacceptable for Google Closure Compiler. How can I modify it to work with it? Thanks!
EDIT:
It seems the proposed solutions does not work when the name of the method is inside of some object, for instance:
var myFunction = function () { return "foo!" }
var myObject = {
itsMethod: function() { return "foo!" }
};
...
var fstMethodToCall = "myFunction"
var sndMethodToCall = "myObject.itsMethod";
...
window[fstMethodToCall](); // foo!
window[sndMethodToCall](); // undefined
Assuming you are not in a nested scope of some kind, try:
var result = window['methodToBeCalled']();
or
var myMethod = 'methodToBeCalled';
var result = window[myMethod]();
To execute an arbitrary function of arbitrary depth based on a string specification, while not executing eval:
var SomeObject = {
level1: {
level2: {
someFunc: function () {
console.log('hello');
}
}
}
};
var target = 'SomeObject.level1.level2.someFunc';
var obj;
var split = target.split('.');
for (var i = 0; i < split.length; i++) {
obj = (obj || window)[split[i]];
}
obj();
You can use indexer notation:
result = window[myMethod]();
The Closure Compiler doesn't prohibit 'eval', you can continue to use it if you find it convenient but you have to understand that the compiler doesn't try to understand what is going on in your eval statement and assumes your eval is "safe":
function f(x, y) {
alert(eval("y")); // fails: hidden reference to "y"
alert(eval('"'+x+'"')); // might be valid
}
f('me', 'you');
When the compiler optimizes this function it tries to remove "y" and renamed the remain parameter. This will the first eval to fail as "y" no longer exists. The second eval would correct display the alert "me".
So with SIMPLE optimizations, you can use eval to reference global variables and object properties as these are not renamed or removed (but not local ones).
With ADVANCED optimizations, it is a little trickier, as the compiler tries to remove and rename global as well as local variables. So you need to export the values you need to have preserved. This is also true if you use a string to try to reference a name by other means:
var methodName = "myMethod";
(window[methodName])()
or
var methodName = "myMethod";
eval(methodName+"()")
the compiler simply doesn't try to determine if "methodName" is a reference to a function. Here is a simply example of an ADVANCED mode export:
window['myMethod'] = myMethod;
The assignment does two things: it preserves the myMethod function if it would otherwise be removed and it gives it a fixed name by assigning it to a property using a string. If you do need to reference local values, you need to be a little trickier and use a Function constructor. A definition of "f" from my first example, that can eval locals:
var f = new Function("x", "y", "alert(eval('y')); alert(eval('\"' + x + '\"'));");
You may find this page useful:
https://developers.google.com/closure/compiler/docs/limitations

Create a single object

I want to create a single object. Does the below code make sense?
singleObj = new function () {
// act as a constructor.
};
Am I hurting any good practice?
I need a constructor. A simple object literal would not be useful here.
If you want just a single object, in that you are never going to make one again, an object literal works perfectly here.
var x = { };
Will give you an object.
In order for
var F = function() {
};
to give you an object you will need to invoke F
var x = new F();
you could try someting like:
var objCreate = function() {
var obj = {};
// do constructor logic
return obj;
};
Just create a new object and then populate it. You don't need a contrustor to do this.
var singleObject = {};
singleObject.value1 = "whatever";
If you really want to use a function, then you need to actually call it.
var singleObj = new (function () {
// act as a constructor.
})();
We can use a self executing function by creating a anonymous function function(){}, and immediately calling it with an empty argument set.
http://www.w3schools.com/js/js_objects.asp
//Used to create an object
personObj=new Object();
personObj.firstname="John";
personObj.lastname="Doe";
personObj.age=50;
personObj.eyecolor="blue";
//Used as a constructor for the object
function person(firstname,lastname,age,eyecolor)
{
this.firstname=firstname;
this.lastname=lastname;
this.age=age;
this.eyecolor=eyecolor;
}
//how to declare objects via constructor template
var myFather=new person("John","Doe",50,"blue");
var myMother=new person("Sally","Rally",48,"green");

Categories

Resources