Data being returned as undefined in Javascript - javascript

I am having an issue with JavaScript returning undefined (which is probably more due to my understanding of JS).
I have 2 functions like so:
getData = function(name) {
var string = "You're name is " + name;
alert("created string is: " + string); // this alerts "You're name is John"
return string;
}
firstFunction = function() {
newString = getData("John");
alert(newString); // this allerts "undefined"
}
firstFunction();
What would be the cause of getData returning undefined to firstFunction?

Code :
<script>
const getData = name => {
var string = `You're name is ${name}`;
alert(`created string is: ${string}`); // this alerts "You're name is John"
// The return string command is not required
}
const firstFunction = () => {
getData("John");
}
firstFunction();
</script>
Edits :
Used arrow function instead of normal one
used string literals instead of normal string
Possibly fixed the error
Reading :
string literals
Arrow function

Related

Use a string in a function, ReferenceError

I am trying to use a string as part of a function.
const import1 = require('./import1');
const import2 = require('./import2');
//on above files there is a method, let's call it method1.
const string = "import1"; // or could be "import2"
//I would like to use above string as code.
//This is what I tried:
const functionToUse = new Function(string + ".method1()");
functionToUse();
This is the error I get: "ReferenceError: import1 is not defined"
I checked this answer: Convert a string to a function, gives ReferenceError and it kind off works but I need to pass in the import1 or 2 as a string.
All help is truly appreciated!
why not using object to access function?
const import1 = { method: function() { alert('method!'); } }; //require('./import1');
const import2 = { method2: function() {alert('method2'); } }; // require('./import2');
// Add link to both objects
window.myImports = { import1, import2 };
const string = "import1";
const functionToUse = getFunction(string + ".method");
function getFunction(path) {
const parts = path.split('.');
let obj = window.myImports;
for(let part of parts) {
obj = obj[part];
}
return obj;
}
functionToUse();
There is problem with your import statement. Otherwise there is no problem for function calling .
let string1 = "hello";
var functionCalls = (string)=>{
console.log("string inside function", string);
}
functionCalls(string1);
You can check example.

Methods, Loops and the `this` Keyword

I am new at Javascript. I am currently looking at the keyword this and methods and how to return strings.
I am struggling to return a string using the keyword this.
I have successfully created code that returns the string, but the problem is that it shows the error that "the object is already defined".
Here is the exercise I am working on and also the code I have tried to create which fails to return the correct results:
function exerciseTwo(userObj) {
// Exercise Two: You will be given an object called 'userObj'
// userObject will already have a key on it called 'name'
// Add a method to userObj, called 'greeting'.
// Using the keyword 'this', the greeting method should return the following string:
// 'Hi, my name is ' and the users name.
// eg: If userObj has a name: 'Dan', greeting should return: Hi, my name is Dan'
// NOTE: DO NOT create a new object.
// NOTE: DO NOT create a key called name the key is already on the object.
let userObj = {
name: "Lisa",
greeting: function() {
return "Hi, my name is " + this.name;
},
};
console.log(userObj.greeting());
}
//In the first line of code it shows a error which says that "userObj" is already defined. So I do not know how to return the string without creating a new object and creating a key called name.
//Here is another option I tried but it also did not work out:
function greeting() {
this.name = "Lisa";
let result = "Hi, my name is " + this.name;
return result;
},
userObj.greeting();
}
//The exercise should add a greeting method to userObject object.
So if userObj has a name: 'Lisa', greeting should return: 'Hi, my name is Lisa'
The problem is that your local variable has the same name as the function parameter. You're supposed to add a method to the existing variable, not create a new variable. The instructions specifically say "DO NOT create a new object", yet that is what you did.
function exerciseTwo(userObj) {
// Exercise Two: You will be given an object called 'userObj'
// userObject will already have a key on it called 'name'
// Add a method to userObj, called 'greeting'.
// Using the keyword 'this', the greeting method should return the following string:
// 'Hi, my name is ' and the users name.
// eg: If userObj has a name: 'Dan', greeting should return: Hi, my name is Dan'
// NOTE: DO NOT create a new object.
// NOTE: DO NOT create a key called name the key is already on the object.
userObj.greeting = function() {
return "Hi, my name is " + this.name;
};
console.log(userObj.greeting());
}
let obj = {
name: "Joe"
};
exerciseTwo(obj);
function exerciseTwo(userObj){ // The argument for this "exerciseTwo" function has been declared as "userObj"
let userObj = { // Here you are trying to declare another variable "userObj"
name: "Lisa",
greeting: function() {
return "Hi, my name is " + this.name;
}
};
console.log(userObj.greeting());
}
To solve your issue,
- Declare the let userObj = { ... } block outside the "exerciseTwo" function and pass it in as a variable
let lisa = {
name: "Lisa"
};
function exerciseTwo(userObj){ // Whatever variable you pass into this function will be synonymous to `userObj` within this function
userObj.greeting = function () {
return "Hi, my name is " + this.name;
}
console.log(userObj.greeting());
}
exerciseTwo(lisa) // lisa will take the position of `userObj` above
As the exercise says you only have to add the greeting function to the users object. Like this:
let userObj = { name: "Lisa" };
function exercise2(userObj) {
userObj.greetings = function () {
return "Hi, my name is " + this.name;
}
}
exercise2(userObj);
console.log(userObj.greetings());

Why toString is not a generic function in javascript

I was trying to do something like this.
var myFunc = function() {}
myFunc.prototype = new String();
myFunc.prototype.replace = function() {return 'hii, Mr '+ this.toString();}
var oVal = new myFunc('Jyotirmay');
oVal.replace();
o/p :: Uncaught TypeError: String.prototype.toString is not generic(…)
Why "function not generic" error comes actually in general?
As to be more clear, How can i pass my argument i.e Jyotirmay from inherited class to base class i.e string. So that i can get that value by calling any proper string function.
I don't want to get my passed value from my function by handling that variable in it.
I want that to be handled by parent class. You can say super() in other languages.
It is unclear what exactly you are trying to achieve from your question and comments, but perhaps this is all you are trying to do?
function myFunc(inputArg) {
this.inputArg = inputArg;
}
myFunc.prototype = {
replace: function () {
return 'hii, Mr ' + this.inputArg;
},
toString: function () {
return '' + this.inputArg;
}
};
myFunc.prototype.valueOf = myFunc.prototype.toString;
function log(inputArg) {
document.getElementById('out').appendChild(document.createTextNode(inputArg + '\n'));
}
var oVal = new myFunc('Jyotirmay');
log(oVal);
log(oVal.replace());
<pre id="out"></pre>
As to Why is toString not generic, this is because not all objects can be represented as a string by the same conversion method.
Update based on your latest comment
Native objects are notoriously difficult, if not impossible, to subclass in Javascript. There are a few hacks that will allow you partial success, but I would not recommend them and good luck across different environments.
Two (but not the only) such hacks are:
Stealing from an iframe
function stealObject(objectName, myVariableName) {
var iframe = document.createElement('iframe');
iframe.style.display = 'none';
iframe.src = 'javascript:parent.' + myVariableName + ' = ' + objectName;
document.body.appendChild(iframe);
document.body.removeChild(iframe);
return window[myVariableName];
}
function log(inputArg) {
document.getElementById('out').appendChild(document.createTextNode(inputArg + '\n'));
}
try {
stealObject('String', 'MyString');
MyString.prototype.replace = function () {
return 'hii, Mr ' + this;
};
var oVal = new MyString('Jyotirmay');
log(oVal);
log(oVal.toUpperCase());
log(oVal.replace());
} catch (e) {
log(e);
}
<pre id="out"></pre>
Doesn't work in SO snippets because SecurityError: Sandbox access violation: but can see it on this jsFiddle. typeof oVal will return object and not string and oVal instanceof String will be false. oVal.constructor === String will return false.
Another hack
function MyString() {
this.str = '' + arguments[0];
};
with(MyString.prototype = new String()) {
toString = valueOf = function () {
return this.str;
};
}
MyString.prototype.replace = function () {
return 'hii, Mr ' + this;
};
function log(inputArg) {
document.getElementById('out').appendChild(document.createTextNode(inputArg + '\n'));
}
var oVal = new MyString('Jyotirmay');
log(oVal);
log(oVal.toUpperCase());
log(oVal.replace());
<pre id="out"></pre>
The magic length property is broken in this one and you would need to call oVal.toString().length instead. typeof oVal will return object and not string but oVal instanceof String will be true. oVal.constructor === String will return true.

Creating method for string without creating prototype

I want to create a method that you can call like 'string'.doSth() without creating a new string prototype. How can I do it?
I noticed you DON'T want String.prototype
Avoid using it by doing something like:
window.doSth = function (s) {
return s + '!';
};
Or, you can make your own constructor:
var SpecialString = function (s) {
this.value = s;
this.doSth = function () {
return this.value + '!';
};
};
Now:
var myString = new SpecialString('Foo');
myString.value; // Its value, Foo
myString.doSth(); // Returns Foo!
I'll leave the rest just in case you change your mind
this and String.prototype
You can use String.prototype. This will let you "add functions" to string. To get the string, use this:
String.prototype.doSth = function () {
alert(this);
};
var testString = 'Foo Bar';
testString.doSth(); // Alerts "Foo Bar"
Using return
Use return to produce a new value. Let's say you wanted this function to add an exclamation mark ! to the end of the string:
String.prototype.addExclamation = function () {
return this + '!';
};
Now:
var testString = "Foo";
var newString = testString.addExclamation();
alert(newString); // Alerts Foo!
Only other way is to just not create a global function and add it to String
String.doSth = function(str) {
//do something
}
String.doSth('hi');
You can allways augment the prototype of String. Here's how
String.prototype.doSomething = function () {
console.log('doing something');
}
var a = 'str';
a.doSomething();
By writing 'string' you are basically creating a new string object.
If you add a doSth method to the string prototype, it will be callable:
String.prototype.doSth = function doSth() {
console.log('Inside');
}
"string".doSth(); // will log 'Inside'

Dynamic function name in javascript?

I have this:
this.f = function instance(){};
I would like to have this:
this.f = function ["instance:" + a](){};
This will basically do it at the most simple level:
"use strict";
var name = "foo";
var func = new Function(
"return function " + name + "(){ alert('sweet!')}"
)();
//call it, to test it
func();
If you want to get more fancy, I have a written an article on "Dynamic function names in JavaScript".
You can use Object.defineProperty as noted in the MDN JavaScript Reference:
var myName = "myName";
var f = function () { return true; };
Object.defineProperty(f, 'name', {value: myName, writable: false});
In recent engines, you can do
function nameFunction(name, body) {
return {[name](...args) {return body.apply(this, args)}}[name]
}
const x = nameFunction("wonderful function", (p) => p*2)
console.log(x(9)) // => 18
console.log(x.name) // => "wonderful function"
Thanks to T S for pointing out the need to preserve this in the comments.
Also, these days, I'd probably use the Object.defineProperty approach to achieve something similar.
Update 2021: CherryDT's answer should be the easiest most straight forward way now, but it doesn't work consistently with different browsers for stack traces or Function.prototype.toString(), so if you need that you're stuck with this less convenient solution.
Old answer: Many suggestions here are suboptimal, by using eval, hacky solutions or wrappers.
As of ES2015 names are inferred from the syntactic position for variables and properties.
So this will work just fine:
const name = 'myFn';
const fn = {[name]: function() {}}[name];
fn.name // 'myFn'
Resist the temptation to create named function factory methods as you wouldn't be able to pass the function from outside and retrofit it into the syntactic position to infer its name. Then it's already too late. If you really need that, you have to create a wrapper. Someone did that here, but that solution doesn't work for classes (which are also functions).
A much more in-depth answer with all the variants outlined has been written here: https://stackoverflow.com/a/9479081/633921
As others mentioned, this is not the fastest nor most recommended solution. Marcosc's solution below is the way to go.
You can use eval:
var code = "this.f = function " + instance + "() {...}";
eval(code);
What about
this.f = window["instance:" + a] = function(){};
The only drawback is that the function in its toSource method wouldn't indicate a name. That's usually only a problem for debuggers.
The syntax function[i](){} implies an object with property values that are functions, function[], indexed by the name, [i].
Thus
{"f:1":function(){}, "f:2":function(){}, "f:A":function(){}, ... } ["f:"+i].
{"f:1":function f1(){}, "f:2":function f2(){}, "f:A":function fA(){}} ["f:"+i] will preserve function name identification. See notes below regarding :.
So,
javascript: alert(
new function(a){
this.f={"instance:1":function(){}, "instance:A":function(){}} ["instance:"+a]
}("A") . toSource()
);
displays ({f:(function () {})}) in FireFox.
(This is almost the same idea as this solution, only it uses a generic object and no longer directly populates the window object with the functions.)
This method explicitly populates the environment with instance:x.
javascript: alert(
new function(a){
this.f=eval("instance:"+a+"="+function(){})
}("A") . toSource()
);
alert(eval("instance:A"));
displays
({f:(function () {})})
and
function () {
}
Though the property function f references an anonymous function and not instance:x, this method avoids several problems with this solution.
javascript: alert(
new function(a){
eval("this.f=function instance"+a+"(){}")
}("A") . toSource()
);
alert(instanceA); /* is undefined outside the object context */
displays only
({f:(function instanceA() {})})
The embedded : makes the javascript function instance:a(){} invalid.
Instead of a reference, the function's actual text definition is parsed and interpreted by eval.
The following is not necessarily problematic,
The instanceA function is not directly available for use as instanceA()
and so is much more consistent with the original problem context.
Given these considerations,
this.f = {"instance:1": function instance1(){},
"instance:2": function instance2(){},
"instance:A": function instanceA(){},
"instance:Z": function instanceZ(){}
} [ "instance:" + a ]
maintains the global computing environment with the semantics and syntax of the OP example as much as possible.
The most voted answer has got already defined [String] function body. I was looking for the solution to rename already declared function's name and finally after an hour of struggling I've dealt with it. It:
takes the alredy declared function
parses it to [String] with .toString() method
then overwrites the name (of named function) or appends the new one (when anonymous) between function and (
then creates the new renamed function with new Function() constructor
function nameAppender(name,fun){
const reg = /^(function)(?:\s*|\s+([A-Za-z0-9_$]+)\s*)(\()/;
return (new Function(`return ${fun.toString().replace(reg,`$1 ${name}$3`)}`))();
}
//WORK FOR ALREADY NAMED FUNCTIONS:
function hello(name){
console.log('hello ' + name);
}
//rename the 'hello' function
var greeting = nameAppender('Greeting', hello);
console.log(greeting); //function Greeting(name){...}
//WORK FOR ANONYMOUS FUNCTIONS:
//give the name for the anonymous function
var count = nameAppender('Count',function(x,y){
this.x = x;
this.y = y;
this.area = x*y;
});
console.log(count); //function Count(x,y){...}
For setting the name of an existing anonymous function:
(Based on #Marcosc's answer)
var anonymous = function() { return true; }
var name = 'someName';
var strFn = anonymous.toString().replace('function ', 'return function ' + name);
var fn = new Function(strFn)();
console.log(fn()); // —> true
Demo.
Note: Don't do it ;/
The function's name property by default isn't writeable, but since it's configurable we can still use Object.defineProperty to change it. Since Object.defineProperty conveniently returns the object itself, we can write a function with a dynamic name like this:
const theName = 'foobar'
const fn = Object.defineProperty(function () {
/* ... */
}, 'name', { value: theName })
console.log(fn.name) // Logs foobar
Of course this could be factored out into a helper function:
const nameFunction = (name, fn) => Object.defineProperty(fn, 'name', { value: name })
const fn = nameFunction('foobar', function () {
/* ... */
})
console.log(fn.name) // Logs foobar
The above nameFunction function can also be used to rename an existing function, of course (here it's just renaming and returning the anonymous one).
Dynamic methods of an object may be created using Object Literal Extensions provided by ECMAScript 2015 (ES6):
const postfixes = ['foo', 'bar'];
const mainObj = {};
const makeDynamic = (postfix) => {
const newMethodName = 'instance: ' + postfix;
const tempObj = {
[newMethodName]() {
console.log(`called method ${newMethodName}`);
}
}
Object.assign(mainObj, tempObj);
return mainObj[newMethodName]();
}
const processPostfixes = (postfixes) => {
for (const postfix of postfixes) {
makeDynamic(postfix);
}
};
processPostfixes(postfixes);
console.log(mainObj);
The output of running the code above is:
"called method instance: foo"
"called method instance: bar"
Object {
"instance: bar": [Function anonymous],
"instance: foo": [Function anonymous]
}
the best way it is create object with list of dynamic functions like:
const USER = 'user';
const userModule = {
[USER + 'Action'] : function () { ... },
[USER + 'OnClickHandler'] : function () { ... },
[USER + 'OnCreateHook'] : function () { ... },
}
There are two methods to achieve this, and they have their pros and cons.
name property definition
Defining immutable name property of a function.
Pros
Every character is available for the name. (eg. () 全 {}/1/얏호/ :D #GO(#*#%! /*)
Cons
The function's syntactic (“expressional”) name may not correspond with its name property value.
Function expression evaluation
Making a named function expression and evaluating it with Function constructor.
Pros
The function's syntactic (“expressional”) name always corresponds with its name property value.
Cons
Whitespaces (and etc.) are not available for the name.
Expression-injectable (eg. For input (){}/1//, the expression is return function (){}/1//() {}, gives NaN instead of a function.).
const demoeval = expr => (new Function(`return ${expr}`))();
// `name` property definition
const method1 = func_name => {
const anon_func = function() {};
Object.defineProperty(anon_func, "name", {value: func_name, writable: false});
return anon_func;
};
const test11 = method1("DEF_PROP"); // No whitespace
console.log("DEF_PROP?", test11.name); // "DEF_PROP"
console.log("DEF_PROP?", demoeval(test11.toString()).name); // ""
const test12 = method1("DEF PROP"); // Whitespace
console.log("DEF PROP?", test12.name); // "DEF PROP"
console.log("DEF PROP?", demoeval(test12.toString()).name); // ""
// Function expression evaluation
const method2 = func_name => demoeval(`function ${func_name}() {}`);
const test21 = method2("EVAL_EXPR"); // No whitespace
console.log("EVAL_EXPR?", test21.name); // "EVAL_EXPR"
console.log("EVAL_EXPR?", demoeval(test21.toString()).name); // "EVAL_EXPR"
const test22 = method2("EVAL EXPR"); // Uncaught SyntaxError: Unexpected identifier
If you want to have a dynamic function like the __call function in PHP, you could use Proxies.
const target = {};
const handler = {
get: function (target, name) {
return (myArg) => {
return new Promise(resolve => setTimeout(() => resolve('some' + myArg), 600))
}
}
};
const proxy = new Proxy(target, handler);
(async function() {
const result = await proxy.foo('string')
console.log('result', result) // 'result somestring' after 600 ms
})()
You can use Dynamic Function Name and parameters like this.
1) Define function Separate and call it
let functionName = "testFunction";
let param = {"param1":1 , "param2":2};
var func = new Function(
"return " + functionName
)();
func(param);
function testFunction(params){
alert(params.param1);
}
2) Define function code dynamic
let functionName = "testFunction(params)";
let param = {"param1":"1" , "param2":"2"};
let functionBody = "{ alert(params.param1)}";
var func = new Function(
"return function " + functionName + functionBody
)();
func(param);
This utility function merge multiple functions into one (using a custom name), only requirement is that provided functions are properly "new lined" at start and end of its scoop.
const createFn = function(name, functions, strict=false) {
var cr = `\n`, a = [ 'return function ' + name + '(p) {' ];
for(var i=0, j=functions.length; i<j; i++) {
var str = functions[i].toString();
var s = str.indexOf(cr) + 1;
a.push(str.substr(s, str.lastIndexOf(cr) - s));
}
if(strict == true) {
a.unshift('\"use strict\";' + cr)
}
return new Function(a.join(cr) + cr + '}')();
}
// test
var a = function(p) {
console.log("this is from a");
}
var b = function(p) {
console.log("this is from b");
}
var c = function(p) {
console.log("p == " + p);
}
var abc = createFn('aGreatName', [a,b,c])
console.log(abc) // output: function aGreatName()
abc(123)
// output
this is from a
this is from b
p == 123
I had better luck in combining Darren's answer and kyernetikos's answer.
const nameFunction = function (fn, name) {
return Object.defineProperty(fn, 'name', {value: name, configurable: true});
};
/* __________________________________________________________________________ */
let myFunc = function oldName () {};
console.log(myFunc.name); // oldName
myFunc = nameFunction(myFunc, 'newName');
console.log(myFunc.name); // newName
Note: configurable is set to true to match the standard ES2015 spec for Function.name1
This especially helped in getting around an error in Webpack similar to this one.
Update: I was thinking of publishing this as an npm package, but this package from sindresorhus does exactly the same thing.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/name
I struggled a lot with this issue. #Albin solution worked like a charm while developing, but it did not work when I changed it to production. After some debugging I realized how to achieve what I needed. I'm using ES6 with CRA (create-react-app), which means it's bundled by Webpack.
Lets say you have a file that exports the functions you need:
myFunctions.js
export function setItem(params) {
// ...
}
export function setUser(params) {
// ...
}
export function setPost(params) {
// ...
}
export function setReply(params) {
// ...
}
And you need to dynamically call these functions elsewhere:
myApiCalls.js
import * as myFunctions from 'path_to/myFunctions';
/* note that myFunctions is imported as an array,
* which means its elements can be easily accessed
* using an index. You can console.log(myFunctions).
*/
function accessMyFunctions(res) {
// lets say it receives an API response
if (res.status === 200 && res.data) {
const { data } = res;
// I want to read all properties in data object and
// call a function based on properties names.
for (const key in data) {
if (data.hasOwnProperty(key)) {
// you can skip some properties that are usually embedded in
// a normal response
if (key !== 'success' && key !== 'msg') {
// I'm using a function to capitalize the key, which is
// used to dynamically create the function's name I need.
// Note that it does not create the function, it's just a
// way to access the desired index on myFunctions array.
const name = `set${capitalizeFirstLetter(key)}`;
// surround it with try/catch, otherwise all unexpected properties in
// data object will break your code.
try {
// finally, use it.
myFunctions[name](data[key]);
} catch (error) {
console.log(name, 'does not exist');
console.log(error);
}
}
}
}
}
}
Node.js JavaScript Class Based Dynamic Function Name
File: Schema.js
class Schema {
constructor() {
this.name = null;
}
virtual(name = null) {
this.name = name;
return this;
}
get(func = false) {
if (!this.name || !func instanceof Function) {
throw new Error("Name and function must be provided.");
}
// Attach the dynamic function name to the "this" Object
this[this.name] = func;
this.name = null;
}
}
module.exports = Schema;
File: index.js
const Schema = require("./Schema.js");
const User = new Schema();
User.virtual("getPostCount").get(() => {
return 10 + 10;
});
const ok = User.getPostCount();
console.log({ User });
console.log(ok);
Thank you Marcosc! Building on his answer, if you want to rename any function, use this:
// returns the function named with the passed name
function namedFunction(name, fn) {
return new Function('fn',
"return function " + name + "(){ return fn.apply(this,arguments)}"
)(fn)
}
function myFunction() {
console.log('It works!');
}
var name = 'myFunction';
window[name].call();
You was near:
this["instance_" + a] = function () {...};
{...};
I might be missing the obvious here, but what's wrong with just adding the name? functions are invoked regardless of their name. names are just used for scoping reasons. if you assign it to a variable, and it's in scope, it can be called. hat happens is your are executing a variable which happens to be a function. if you must have a name for identification reasons when debugging, insert it between the keyword function and the opening brace.
var namedFunction = function namedFunction (a,b) {return a+b};
alert(namedFunction(1,2));
alert(namedFunction.name);
alert(namedFunction.toString());
an alternative approach is to wrap the function in an outer renamed shim, which you can also pass into an outer wrapper, if you don't want to dirty the surrounding namespace. if you are wanting to actually dynamically create the function from strings (which most of these examples do), it's trivial to rename the source to do what you want. if however you want to rename existing functions without affecting their functionality when called elsewhere, a shim is the only way to achieve it.
(function(renamedFunction) {
alert(renamedFunction(1,2));
alert(renamedFunction.name);
alert(renamedFunction.toString());
alert(renamedFunction.apply(this,[1,2]));
})(function renamedFunction(){return namedFunction.apply(this,arguments);});
function namedFunction(a,b){return a+b};
This is BEST solution, better then new Function('return function name(){}')().
Eval is fastest solution:
var name = 'FuncName'
var func = eval("(function " + name + "(){})")

Categories