If I have an array of objects like:
function Fruit() {
this.onTree = true;
}
Fruit.prototype.pick = function() {
this.onTree = false;
};
var arr = [new Fruit(), new Fruit()];
Is there any way to use Array.forEach to call the pick method on each one without creating an extra anonymous function?
arr.forEach(function(f) { f.pick(); });
I thought maybe I could do something with Fruit.prototype.pick.call but then the this context of the call function is lost so I have to bind that and I end up with:
arr.forEach(Function.call.bind(Fruit.prototype.pick));
which works but it's pretty ugly. Basically I just want something like this from Java:
arr.forEach(Fruit::pick);
You can use many approaches, but at least you need to pass a function to forEach because that is it's syntax. But if you use ES6, you can work with arrow functions and it can be more beautiful.
arr.forEach(f => f.pick());
You missed () after Fruit definition, didn't you?
function Fruit() {
this.onTree = true;
}
Fruit.prototype.pick = function() {
this.onTree = false;
};
var arr = [new Fruit(), new Fruit()];
arr.forEach(function(val, index) {
val.pick();
console.log(val);
})
I tested that one nd it change those fruit.onTree into false.
If you cannot use ES6 (but, well, it's 2017...) you can store your this reference
var self = this;
function invoker(item){
Item.pick.call(self);
}
array.forEach(invoker)
Or just use a for loop
Related
I'm using array value as variable and then call the function N method, how I get them in function N.
I really want to simulate the Javascript array method, I don't want to use parameters to achieve it. For example,
var p1 = [1,2,3,4,5]; p1.push(6);
function _Array() {
this._this = this;
}
_Array.prototype.show = function () {
this._this.forEach(function(item){alert(item);}) //how to print 1,2,3,4,5
};
var p1 = [1,2,3,4,5];
p1 = new _Array();
//p1._Array.call(p1); //not work
// new _Array().show.call(p1); //not work
// p1.show(); //not work
You have to store that in the instance
function N(arr) {
this._this = arr
}
N.prototype.say = function () {
this._this.forEach(function (item) {
console.log(item)
})
}
p1 = new N([1, 2, 3, 4, 5])
p1.say()
If you are insistent on wanting to write a method that takes the array by reference, you can modify the array prototype like so:
Array.prototype.show = function() {
this.forEach(item => alert(item));
}
However, it is a VERY BAD IDEA to modify the built in object prototypes, as this can cause conflicts with external libraries implementing their own "show" function that is being used differently, or cause incompatibilities with future versions of JS that implements this method.
It would be far more prudent in most situations to pass the array as a parameter, unless you have a very specific reason why you're not doing so. In that case, you should at least prefix the method with some sort of project identifier to minimize the chances of conflicts occurring.
What is the equivalent code of window["functionName"](arguments) in NodeJS server-side?
If you need such a capability within a module, one hack is to store such module functions in variables within the module and then call them by accessing them from the module object properties. Example:
var x = { }; // better would be to have module create an object
x.f1 = function()
{
console.log('Call me as a string!');
}
Now, within the module, you can call it using the value from a string:
var funcstr = "f1";
x[funcstr]();
I am learning the ropes with Node myself, the above is probably all sorts of wrong :-). Perhaps a marginally better way to write this example would be (for the module m.js):
module.exports =
{
f1: function() { console.log("Call me from a string!"); },
f2: function(str1) { this[str1](); }
}
Now you can:
var m = require('m.js');
m.f2('f1');
Or even just:
var m = require('m.js');
m['f1']();
FWIW!
you're looking for global
Note, however, that in modules nothing is ever exposed to this level
1) If methods are in same js file
define all methods as properties of Handler:
var Handler={};
Handler.application_run = function (name) {
console.log(name)
}
Now call it like this
var somefunc = "application_run";
Handler[somefunc]('jerry codes');
Output: jerry codes
2) If you want to keep methods in a different js file
// Handler.js
module.exports={
application_run: function (name) {
console.log(name)
}
}
Use method defined in Handler.js in different.js:
// different.js
var methods = require('./Handler.js') // path to Handler.js
methods['application_run']('jerry codes')
Output: jerry codes
If you want to call a class level function using this then following is the solution and it worked for me
class Hello {
sayHello(name) {
console.log("Hello " + name)
}
callVariableMethod() {
let method_name = 'sayHello'
this[`${method_name}`]("Zeal Nagar!")
}
}
If You need it in module scope, You can use something like this
var module = require('moduleName');
module['functionName'](arguments);
Honestly, looking at all these answers they seem a bit too much work. I was playing around to look for other ways around this. You can use the eval() command to print a variable as text then call it as a function
I.e
let commands = ['add', 'remove', 'test'];
for (i in commands) {
if (commands[i] == command) {
var c = "proxy_"+command;
eval(c)(proxy);
}
}
eval(string)(arg1, arg2);
This example script would execute the function proxy_test(proxy)
You know, the OP's code inspired me to try this:
global.test = function(inVal){
console.log(inVal);
}
global['test']('3 is the value')
But now that I think about it, it's no better than #Ravi' s answer.
I use this for node, see if this approach works for you
var _ = require('lodash');
var fnA1 = require('functions/fnA1');
var fnA2 = require('functions/fnA2');
module.exports = {
run: function(fnName, options, callback) {
'use strict';
var nameSpace = fnName.toString().split('.');
// if function name contains namespace, resolve that first before calling
if (nameSpace.length > 1) {
var resolvedFnName = this;
_.forEach(nameSpace, function(name){
resolvedFnName = resolvedFnName[name];
});
resolvedFnName(options, callback);
} else {
this[fnName](options, callback);
}
},
fnA1: fnA1,
fnA2: fnA2
};
call this like
importVariable.run('fnA1.subfunction', data, function(err, result){
if (err) {return callback(err);}
return callback(null, result);
});
That is not specific to the window object. In JavaScript any property of the object can be accessed this way. For example,
var test = {
prop1 : true
};
console.log(test.prop1); // true
console.log(test["prop1"]); // also true
Read more here : https://developer.mozilla.org/en/JavaScript/Guide/Working_with_Objects
I have this code:
var createAllAreSelectedClickedHandler = function(selectablesArrayGetter) {
return function() {
var array = selectablesArrayGetter();
var desiredState = array.every(function(selectable) { return selectable.selected; }) ? false : true;
array.forEach(function(selectable) {
selectable.selected = desiredState;
});
};
};
Followed by this one:
function PromoViewModel() { this.registrations = [...] }
PromoViewModel.prototype.allEventsSelectedClickedHandler = createAllAreSelectedClickedHandler(function() { return this.registrations; }));
I can't manage to set the correct value of this. The "this" value when the function is created points to Window so I can't do .bind(this). I've tried doing .bind(PromoViewModel.prototype) but it lacks all the precious instance fields set inside the constructor.
I know I could simply set this.allEventsSelectedClickedHandler in the constructor function, but I'm trying to separate the methods creation from the variables.
The problem is the call selectablesArrayGetter(); which determines the this value for the callback.
You will need to "pass" the this value that the method (i.e. the closure you are returning) is invoked on, using call:
var array = selectablesArrayGetter.call(this);
I'd recommend defining your PromoViewModel.prototype.allEventsSelectedClickedHandler method as follows:
PromoViewModel.prototype.allEventsSelectedClickedHandler = function() {
var _array = this.registrations;
var desiredState = _array.every(function(selectable) { return selectable.selected; }) ? false : true;
_array.forEach(function(selectable) {
selectable.selected = desiredState;
});
};
the function that you're passing as callback uses this, but doesn't have the PromoViewModel context. You can ensure the method has the proper context by binding this to a variable.
function PromoViewModel()
{
var me = this;
this.registrations = [...];
this.allEventsSelectedClickedHandler = createAllAreSelectedClickedHandler(function() {
return me.registrations;
});
}
Working fiddle: http://jsfiddle.net/michaschwab/coegnL5j/9/ also has Bergi's answer in there (commented out) to show that that works just as well.
Ok here is what I did.
In the prototype definition instead of directly associating it to createAllAreSelectedClickedHandler function, I actually define a function that returns the createAllAreSelectedClickedHandler function. By doing this, I can define a variable (in this case protoScope) that maps this context when defined.
When doing that, if you put a break-point in the createAllAreSelectedClickedHandler function you will see that the selectablesArrayGetter value is correct (the acutal registrations array).
PromoViewModel.prototype.allEventsSelectedClickedHandler = function (){
var protoScope = this;
return createAllAreSelectedClickedHandler(function() {
return protoScope.registrations;
});
}
I would like to get some help debugging a situation where a Reactive Variable is undefined, when it has been defined already.
This code is attaching a Reactive Variable to the template instance, and using the variable in template.autorun().
Template.home.onCreated(function () {
this.limit = new ReactiveVar(15);
this.autorun(function () {
this.subscribe('recent-topics', this.limit.get());
});
});
When I load the template for the first time, I expect the template to subscribe to recent-topics with an argument 15. However, the code throws an error:
Uncaught TypeError: Cannot read property 'get' of undefined
Any ideas why?
Just an answer for the sake of spreading the joys of ES6:
Template.home.onCreated(function () {
this.limit = new ReactiveVar(15);
this.autorun(() => {
this.subscribe('recent-topics', this.limit.get());
});
});
Make sure you add the grigio:babel package, and your Javascript file ends in .es6.js, .es6, or .jsx.
Explanation
In ES6 (aka ECMAScript 6), there's a new "fat arrow" syntax which is very similar to CoffeeScript's implementation. In ES6, when you do something like this:
someFunc = function () {
anotherThing((var1, var2) => {
this.thing = true;
});
};
It's the same as doing this:
someFunc = function () {
var self = this;
anotherThing(function (var1, var2) {
self.thing = true;
});
};
This is a scoping issue.
Inside of your Tracker.autorun, this no longer refers to the template, but the autorun's callback function. Inside of the autorun, try calling Template.instance().limit.get().
Better than using Template.instance().limit.get() (ryan's answer)
You should do something like this:
Template.home.onCreated(function () {
var self = this;
self.limit = new ReactiveVar(15);
self.autorun(function () {
self.subscribe('recent-topics', self.limit.get());
});
});
Is it possible to call a function in javascript from a string, where the function is in an object?
e.g: call "main.object.doSomething()" (notice it is a string) from the object below.
window.main = {
object: {
doSomething: function(){
alert('Called');
}
}
}
--- Update ---
...without using eval();
window.main = {
object: {
doSomething: function(){
alert('Called');
}
}
}
function callFromString(aString) {
var parts = aString.split(".");
var obj = window;
for (var i = 0; i < parts.length - 1; i++) {
obj = obj[parts[i]];
if (!obj)
return;
}
// strip () at the end of parts[parts.length - 1] if they are present
if (obj[parts[parts.length - 1]])
obj[parts[parts.length - 1]]();
}
callFromString("main.object.doSomething");
http://jsfiddle.net/79nWH/
You can use eval, so:
eval("main.object.doSomething()");
But eval is evil - try to avoid it.
Do not use eval! There are many good reasons not to use eval, and most of the time there's absolutely no reason to do so. Instead, you can use the string property lookup syntax to get the method you're looking for: main.object.doSomething() is equivalent to main.object['doSomething'](). So, for example, if you want to call a function based on a string, you could do:
var methodToCall = 'doSomething';
main.object[methodToCall]();
If putting the parentheses right after the property lookup looks weird to you, you could also do main.object[methodToCall].call(null).
use eval(expression or function)
read about that in http://www.w3schools.com/jsref/jsref_eval.asp
or http://viralpatel.net/blogs/calling-javascript-function-from-string/
Lets say you have your string like:
var funcString = "window.main = {
object: {
doSomething: function(){
alert('Called');
}
}
}";
eval(funcString);
and if you have already your function defined in the page, you can call it with 2 different ways, using eval (which no js expert would never offer using it, you should use it just when you don't have any other option):
eval("main.object.doSomething()");
and the other way is using anonymous function:
Function("main.object.doSomething();")();