method name not conflict with property name in JS - javascript

I am new to JS. While seeing this code:
var obj = {
foo : function foo(){console.log("foo");}
}
I was wondering why the 2 foo names did not create conflict ?

The first one is the key name, and the other one is the function name:
var obj = {
foo : function foo(){console.log("foo");}
// ^ ^
// Key Name
} | |
v |
obj.foo.name <-----+
// => foo
It is something similar to:
function foo () {console.log("foo");}
var obj = { foo: foo }
// or simply
var obj = { foo }
Function.name
A Function object's read-only name property indicates the function's name as specified when it was created, or it may be rather anonymous or ''(an empty string) for functions created anonymously.

Related

What different between assigning property on Object and Object.prototype?

What different between assigning property on Object and Object.prototype?
for example
Object.test =function(){};
and
Object.prototype.test =function(){}
The first gives Object a static method that can be invoked directly from the class, without an instance. For example:
Object.test =function(){
console.log('Object test running');
};
Object.test();
Assigning a function to the prototype, on the other hand, allows for instances to run the method:
Object.prototype.test = function() {
console.log('test running on object ', this);
};
// don't use the object constructor, this is just an example:
const obj = new Object();
obj.test();
It might make a bit more sense if you didn't use the built-in Object, which everything inherits from:
function Foo() {}
Foo.checkIfFoo = function(arg) {
return arg instanceof Foo;
};
const f = new Foo();
console.log(Foo.checkIfFoo(f));
Here, foo.checkIfFoo is a helper function on Foo that checks if a passed object is an instance of Foo or not - no instance is required to run checkIfFoo. Functions on the prototype, on the other hand, require an instance to run:
function Foo() {
this.info = 'A Foo instance';
}
Foo.prototype.checkInfo = function() {
console.log(this.info);
};
const f = new Foo();
f.checkInfo();
Note that in ES6+, you can put a function directly on the class with the static keyword:
// roughly equivalent to the snippet with checkIfFoo above
class Foo {
static checkIfFoo(arg) {
return arg instanceof Foo;
}
}
const f = new Foo();
console.log(Foo.checkIfFoo(f));
Whereas a standard method lacks the static keyword:
// roughly equivalent to the snippet with checkInfo above
class Foo {
constructor() {
this.info = 'A Foo instance';
}
checkInfo() {
console.log(this.info);
}
}
const f = new Foo();
f.checkInfo();

Get key name from the property of javascript object

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.

Is it possible to get name property of a function without using new using ES6 in strict mode? [duplicate]

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');
});

Pass an object literal to an object with a variable name inside a function

This is just an example:
var foo = "foo1";
fooFunction({
bar: {
foo : value
}
});
The property will be named foo instead of foo1.
How can I make it be called foo1?
You cannot specify a dynamic property name in an object literal, you would have to add the property after the object is created.
var foo = "foo1";
var obj = {
bar: {}
};
obj.bar[foo] = value;
function(obj);
There's nothing special about an object literal when used as an input to a function call. The rules of object literals apply wherever it is used, including assignment, input parameters, destructing (ES2015) or any other usage I might have left out.
It is possible using ES2015 to do this with a slight change:
var foo = "foo1";
fooFunction({
bar: {
[foo] : value
}
});
This is called computed property name.

Referring to previously defined properties within an object literal

When using object constructors, properties can be directly assigned to the value of previously defined properties:
var foo = new (function() {
this.bar = 5;
this.baz = this.bar;
})();
alert(foo.baz) // 5
I would like to refer to a previously defined property within an OBJECT LITERAL:
var foo = {
bar : 5,
baz : bar
}
alert (foo.baz) // I want 5, but evaluates to undefined
I know that I could do this:
var foo = {
bar : 5,
baz : function() {
alert(this.bar); // 5
}
But I want to assign baz directly to a value rather than a function. Any ideas?
No, you won't be able to use any properties of the object literal before it has been created. Your closest option is probably to use a temporary variable like so:
var tmp = 5,
foo = {
bar : tmp,
baz : tmp
}
If you are free to use ECMAScript 5 features, you could write a getter function for the baz property that instead returns the value of bar:
var yourObject = {
bar: 5
};
Object.defineProperty(yourObject, 'baz', {
get: function () { return yourObject.bar; }
});
You can also just build a literal by parts:
var foo = {bar:5};
foo.baz = foo.bar;
If you need to fit this inside an expression (instead of through multiple statements) you can try abusing the comma operator or you can make a helper function:
(Warning: untested code)
function make_fancy_object(base_object, copies_to_make){
var i, copy_from, copy_to_list;
for(copy_from in copies_to_make){
if(copies_to_make.hasOwnProperty(copy_from)){
copy_to_list = copies_to_make[copy_from];
for(var i=0; i<copy_to_list.length; i++){
base_object[copy_to_list[i]] = base_object[copy_from];
}
}
}
}
var foo = make_fancy_object(
{bar: 5},
{bar: ["baz", "biv"]}
);
//foo.baz and foo.biv should be 5 now as well.

Categories

Resources