Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 8 years ago.
Improve this question
I want to store into an array, a set of closures to be run when it been called.
Is eval the best thing to do it?
"Eval is evil" ;-)
but here's a possible solution
Array.prototype.execute = function() {
for ( var i in this ) {
if ( i && 'execute' != i && Function == this[ i ].constructor ) {
this[ i ].apply( this );
}
}
};
var arr = [];
arr.push( ( function() {alert('A'); } ) );
arr.push( ( function() {alert('B'); } ) );
arr.push( ( function() {alert('C'); } ) );
arr.execute();
please keep in mind: it's not recommended to extend basical Javascript types in the way I did.
I’m not sure what you mean by "run when it been called", but since Arrays are Objects, you can store static information as object keys in the array:
var arr = ['foo','bar'];
arr.methods = {
foo: function() { alert(this[0]); },
bar: function() { alert(this[1]); },
};
arr.run = function() {
for (var fn in this.methods) {
this.methods[fn].call(this);
}
};
arr.run();
You could also make this into a reusable function using prototypal inheritance, but you would need to embed the array inside it, since Arrays are not "subclassable" in javascript.
Ok, since everybody keeps guessing at what it is you're actually looking for, here's my .02:
var closures = (function(Global,undefined)
{
var that = [];//return value
that[0] = (function(some,vars, forClosure1)
{
return function()
{
console.log(some, vars,forClosure1);
};
})(values,of,closureArguments);//create all closures you need
that.execAll = function (context,args)//the method to call them all (with arguments)
{
context = (context === undefined || context === Global ? that : context);
args = args.length ? args : [];//make sure arguments has length property
for (var i=0;i<that.length;i++)
{
if (typeof that[i] === 'function')
{
that[i].apply(context,args);
}
}
};
return that;//return closure array (with execAll method)
})(window);
Now, I've created an array of closures, that has its own method execAll, you can pass 2 arguments to this method: the first determines the context in which the closre functions of the array will be called, the second expects an array or arguments object to pass to each of these closure functions.As it currently stands, the closures cannot be called in a global context using execAll. That's just for safety, but you never know, maybe you might want to call them in the global object's context.
All in all, I think this is what you're looking for, though I must admit: I'm struggeling to see how this code could be of any use, but maybe that's just me.Anyway: good luck
You can create a function on the fly and store the reference in a variable:
var something = function() { alert("hello world"); };
And by extension in an array:
var something = [function() { alert("hello world"); },
function() { alert("hello world"); },
function() { alert("hello world"); }];
Which you may later call by using something(); in the first example or something[1](); in the second for instance. Eval is absolutely not needed here, unless the actual body of the function comes from user input (god forbid :-) )
What and how to call it is left to the implementation, but it should be fairly trivial once you are aware of this.
Related
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 2 years ago.
Improve this question
I want to access same variable properties in a java script file but because are too many properties the code looks a bit to ugly. I have the next code:
$scope.invoice = new Invoice();
$scope.operations = {
editingLine: {},
isNewLine: false,
isEditOpen: false
};
$scope.modify = function (invoiceLine) {
if ($scope.operations.isEditOpen) return;
let originalLine = $scope.invoice.invoiceLines.find(line => line.id = invoiceLine.id);
tempLine = angular.copy(originalLine);
$scope.operations.editingLine[invoiceLine.id] = true;
$scope.operations.isEditOpen = true;
};
Is there any way to access the the property invoiceLine which is set on the object invoice, or the property isEditOpen which is set on the object operations in cleaner way? I have a lot of repetition of this code in my file and I want to find a clener way to access properties like this.
I know that I can to define a variable var operations = $scope.operations and to access the property operations.isEditOpen when I need this value but still, I want something more simpler because I don't want to create variable for all objects from the scope.
Is there any way to create a function with two params (objectFromScope, neededProperty) that can return the requiered property value from a variable which is set on the scope? Or is there any better way to do not have such much code when I want to access an object property from the scope?
PS: I can also do something like this:
let editingLine = $scope.operations.editingLine;
let isNewLine = $scope.operations.isNewLine;
let isEditOpen = $scope.operations.isEditOpen;
$scope.modify = function (invoiceLine) {
if (isEditOpen) return;
let originalLine = invoiceLines.find(line => line.id = invoiceLine.id);
tempLine = angular.copy(originalLine);
editingLine[invoiceLine.id] = true;
isEditOpen = true;
};
But is this a good approach?
Is there any way to create a function with two params ( objectFromScope, neededProperty ) that can return the required property value from a variable which is set on the scope? Or is there any better way to do not have such much code when I want to access an object property from the scope?
Yes, but I don't see how it saves you any trouble. It will also make it harder to switch to TypeScript (though you can make it work with keyof if you don't want to dereference an entire property path).
But this is that function:
function getPropertyValue( objectFromScope, neededProperty ) {
const pathComponents = neededProperty.split( '.' );
let obj = objectFromScope;
for( const component of pathComponents ) {
obj = obj[ component ];
}
return obj;
}
Usage:
$scope.invoice = new Invoice();
$scope.operations = {
editingLine: {},
isNewLine: false,
isEditOpen: false
};
$scope.modify = function( invoiceLine ) {
if ($scope.operations.isEditOpen) return;
const lines = getPropertyValue( $scope, 'invoice.invoiceLines' );
let originalLine = lines.find(line => line.id = invoiceLine.id);
tempLine = angular.copy(originalLine);
$scope.operations.editingLine[invoiceLine.id] = true;
$scope.operations.isEditOpen = true;
};
...but this really doesn't make your code any easier to read or maintain. Instead it makes it worse because doing things this way is very non-idiomatic for JavaScript and AngularJS: anyone else who works on this project will stare at the code for a few minutes and scratch their head before wondering out loud why you're doing this in the first place.
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 2 years ago.
Improve this question
Example :
Creating function
const isElementLoaded = () => {
//Logic
return true;
}
Calling function using this.isElementLoaded :
if (this.isElementLoaded)
{
//output true
}
If you don't want to use (), you need to make it an accessor property. (The only other way to call it without () is to use it as a tag function on a tagged template literal, which doesn't seem relevant to what you're doing. :-) )
In a class, you'd do that like this:
class Example {
get isElementLoaded() {
return /*...appropriate value...*/;
}
}
In an object literal, it's basically the same:
const obj = {
get isElementLoaded() {
return /*...appropriate value...*/;
}
};
In either case, TypeScript should be able to infer the return type from your return statement, but if necessary add the annotation, e.g.:
class Example {
get isElementLoaded(): boolean {
return /*...appropriate value...*/;
}
}
If you want to add an accessor to an object after it's created, you use defineProperty:
Object.defineProperty(obj, "isElementLoaded", {
get() {
return /*...appropriate value...*/;
},
// flags here if appropriate; they default to `false` if omitted
});
You'll need to be sure the type information for the object includes the accessor (perhaps as an optional property).
Either you use a function and then you need to use () to call the function (that's the TypeScript / JavaScript syntax):
const isElementLoaded = () => {
//Logic
return true;
}
// in a function:
if (this.isElementLoaded()) {
//output true
}
Or, you can use a property on your class with a getter:
get isElementLoaded() {
//Logic
return true;
}
// in a function
if (this.isElementLoaded) {
//output true
}
tl;dr: use this.isElementLoaded()
You are actually not calling the function you created there. You are using arrow notation to create a function, you could do the same with
function isElementLoaded(...){...}
which would it make more clear maybe that you have to call it to actually do something. By just calling the name of the function you reference to the function body - but that is not progressed in any way.
Here's a quick try-out example: https://jsbin.com/kekifugoqe/edit?js,console
Hit 'run' and you see the difference in the output.
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Can I get the name of the currently running function in javascript?
I need this for recursion. I'd like to be able to change the function name without checking and changing every instance where the function calls itself.
(For example php has "magic constants" like __FUNCTION__ etc.. - is something similar in JavaScript?)
If your goal is recursion, you don't need the function name as a string if you can get a reference to the function itself. Note that you'll still have to check and change every instance where the function is called by others, and that's likely to be a larger task than updating the recursive calls (if for no other reason than it's not localized to the function body).
Passing the function as an argument
function foo(self, i)
{
if (i === 0 )
return;
console.log(i--);
self(self, i);
}
foo(foo, 3);
Using arguments.callee (As Raynos points out, this is brittle in strict mode)
function foo(i)
{
if (i === 0 )
return;
console.log(i--);
arguments.callee(i);
}
foo(3);
Output of either option
3
2
1
Maybe you can refactor your function since arguments.callee is not dependable. For example, you could use a nested function that does the recursion:
var name_does_not_matter = function(m) {
var inner = function(n) {
if (n <= 2) return 1;
return inner(n-2) + inner(n-1);
};
return inner(m);
};
[UPDATE] Actually, you should be able to access the function by its name regardless of the parent scope. In my test, the following example works:
var foo = 10;
var bar = function foo(n) {
return (n <= 2) ? 1 : foo(n-2) + foo(n-1);
};
alert(foo); // Displays '10'
alert(bar(10)); // Displays '55'
function senad()
{
var fName= arguments.callee.toString();
fName= fName.substr('function '.length);
fName= fName.substr(0, fName.indexOf('('));
alert(fName)
}
senad();
(function() {
"use strict";
console.log(arguments.callee);
})()
Yields
TypeError: Cannot access property 'callee' of strict mode arguments
You cannot do this in ES5 strict mode, and for a good reason. It's a hack. Don't do it.
My problem is pretty easy to understand. I have a JSON object (see code) and I will automatically call all functions of this object in the order that those appears. .
var installer = {
a : function() {
...
}
b : function() {
...
}
};
for(var func in installer) {
fn.call(document);
};
Have you any idea why the previous code doesn't work ? I'm sorry, I'm a beginner in javascript.
Thanks in advance !
Regards.
You don't have a variable called fn, and you are also missing commas at the end of your function definitions.
Additionally, your functions will not be called in order because JavaScript orders your object properties arbitrarily. You may want to consider using an array or, as I have done below, specify an array that determines the order.
var installer = {
a : function() {
...
},
b : function() {
...
},
};
var order = [ "a", "b" ];
for(var i = 0; i < order.length; i++) {
installer[order[i]].call(document);
}
You declare var func as the variable to loop through the members of installer, yet you use fn.call(...). Where did fn come from?
Should you be able to do: installer[func].call(document) instead of fn.call(document).
Also your functions declared in the installer object don't take any arguments, yet you're passing document as an argument.
[updated code to add missing .call to installer[func](document)]
I'm trying to create a simple, small and basic javascript framework just for learning purposes.
But the thing is that i'm allready stuck at the very basics.
I'm trying to do something like this:
$('testdiv').testFunction();
And the code i've written for that:
var elementID;
var smallFramework = {
$:function(id) {
this.elementID = id;
},
testFunction:function() {
alert(this.elementID);
}
};
window.$ = smallFramework.$;
But in return I get:
$('testdiv) is undefined
Can anyone help me with this small and hopefully easy question?
To get the behavior you're expecting, you need the $ function to return an object with a method named testFunction.
Try:
var smallFramework = // an object for namespacing
{
$:function(id) // the core function - returns an object wrapping the id
{
return { // return an object literal
elementID: id, // holding the id passed in
testFunction: function() // and a simple method
{
alert(this.elementID);
}
};
}
};
Of course, there are many other ways to achieve the behavior you desire.
If you're trying to add methods to an HTML element you could do something along these lines.
$ = function( elementId ) {
var element = document.getElementById( elementId );
element.testFunction = function(){
alert( this.id );
return this; // for chaining
}
return element;
}
$('test').testFunction();
Try
smallFramework.$('testdiv');
instead. According to the code you posted, that's where your $ function ended up.
Or alternatively, it looks like you're trying to replicate something like jQuery. You might want to try something like this.
var $ = smallFramework = (function () {
var f =
{
find:function(id) {
f.elementID = id;
return f; //every function should return f, for chaining to work
},
testFunction:function() {
alert(f.elementID);
return f;
}
}
return f.find //the find function will be assigned to $.
//and also assigned to smallFramework.
//the find function returns f, so you get access to testFunction via chaining
// like $("blah").testFunction()
})() //note this function gets called immediately.
this code may look confusing to someone new to JavaScript because it depends heavily on the concept of closures. I suggest that if this doesn't make sense, spend some time at Douglas Crockford's JavaScript website. This is important because the code above will bite if you happen to use this in the find function because this won't be bound to f, as you may expect it to be when you use it from $ or smallFramework.