How can I get the key name "email" inside the function ? Is there a special context variable to do this ?
Thanks for help.
var user = {
"email": function() {
// How can I get the name of the key (email) inside the function ?
}
}
A relatively new feature of JS will assign a name to an anonymous function expression based on the variable or property to which it is initially assigned.
You can access a function's name via arguments.callee.name
var bar = {
baz: function() {
console.log(arguments.callee.name);
}
}
bar.baz();
Of course, if you copy the function elsewhere, it won't get a new name. The name is given to it at the time it is created.
var bar = {
baz: function() {
console.log(arguments.callee.name);
}
}
bar.foo = bar.baz;
bar.foo();
I will answer this by asking a question. Consider this scenario:
let myFunc = function(){ /* somehow returns the name */ };
let a = {
funcA: myFunc
};
let b = {
funcB: myFunc
};
Now, consider this:
a.funcA();
b.funcB();
What should they return? myFunc, funcA, or funcB? The answer is "it doesn't make sense".
This is why what you are trying to do is impossible. The function can be "owned" by different objects.
Related
I have a function which has other functions defined:
var A = function(n) {
console.log(n + A.num());
}
A.num = function() {
return 5;
}
I want to change the name to B and delete A:
var B = A;
A = undefined;
But, when I do B(), It gives an error throws: "Cannot read property 'num' of undefined", which is completely normal and expected.
How do I handle this?
PS: Anyone who thinks that changing A.num() with this.num(), It will not work
You can always refer to the current function using its explicit name (if it has one).
So, change the definition, to name the function, and refer to it using that:
var A = function currentFunction(n) {
console.log(n + currentFunction.num());
}
A.num = function() {
return 5;
}
var B = A;
A = undefined;
B(10); //15
console.log(typeof currentFunction) //undefined, function name is local
Note: the abovementioned approach won't work if the function is named implicitly, but will continue to work if the function is renamed via fn.name
Alternatively, if the function isn't an arrow function, you can also use arguments.callee, that will work even with anonymous functions, but its use isn't recommended:
var A = function (n) {
console.log(n + arguments.callee.num());
}
A.num = function() {
return 5;
}
var B = A;
A = undefined;
B(10); //15
Unfortunately, none of the above will work with arrow functions, if you want to refer to itself, use a named bound function expression instead.
actually that's normal, because in js you can't really copy object
// Define object bar
var bar = {
x : 'Hi'
}
console.log(bar.x); //Hi
// Assign it to foo
var foo = bar;
console.log(foo.x); //Hi
//But
foo.x = 'Hello!! Im foo.';
console.log(foo.x); //Hello!! Im foo.
console.log(bar.x); //Hello!! Im foo.
bar.x = "Nice to meet you foo!!";
console.log(foo.x); //Nice to meet you foo!!
console.log(bar.x); //Nice to meet you foo!!
you have to return a new one with the same value as the last
var foo = {...bar};
and this is not working because B is always calling 'num' from A that doesn't exist, One way to sever the parity would be stringify the initial function, then use a function constructor to create the clone after replacing the 'A' by 'B'
but tell me more why are you facing this problem ?
var A = function(n) {
if(!this.num){
console.log("This is not available coz obj is not created");
console.log("Below error is for testing purpose");
}
let a=this.num(n);
console.log(a);
}
//use prototype here
//A.num = function() {
A.prototype.num=function(n){
return n+5;
}
//use new to create object
new A(5);
var B = A;
A = undefined;
//use new to create object
new B(6);
B(5);//lets try without using new keyword
.as-console-wrapper { max-height: 100% !important; top: 0; }
I am developing a widget inside a framework so that I would need to log variable "a" using a pattern like the one below. How do I "call" this function log_a so it can access the variable declared in the execution context it is called from? i.e. Have the console output "a value", instead of the current error of not able to find variable "a".
(function(global) {
global.log_a = function() {
console.log(a);
};
}(window));
var anotherFunction = function() {
var a = 'a value';
log_a();
};
anotherFunction();
edit:
I tried to make the example simple to make the question easier to follow but I now see it led to confusion. Update with more clarifications:
The first part of the code is trying to emulate my effort of moving large functions to a different file for cleaner code.
I am using a library where one input is a function and it will always pass one parameter to it, so I have no option of adding extra arguments (i.e. the answers suggesting to put "a" as an argument).
The trick of declaring "a" as global works and it is what I am currently using, but I thought this wasn't the best practice.
So my questions is (I am guessing the answer is "it is not possible") if there is some way to call log_a so it behaves like if the code was like this:
var anotherFunction = function() {
var a = 'a value';
var log_a = function() {
console.log(a);
};
};
anotherFunction();
You can use function arguments to pass the value of a to your log_a method. The issue that you are currently happening is that var a = 'a value' is unknown to the log_a as it is defined within another function. This is because a variable declared with var in a function scope cannot be accessed outside that function scope. Thus, you are better of doing something such as the following:
(function(global) {
global.log_a = function(a) { // retrieve 'a' as an argument in the log_a method
console.log(a); // print the argument passed through
};
}(window));
var anotherFunction = function() {
var a = 'a value';
log_a(a); // pass through 'a' into the `log_a` method
};
anotherFunction();
You can pass variable a value from that function so log_a() function can access that variable value.
(function(global) {
global.log_a = function(a){
console.log(a);
};
}(window));
var anotherFunction = function() {
var a = 'a value';
log_a(a);
};
anotherFunction();
Variable a exists only in the scope of function anotherFunction;
(function(global) {
global.log_a = function() {
console.log(a);
};
}(window));
var anotherFunction = function() {
// var a exists only here, inside this function
var a = 'a value';
// log_a is another function, it has its own scope,
// and it doesn't know about var a
log_a();
};
anotherFunction();
You can either pass the variable a as an argument to log_a, like log_a(a) inside anotherFunction, or make the variable a available to both anotherFunction and log_a functions:
var a = 'a value';
(function(global) {
global.log_a = function() {
console.log(a);
};
}(window));
var anotherFunction = function() {
log_a();
};
anotherFunction();
I need the current function name as a string to log to our log facility. But arguments.callee.name only works in loose mode. How to get the function name under "use strict"?
For logging/debugging purposes, you can create a new Error object in the logger and inspect its .stack property, e.g.
function logIt(message) {
var stack = new Error().stack,
caller = stack.split('\n')[2].trim();
console.log(caller + ":" + message);
}
function a(b) {
b()
}
a(function xyz() {
logIt('hello');
});
You can bind function as its context then you can access its name via this.nameproperty:
function x(){
console.log(this.name);
}
x.bind(x)();
After little research here is a good solution :
function getFnName(fn) {
var f = typeof fn == 'function';
var s = f && ((fn.name && ['', fn.name]) || fn.toString().match(/function ([^\(]+)/));
return (!f && 'not a function') || (s && s[1] || 'anonymous');
}
function test(){
console.log(getFnName(this));
}
test = test.bind(test);
test(); // 'test'
Source : https://gist.github.com/dfkaye/6384439
Building on #georg solution, this one returns just the function name. Note though that it may fail if called from an anonymous function
function getFncName() {
const stackLine = (new Error())!.stack!.split('\n')[2].trim()
const fncName = stackLine.match(/at Object.([^ ]+)/)?.[1]
return fncName
}
function Foo() {
console.log(getFncName()) // prints 'Foo'
}
A simple solution to dynamically retrieve function names [like magic variables] is the use of scoped variables, and the Function.name property.
{
function foo() {
alert (a.name);
}; let a = foo
}
{
function foo2() {
alert(a.name)
}; let a = foo2
};
foo();//logs foo
foo2();//logs foo2
Note: Nested functions cease to be source elements, and are hence not hoisted. Also, this technique cannot work with anonymous functions.
If (like me) you want to define this elsewhere and call it generically, you can store the code as a string somewhere global or import it, then eval() it wherever to access the current function name. (Using eval keeps the context at the point of invocation.)
There's gotta be a way to do this without using a string, but whatever.
SomeObject.whatFunc =
'const s = new Error().stack;' +
"const stackLine = new Error().stack.split('\\n')[2].trim();" +
'const fncName = stackLine.match(/(?<=at )(.*)(?= \\()/gm)[0];' +
'console.log(fncName);'
// Whereever you want the func name
function countBananas('weeee') {
eval(SomeObject.whatFunc)
// blah blah blah
}
countBananas() // logs 'countBananas'
just an update to get the full name :
function logIt(message) {
var stack = new Error().stack,
// update is on this line
caller = stack.split('\n')[2].trim().split(/\s+/)[1];
console.log(caller.trim().split(/\s+/)[1];);
}
function a(b) {
b()
}
a(function xyz() {
logIt('hello');
});
Basically I want to do this:
someFunction() // do something
someFunction.somePropertyFunction()
someFunction() // Now someFunction is modified; it should now exhibit a different behaviour
Is this possible?
EDIT:
I'm not looking for what #Kolink was suggesting. Basically I want to augment a function's functionality by calling one of it's property function.
Specifically, I need to: 1. have access to the original function inside my property function (which is entirely doable using this), and 2. bind a new function to the original function's name (which I'm not sure if it's possible).
Just to be clear, I don't have access to the internal definition of the function that I want to augment. I want to attach a function to Function.prototype (so that it will be available as a property of the function that I want to augment), and then I will call func.augmentThis(), and then func should be augmented. But I'm not sure how, hence the question :P
Easily. Here's an example:
var derp = 123;
someFunction = function() {alert(derp);};
someFunction.somePropertyFunction = function() {derp = 456;};
someFunction(); // alerts 123
someFunction.somePropertyFunction();
someFunction(); // alerts 456
Okay, that's an oversimplified example, but yeah, it's entirely possible.
If your question is whether a function attached as a property to another function has a way to access the function to which it is attached, the answer is no. After all, the same function could be attached to any number of functions of objects.
So one alternative is to explicitly refer to the "mother" function within the function that is attached to it and intended to change its behavior:
function f (n) { alert (n + f.offset); }
f.offset = 0;
f.change_offset = function (i) { f.offset = i; };
f (1); //1
f.change_offset (100);
f (1); //101
Here, f is hard-wired into the definition of change_offset. If this bothers you, or you want something slightly more general, write a little routine to set a function as a property on another function, while binding its this to the function being attached to:
function set_func_as_func_prop ( propname, func_to_set, func_to_set_on ) {
func_to_set_on[propname] = func_to_set.bind(func_to_set_on);
}
Now you can write the function more generally
function change_offset (i) {
this.offset = i;
}
and set it on f or any other function.
set_func_as_func_prop ("change_offset", change_offset, f);
set_func_as_func_prop ("change_offset", change_offset, g);
Sort of:
function someFunction() {
return realFunction.apply(this, arguments);
}
function someFunctionA(name) {
return 'Hello, ' + name + '!';
}
function someFunctionB(name) {
return 'Goodbye, ' + name + '...';
}
var realFunction = someFunctionA;
someFunction.somePropertyFunction = function () {
realFunction = someFunctionB;
};
Sure it's possible. It's not recommended, but it's possible. For example:
function a() {
alert("a");
}
function b() {
alert("b");
}
function c() {
return c.f.apply(this, arguments);
}
c.f = a;
c.toggle = function () {
c.f = c.f === a ? b : a;
};
Now let's test it:
c(); // alerts "a"
c.toggle();
c(); // alerts "b"
See the demo: http://jsfiddle.net/LwKM3/
I want to attach a function to Function.prototype. Then I need to bind a new function to the original function's name (which I'm not sure if it's possible).
That indeed is impossible, you don't know what refers to the function. And you cannot change the internal representation of a function, which is immutable.
The only thing you can do is to create a new function and return that, to let the caller of your method use it somehow - specifically assigning it to the original variable:
somefunction = somefunction.augmentSomehow();
Your method for that will look like this:
Function.prototype.augmentSomehow = function() {
var origFn = this;
return function() {
// in here, do something special
// which might include invoking origFn() in a different way
};
};
Not sure if this helps, but I would implement described problem in following way:
// defined by somebody else - unknown to developer
var someFunction = function() {
alert("this is initial behavior");
}
someFunction(); // returns "this is initial behavior"
// defines parent object on which someFunction() is called
var parentObject = this; // returns window object (as called direclty in the
// browser)
// if you are calling someFunction from some object (object.someFunction())
// it would be:
// var parentObject = object;
// augumentThis definition
someFunction.augumentThis = function() {
var newFunction = function() {
alert("this is changed behavior");
};
parentObject.someFunction.somePropertyFunction = function() {
parentObject.someFunction = newFunction;
parentObject.someFunction();
};
};
someFunction.augumentThis(); // change function behavior
someFunction(); // "this is initial behavior"
someFunction.somePropertyFunction(); // "this is changed behavior"
someFunction(); // "this is changed behavior"
When we make an object like this
function myObject(){
Properties and methods here----
};
We write “function” keyword before name of object is it necessary? All objects are functions in real? Can we not write direct object name like this?
myObject(){
Properties and methods here----
};
No, not all objects are functions. (All functions are objects, though.)
Here, obj isn't a function:
var obj = {
foo: "bar"
};
Nor dt here:
var dt = new Date();
The function keyword is necessary in order to say "what follows is a function declaration or function expression." It's just part of the basic syntax of JavaScript.
in the first case, the function can be used as the constructor for an object. So you can have:
function Person(name) {
this.name = name
}
Person.prototype = {
// methods can go in here
}
person1 = new Person("bob");
alert(person1.name) // alerts "bob"
It is also true that you can use a function as an object. For example:
function myObject() {
return myObject.test;
}
myObject.test = "bob";
alert(myObject()) // would alert "bob"
but all objects are not functions.
var someObject = {
name: "bob",
moody: "sad"
}
alert(someObject.name); // alerts "bob"
try {
someObject();
} catch (er) {
alert(er); // alerts "TypeError: object is not a function"
}
I'd suggest you take a look at https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Function
One reason is obviously disambiguity;
function foo()
{
alert("cake")
}
foo()
{
alert("burb");
}
foo();
alerts cake, burb, cake as the 2nd foo() {...} is just a regular function call followed by a regular compound statement enclosed in {}.
function declares a function. Because of the way JavaScript works, a function can be used as a class, to make objects.
But if you really just want an object, use squiggly braces, like this:
var myObject = {
x : 30, // a property
getX : function() { // a method
return this.x;
}
}
But your understanding of JavaScript needs a lot of work: read a few books about it.
In Javascript we can create objects in various ways:
1) Literals
let employee = {"name": "tyrion","age":34}
2) Constructor functions(functions having this)
function employee(name, age) {
this.name = name;
this.age = age;
}
let specificEmployee = new employee("tyrion",34);
Constructor function always need to have a new operator to create a object
3) Using Object constructor
let employee = Object.create(null);
employee.name = "tyrion";
employee.age = 34
In javascript every thing other than primitive type is an instance inherited from Object constructor.
No it's not required. You can also have:
var myObject = {
Prop1: "Value1",
Prop2: "Value2",
Method1: function() {
alert("hello");
}
};
Live test case: http://jsfiddle.net/rKunx/
You can write:
myObject = {
Properties and methods here----
}
If you want to avoid the function keyword as much as possible in Java you could use classes:
class Person {
name;
setName(name) {
this.name = name;
this.doStuff();
}
doStuff() {
//...
}
}
The obvious disadvantage to using classes though is that any property or function has to be accessed with this. An advantage of this keyword is that it is clear to know that you are referring to a class property or function and not a local one within the function.
Some people use a var or let in the top:
setName(name) {
let t = this;
t.name = name;
t.doStuff();
}
Still, many prefer to use a function to define some kind of class instead since that does not need this in order to reach the properties which are just variables in the scope of the function. Put inside a module you will still be able to contain these in much the same way you would a class.
If I could make a wish for the future of Javascript it would be to find some way that this is implicitly referring to the class in some way to have a smaller code style with less tokens and easier readability.