I have a Javascript snippet like this:
var a = {ac: 10, function(){console.log("hi")}}
The browser is not throwing an error for this. So it may be valid.
But when I use
var a = {ac: 10, function hi(){console.log("hi")}}
The browser throws error:
Uncaught SyntaxError: Unexpected identifier
Can anybody tell me how can I make use of the first code in any scenario in Javascript
Thanks in Advance
What's happening here is that ES6 allows you to have a shorthand syntax for function definitions. This: const obj = { method() {} } basically translates to this const obj = { method: function() {} }.
So, when you use this snippet var a = {ac: 10, function(){console.log("hi")}} you're telling the browser that function is not a reserved word for you inside that object, rather the name of the property that you want to use, so you end up with an object that has a method called function.
Btw, you should avoid this in the future, do not use reserved keywords for another purpose.
In the second snippet var a = {ac: 10, function hi(){console.log("hi")}} what's happening is that you're trying to have a function declaration (function hi(){console.log("hi")}) inside an object, and that's a syntax error. By giving the function a name, you changed from a shorthand syntax for methods declarations inside the object to a function definition. If you use a proper naming (avoiding reserved words) for this shorthand syntax, or declare the function outside and reference it inside the object, you shouldn't have problems.
What you are doing in your first example is called shorthand method names, and is a newer way of initialising functions in js objects. What is actually happening in your example, is it is taking the name of the object key (and the function name) to befunction. But 'function' can be replaced with any key/name. For example:
var a = {
ac: 10,
other() { console.log('inside other') }
}
You can read more about the different ways to initialise an object here: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Object_initializer
The reason why your second example fails, is simply because it is invalid syntax. If you remove the word function from your second example, it will work as I think you were originally expecting it to.
You could try structuring it like this:
var obj = {
ac: 10,
hello: function(){
console.log("Goodbye");
}
}
console.log(obj.ac);
console.log(obj.hello());
Related
How can I access a function name from inside that function?
// parasitic inheritance
var ns.parent.child = function() {
var parent = new ns.parent();
parent.newFunc = function() {
}
return parent;
}
var ns.parent = function() {
// at this point, i want to know who the child is that called the parent
// ie
}
var obj = new ns.parent.child();
In ES6, you can just use myFunction.name.
Note: Beware that some JS minifiers might throw away function names, to compress better; you may need to tweak their settings to avoid that.
In ES5, the best thing to do is:
function functionName(fun) {
var ret = fun.toString();
ret = ret.substr('function '.length);
ret = ret.substr(0, ret.indexOf('('));
return ret;
}
Using Function.caller is non-standard. Function.caller and arguments.callee are both forbidden in strict mode.
Edit: nus's regex based answer below achieves the same thing, but has better performance!
ES6 (inspired by sendy halim's answer below):
myFunction.name
Explanation on MDN. As of 2015 works in nodejs and all major browsers except IE.
Note: On bound functions this will give "bound <originalName>". You will have to strip the "bound " if you want to get the original name.
ES5 (inspired by Vlad's answer):
If you have a reference to the function, you can do:
function functionName( func )
{
// Match:
// - ^ the beginning of the string
// - function the word 'function'
// - \s+ at least some white space
// - ([\w\$]+) capture one or more valid JavaScript identifier characters
// - \s* optionally followed by white space (in theory there won't be any here,
// so if performance is an issue this can be omitted[1]
// - \( followed by an opening brace
//
var result = /^function\s+([\w\$]+)\s*\(/.exec( func.toString() )
return result ? result[ 1 ] : '' // for an anonymous function there won't be a match
}
I have not run unit tests on this, or verified implementation
differences, but in principle it should work, if not leave a comment.
Note: won't work on bound functions
Note: that caller and callee are considered deprecated.
[1] I include it here because it is legal and often enough syntax highlighting tools fail to take into account the white space between function name and parenthesis. On the other hand, I'm not aware of any implementation of .toString() that will include white space here, so that's why you can omit it.
As an answer to the original question, I would drop parasitic inheritance and go for some more traditional OOP design patterns. I wrote a TidBits.OoJs to comfortably write OOP code in JavaScript with a feature set mimicking C++ (not yet complete, but mostly).
I see from the comments that you would like to avoid passing information parent needs to it's constructor. I must admit that traditional design patterns won't save you from that one though, since it is generally a considered a good thing to make your dependencies obvious and enforced.
I would also suggest to steer away from anonymous functions. They only make debugging and profiling a PITA because everything just shows up as "anonymous function", and there is no benefit to them that I'm aware of.
what you're doing is assigning unnamed function to a variable. you probably need named function expression instead ( http://kangax.github.com/nfe/ ).
var x = function x() {
console.log( arguments.callee.name );
}
x();
however I'm not sure how much cross-browser that is; there's an issue with IE6 that makes you function's name leak to the outer scope. also, arguments.callee is kind of deprecated and will result in error if you're using strict mode.
It looks like the most stupid thing, that I wrote in my life, but it's funny :D
function getName(d){
const error = new Error();
const firefoxMatch = (error.stack.split('\n')[0 + d].match(/^.*(?=#)/) || [])[0];
const chromeMatch = ((((error.stack.split('at ') || [])[1 + d] || '').match(/(^|\.| <| )(.*[^(<])( \()/) || [])[2] || '').split('.').pop();
const safariMatch = error.stack.split('\n')[0 + d];
// firefoxMatch ? console.log('firefoxMatch', firefoxMatch) : void 0;
// chromeMatch ? console.log('chromeMatch', chromeMatch) : void 0;
// safariMatch ? console.log('safariMatch', safariMatch) : void 0;
return firefoxMatch || chromeMatch || safariMatch;
}
d - depth of stack. 0 - return this function name, 1 - parent, etc.;
[0 + d] - just for understanding - what happens;
firefoxMatch - works for safari, but I had really a little time for testing, because mac's owner had returned after smoking, and drove me away :'(
Testing:
function limbo(){
for(let i = 0; i < 4; i++){
console.log(getName(i));
}
}
function lust(){
limbo();
}
function gluttony(){
lust();
}
gluttony();
Result:
Chrome:
Fitefox:
This solution was creating only just for fun! Don't use it for real projects. It does not depend on ES specification, it depends only on browser realization. After the next chrome/firefox/safari update it may be broken.
More than that there is no error (ha) processing - if d will be more than stack length - you will get an error;
For other browsers error's message pattern - you will get an error;
It must work for ES6 classes (.split('.').pop()), but you sill can get an error;
Any constructor exposes a property name, which is the function name. You access the constructor via an instance (using new) or a prototype:
function Person() {
console.log(this.constructor.name); //Person
}
var p = new Person();
console.log(p.constructor.name); //Person
console.log(Person.prototype.constructor.name); //Person
This might work for you:
function foo() { bar(); }
function bar() { console.log(bar.caller.name); }
running foo() will output "foo" or undefined if you call from an anonymous function.
It works with constructors too, in which case it would output the name of the calling constructor (eg "Foo").
More info here: https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Function/Caller
They claim it's non-standard, but also that it's supported by all major browsers: Firefox, Safari, Chrome, Opera and IE.
You can't. Functions don't have names according to the standard (though mozilla has such an attribute) - they can only be assigned to variables with names.
Also your comment:
// access fully qualified name (ie "my.namespace.myFunc")
is inside the function my.namespace.myFunc.getFn
What you can do is return the constructor of an object created by new
So you could say
var obj = new my.namespace.myFunc();
console.info(obj.constructor); //my.namespace.myFunc
You could use this, for browsers that support Error.stack (not nearly all, probably)
function WriteSomeShitOut(){
var a = new Error().stack.match(/at (.*?) /);
console.log(a[1]);
}
WriteSomeShitOut();
of course this is for the current function, but you get the idea.
happy drooling while you code
You could use Function.name:
In most implementations of JavaScript, once you have your constructor's reference in scope, you can get its string name from its name property (e.g. Function.name, or Object.constructor.name
You could use Function.callee:
The native arguments.caller method has been deprecated, but most browsers support Function.caller, which will return the actual invoking object (its body of code):
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/caller?redirectlocale=en-US&redirectslug=JavaScript%2FReference%2FGlobal_Objects%2FFunction%2Fcaller
You could create a source map:
If what you need is the literal function signature (the "name" of it) and not the object itself, you might have to resort to something a little more customized, like creating an array reference of the API string values you'll need to access frequently. You can map them together using Object.keys() and your array of strings
You can use name property to get the function name, unless you're using an anonymous function
For example:
var Person = function Person () {
this.someMethod = function () {};
};
Person.prototype.getSomeMethodName = function () {
return this.someMethod.name;
};
var p = new Person();
// will return "", because someMethod is assigned with anonymous function
console.log(p.getSomeMethodName());
now let's try with named function
var Person = function Person () {
this.someMethod = function someMethod() {};
};
now you can use
// will return "someMethod"
p.getSomeMethodName()
You can use constructor name like:
{your_function}.prototype.constructor.name
this code simply return name of a method.
as part as ECMAScript 6 you can use Function.name method
function doSomething() {}
alert(doSomething.name); // alerts "doSomething"
I know this is a old question but lately I've been facing some similar issue while trying to decorate some React Component's methods, for debugging purposes. As people already said, arguments.caller and arguments.callee are forbidden in strict mode which is probably enabled by default in your React transpiling. You can either disable it, or I've been able to come up with another hack, because in React all class functions are named, you can actually do this:
Component.prototype.componentWillMount = function componentWillMount() {
console.log('Callee name: ', this.__proto__.constructor.toString().substr(0,30));
...
}
This worked for me.
function AbstractDomainClass() {
this.className = function() {
if (!this.$className) {
var className = this.constructor.toString();
className = className.substr('function '.length);
className = className.substr(0, className.indexOf('('));
this.$className = className;
}
return this.$className;
}
}
Test code:
var obj = new AbstractDomainClass();
expect(obj.className()).toBe('AbstractDomainClass');
I had a similar problem and I solved it as follows:
Function.prototype.myname = function() {
return this.toString()
.substr( 0, this.toString().indexOf( "(" ) )
.replace( "function ", "" );
}
This code implements, in a more comfortable fashion, one response I already read here at the top of this discussion.
Now I have a member function retrieving the name of any function object.
Here's the full script ...
<script language="javascript" TYPE="text/javascript">
Function.prototype.myname = function() {
return this.toString()
.substr( 0, this.toString().indexOf( "(" ) )
.replace("function ", "" );
}
function call_this( _fn ) { document.write( _fn.myname() ); }
function _yeaaahhh() { /* do something */ }
call_this( _yeaaahhh );
</script>
If I understood what you wanted to do, this is what I do inside a function constructor.
if (!(this instanceof arguments.callee)) {
throw "ReferenceError: " + arguments.callee.name + " is not defined";
}
This will work in ES5, ES6, all browsers and strict mode functions.
Here's how it looks with a named function.
(function myName() {
console.log(new Error().stack.split(/\r\n|\r|\n/g)[1].trim());
})();
at myName (<anonymous>:2:15)
Here's how it looks with an anonymous function.
(() => {
console.log(new Error().stack.split(/\r\n|\r|\n/g)[1].trim());
})();
at <anonymous>:2:15
A simple solution to dynamically retrieve function names [like magic variables] is the use of scoped variables.
{
function parent() {
console.log(a.name);
}; let a = parent
}
{
function child() {
console.log(a.name)
}; let a = child
};
parent();//logs parent
child();//logs child
Note: Nested functions cease to be source elements, and are hence not hoisted.
Also, this technique cannot work with anonymous functions.
Just try Function.name
const func1 = function() {};
const object = {
func2: function() {}
};
console.log(func1.name);
// expected output: "func1"
console.log(object.func2.name);
// expected output: "func2"
look here: http://www.tek-tips.com/viewthread.cfm?qid=1209619
arguments.callee.toString();
seems to be right for your needs.
Easy way to get function name from within fuction you are running.
function x(){alert(this.name)};x()
you can use Error.stack to trace the function name and exact position of where you are in it.
See stacktrace.js
I'm writing an API and I need to execute a ternary inside a "getter" function for various fields. This works fine but I don't want the end user to have to use parentheses when accessing these fields.
Strangely the getter code actually executes when I access the field without the parentheses but I'm wondering if this is normal for javascript or if this is browser dependent? Currently using Firefox 31.
This works:
var theScript = Scripts.jQuery_1_11_1_js(); // Note I'm using the parentheses
This also works even without parentheses. How?:
var theScript = Scripts.jQuery_1_11_1_js; // Note the lack of parentheses
Example API:
var Scripts = (function () {
function Scripts() {
}
Scripts.isProduction = false;
Scripts.Url = "/Scripts";
Scripts.jQuery_1_11_1_js = function () {
return Scripts.isProduction ? Scripts.Url + "/jQuery_1_11_1.min.js" : Scripts.Url + "/jQuery_1_11_1.js";
}
return Scripts;
})();
var theScript = Scripts.jQuery_1_11_1_js();
var theScript = Scripts.jQuery_1_11_1_js; /// why does this work?
This also works even without parentheses. How?:
var theScript = Scripts.jQuery_1_11_1_js; // Note the lack of parentheses
No, it doesn't. The line executes just fine, but it doesn't call Scripts.jQuery_1_11_1_js, it just sets the value of theScript to a reference to the function Scripts.jQuery_1_11_1_js.
There are only two four (as of ES2015) ways I know of to call a function without parentheses:
Define the property on Scripts as an ES5 getter. Here's the ES5 syntax for doing that:
Object.defineProperty(Scripts, "jQuery_1_11_1_js", {
get: function() {
return Scripts.isProduction ? Scripts.Url + "/jQuery_1_11_1.min.js" : Scripts.Url + "/jQuery_1_11_1.js";
}
});
Now, the line
var theScript = Scripts.jQuery_1_11_1_js;
...will call that anonymous function we defined as the getter for the property.
Unfortunately, you can't do that in IE8. In IE8 (bizarrely), Object.defineProperty can only create properties on DOM elements, not normal objects. IE9 supports it properly.
Just for completeness, there is a second way, with new:
var foo = new Foo;
...which is equivalent to
var foo = new Foo();
But of course, you don't want to do that unless Foo is meant to be a constructor function, as it creates an object to pass to Foo as this.
Calling a tag function:
someFunction`template contents here`;
That doesn't look like a function call, but it is. It parses the template, evalutes any token expressions, and passes the raw form of the template (an array of strings with an added raw property, subsequent arguments for the token substitutions) into someFunction. Whereas someFunction(`template contents here`) would evaluate the template, evaluate any token expressions, and substitute them into the template producing a string, and then pass the string into someFunction. More on MDN.
Do just about anything on a Proxy object, since all the fundamental object operations (getting properties, setting properties, defining properties, getting its prototype, etc., etc.) can be trapped on proxies, generating a call to a trap handler.
There are different ways of defining the javascript functions. I often use the simplest way to define the function
function myfunc(){
}
and the next way to define the function in the variable like this (a little bit confusing the way of using)
var myvar = myfunc(){
/*some code*/
}
and the difficult way for me and mostly found in codes developed by advanced programmers like the following
var SqueezeBox={presets:{onOpen:function(){},onClose:function(){}}
Please, can anyone clear my concept on this how can I use?
function myfunc(){}
Function declaration: the function is declared using the standard syntax
function functionName(params[]) {
//functionbody
}
Using this syntax declares the function at the begin of the scope execution, so they'll be available everywhere in their scope(and in their descendeant scopes).
var s = myfunc(); //s == 0
function myfunc() {return 0;}
var myfunc = function() {};
This uses the pattern known as function expression, it just assigns a reference of an anonymous function to a variable named myfunc. Using this syntax won't allow you to use the function until the variable is parsed. Even if variables are hoisted at the top of their scope, they're initialized when the interpreter parses them, so the above example won't work:
var s = myfunc(); //ReferenceError: myfunc is not defined
var myfunc = function() {return 0;};
But the example below will:
var myfunc = function() {return 0;};
var s = myfunc(); //s == 0
The third example is just assigning an anonymous function to an object property(also known as object method) in the way we've just done with function expression, so if I use the pattern above the code will become:
var onOpen = function() {},
onClose = function() {},
SqueezeBox = {//curly braces denotes an object literal
presets: {//again, this is a nested object literal
onOpen: onOpen,
onClose: onClose
}
};
This acts exactly the same as your example, with the only difference that here I used a variable to get a reference to the anonymous function before passing it to the object. If you need to know more about objects, I recommend you reading the MDN docs. Anyway, if you're really intrested in how JS works, I'd suggest Javascript Garden, which is a very good article about JS.
The first code snippet is a function declaration:
function myfunc() { }
You are declaring a named function called myfunc. You can verify this by myfunc.name === "myfunc"
Your second code snippet contains syntax error. I believe you meant:
var myvar = function() { };
This is an anonymous function expression assigned to a variable. You can verify this by typeof myvar === "function" and myvar.name === "".
The third snippet is a javascript object. Basically you can think of it as a Map or Dictionary<string, object>. So SqueezeBox contains 1 key presets, which in turn is a dictionary that contains 2 keys, onOpen and onClose, which both of them are anonymous functions.
In
var SqueezeBox={presets:{onOpen:function(){},onClose:function(){}}}
He's creating an object SqueezeBox containing another object presets with two empty anonymous functions, he's defining the function inline with an empty body inside the {}.
A better way to see it is formatted this way:
var SqueezeBox={
presets:{
onOpen:function(){/* empty function body */},
onClose:function(){/*empty function body */}
}
}
There is a lot of useful information on this subject here
Functions can have a name, which if specified cannot be changed. Functions can also be assigned to variables like any other object in javascript.
The first example is of a function declaration:
function myfunc(){
}
Using the function declaration you will be able to call the function from anywhere within the closure in which the function is declared, even if it is declared after it is used.
The other two examples are function expressions:
var myvar = function(){
/*some code*/
}
var SqueezeBox= {
presets: {
onOpen:function(){/* empty function body */},
onClose:function(){/*empty function body */}
}
}
Using function expressions you are assigning functions to a variable. When doing this you must declare them before you use them. Most of the time you see this the functions will be anonymous but it is possible to name a function in an expression:
var myvar = function myFunc(){
myFunc(); // Because it has a name you can now call it recursively
}
When doing this, the myFunc function is only available within the body of the function because it is still a function expression rather than a declaration.
The third example declares a javascript object literal, SqueezeBox and within that object there is another called presets. Within this object there are two more objects/labels called onOpen and onClose. This means you can do the following to use these functions:
SqueezeBox.presets.onOpen();
SqueezeBox.presets.onClose();
You can think of onOpen and onClose as variables that are part of the object. So it's very similar to doing the following (but the variable is only in the scope of the presets object which is only available within the SqueezeBox object).
var onOpen = function() {};
This has already been answered here: What is the difference between a function expression vs declaration in Javascript?.
For the last example, as Atropo said, it's affecting an anonymous function to an object. It's similar to the var example.
var a = {
text : 3,
logText : function () {
console.log(this.text);
},
callLogText : function() {
logText();
}
};
a.callLogText();
This will genernate a ReferenceError: logText is not defined error message.
Instead, you prefix this to the logText() method, it will be ok. No error msg will pop.
var a = {
text : 3,
logText : function () {
console.log(this.text);
},
callLogText : function() {
this.logText();
}
};
I really cant figure out the reason.
You need to learn the JavaScript scoping rules. This blog post gives a good introduction.
In a nutshell, JavaScript follows some rules when you use a variable name (for the purpose of this explanations, function definitions are pretty much like variable declarations).
What probably confuses you is this:
var a = { b: ...};
var a = function() { var b = ... }
In both cases, you get a new variable a. In the first case, it's an object with a property b. In the second case, it's a function which has a nested scope in which a new variable b is defined.
JavaScript will look in the current and all parent scopes for variables. But object definitions are no scopes. As far as JavaScript is concerned, the property b is invisible unless you make it visible by using the special variable this which always references the "current" object (in your example, that is a).
Since the properties of the object a are not "in scope", JavaScript can't find logText() unless you tell it to look in this. If you don't say anything, JavaScript will look in the current scope (the body of the function callLogText), then the parent scope (in which a is defined) and then in any parent scopes of that.
It's not a quirk. It's how most languages function when it comes to objects.
logText() is a method of the a object, not a function.
You need to call methods internally as this.methodName() or externally as object.methodName().
logText(); is to execute a global function logText which is undefined.
this.logText(); is to execute the function a.logText.
Calling
logText();
means somewhere there is a function named logText(), but here you have defined logText() as a property of an object, so to access the logText() you have to refer it with the help of the object it is defined in. In this case it is in the same object so you refer to the same object by saying this.
I've opened jQuery 1.7.1 library and wanted to study the code, but I've found a that functions are declared in strange way (for me). For example:
show: function() {
//some code here
},
I learned to define function on this way:
function show() {
//some code here
}
Can someone explain me why show function is not written on second way (like in most tutorials on internet)?
This is because it is within an object. Object Literals have their properties defined in this way:
{
name: value,
//OR
'name': value
}
Where value can be nearly anything such as a number, string, function, or even another object. In JavaScript you can also declare anonymous functions and assign them to a variable. In fact, the following declarations have the same effect:
//declares the myFunc1 function
function myFunc1() {}
//declares an anonymous function and assigns it to myFunc2
var myFunc2 = function() {};
//you can now call either like so:
myFunc1();
myFunc2();
So, combining those two concepts if I have an object and I want one of its properties to be a function I would do it like so:
var myObj = {
name: 'My Object',
init: function() {
return 'Initializing!';
},
version: 1.0
};
alert(myObj.init());
You would then get the output: Initializing!. Make sure to check out the great documentation and tutorials on the Mozilla Developer Network, including their JavaScript Tutorial Series
Hope this helps!
Writing it the first way is in essence, setting a function as property of an object.
For example:
// I can create a new empty object
var myObject = {};
// or I can create a new object with a basic property
var myObject = {
color: "blue"
};
// I can also create an object with methods (like jQuery)
var myObject = {
color: "blue",
showColor: function(){
alert(this.color);
}
};
// and you can use the object like this
myObject.showColor(); // calls the showColor method and will alert "blue"
This helps jQuery to encapsulate, namespace, and organize code.
Here are a couple of pretty good write-ups:
Why do you need to invoke an anonymous function on the same line?
http://en.wikibooks.org/wiki/JavaScript/Anonymous_Functions
http://www.evotech.net/blog/2008/07/javascript-object-literals-a-definition/
The first declaration, i.e., show: function, defines show to be a field in an object having type function. The second declares a function named show within the current scope (possibly global?)
they're being described as a js object function. In this case:
var jQuery = {
show: function(){
//some code here
}
}
so you access it like jQuery.show() for example.
I would say Chad's answer is most accurate for in depth research. You should look into them as they can revolutionize how you write js in a very clean way that is much less likely to conflict with other libraries.