How to assign to members of a function? - javascript

Since functions are first class objects, it should be possible to assign to the members of them.
Am I right thinking that arguments.callee does this?
Are there any other ways to set these fields?
How is it possible to set field in first case?
function something1() {
arguments.callee.field = 12;
}
alert(something1.field); // will show undefined
something1();
alert(something1.filed); // will show 12
something2 = function() {
arguments.callee.field = 12;
};
alert(something2.field); // will show undefined
something2();
alert(something2.field); // will show 12
UPDATE 1
I mean how to access members from within function when it runs.

You don't need to use arguments.callee to refer to a function that has a name; you can just use the name. This is naturally the case when you declare the function using the
function name(...) { ... }
syntax; but even in a function expression, you're allowed to supply a temporary name:
(function temp_name(...) { ... })(arg);
So, if you want to set the properties from inside the function, you can write:
function something1() {
something1.field = 12;
}
alert(something1.field); // will show undefined
something1();
alert(something1.field); // will show 12
something2 = function something2() { // note the second "something2"
something2.field = 12;
};
alert(something2.field); // will show undefined
something2();
alert(something2.field); // will show 12

Here's how I would do it:
function something1() {
this.field = 12;
}
var test = new something1();
alert(test.field); // alerts "12"
test.field = 42;
alert(test.field); // alerts "42"
If you're going to treat it like a class, you need to create a new instance of it before you can access its fields.
JSFiddle

Am I right thinking that arguments.callee does this?
Yes it did, but now they deprecated it.
Are there any other ways to set these fields?
The official way to replace callee is to use an explicit function name, as in funcName.propertyName=.... This is however not always convenient, for example, with dynamically generated functions. To quote John Resig, we're going to miss arguments.callee, it was quite useful for specific tasks.

Simple
function something1() {};
something1.Property = "Foo";
You can directly assign the properties to any function just like a normal object. If to say in OOP language create static properties and methods.
Edit
The same inside the function
function something1() {
something1.AnotherProp = "Bar";
};
something1.Property = "Foo";

Related

Get the variable name based on the methods that it was called from JavaScript?

class Foo {
constructor(name) {
this.name = name;
}
sayHello() {
// get the name of the class here which is defined as bar
console.log(`Hello ${this.name}`)
}
}
var bar = new Foo("John");
bar.sayHello();
Here, as you can see there is a defined class called Foo and it has a method associated with it called, sayHello. So, when I called this method, like bar.sayHello();, how can I get the access to the variable name which is bar. I know that bar.constructor.name would return me Foo as the name, but I am looking for the way to get the name bar. How can I do it in JavaScript.
Thank You.
Javascript doesn't allow variable names to be accessed. You simply cannot get the variable name from the actual value of the variable in a reliable manner, nor should you have to in the first place. However, if you really need to for some inexplicable reason, and you're using browser javascript, you can just scan the window object (note that this will only work if your variable isn't a primitive).
function getVarName(variable) {
for (let key in window) {
if (window[key] == variable) {
return key;
}
}
return null;
}
var var1 = {};
foobar = {};
let var2 = {};
const var3 = {};
console.log(getVarName(var1)); // var1
console.log(getVarName(foobar)); // foobar
console.log(getVarName(var2)); // null
console.log(getVarName(var3)); //null
Note how the last two don't work because this is hack that is in no way guaranteed to work.
EDIT: This also works in node if you use global instead of window, but the last two examples I demonstrated still won't work.

JavaScript: that vs this

I am trying to understand better the use of that and this in JavaScript. I am following Douglas Crockford's tutorial here: http://javascript.crockford.com/private.html
but I am confused regarding a couple of things. I have given an example below, and I would like to know if I am making a correct use of them:
function ObjectC()
{
//...
}
function ObjectA(givenB)
{
ObjectC.call(this); //is the use of this correct here or do we need that?
var aa = givenB;
var that = this;
function myA ()
{
that.getA(); //is the use of that correct or do we need this?
}
this.getA = function() //is the use of this correct?
{
console.log("ObjectA");
};
}
function ObjectB()
{
var that = this;
var bb = new ObjectA(that); //is the use of that correct or do we need this?
this.getB = function()
{
return bb;
};
that.getB(); //is the use of that correct or do we need this?
}
Note this is just an example.
this in JavaScript always refers to current object, method of which was called. But sometimes you need to access this of your object in deeper. For example, in callbacks. Like so:
function MyClass() {
this.a = 10;
this.do = function() {
http.get('blablabla', function(data) {
this.a = data.new_a;
});
};
}
It will not work, because this in callback may refer to http, to some dom element or just window(which is really common). So, it is common solution to define self or that, an alias for this or your object, so you can refer it anywhere inside.
function MyClass() {
var self = this;
this.a = 10;
this.do = function() {
http.get('blablabla', function(data) {
self.a = data.new_a;
});
};
}
This should give you vision why it is used and how it should be used.
There is no other reasons(currect me if I'm wrong) to create special variable, you can use this to send your object to other objects and do things, many assignments, such logic, wow...
ObjectC.call(this); //is the use of this correct here or do we need that?
The first thing you need to understand is how the this keyword works. It's value depends on how the function/method/constructor is called.
In this case, function ObjectA is a constructor, so you can just use this inside the code of it. In fact, with var that = this; you declare them to be absolutely identical (unless you use that before assigning to it).
function myA() {
that.getA(); //is the use of that correct or do we need this?
}
Again, it depends on how the function is called - which you unfortunately have not show us. If if was a method of the instance, this would have been fine; but but it seems you will need to use that.
this.getA = function() //is the use of this correct?
As stated above, using that would not make any difference.
var bb = new ObjectA(that) //is the use of that correct or do we need this?
var that = this;
that is undefined when it is used here. And it would be supposed to have the same value as this anyway. Better use this.
that.getB(); //is the use of that correct or do we need this?
Again, both have the same effect. But since you don't need that, you should just use this.
Everything is correct except for :
function ObjectB()
{
var bb = new ObjectA(that) //this is wrong
var that = this;
this.getB = function()
{
return bb;
};
that.getB();
}
You are missing ; and that isn't declare.
You need that (in your case, this is the variable name you use) when you want to use this in another scope :
function ObjectB()
{
var that = this;
// here 'this' is good
function()
{
// Here 'this' doesn't refer to the 'this' you use in function ObjectB()
// It's not the same scope
// You'll need to use 'that' (any variable from the ObjectB function that refers to 'this')
};
// Here 'that' = 'this', so there is no difference in using one or another
}
What "that" is in this context is simply a variable that is equal to "this". That means saying "that" is exactly the same as saying "this", which makes in unnecessarily complicating.
This code:
var that=this;
that.getA();
Will yield the same result as this code:
this.getA();
Having a variable to represent "this" just complicates things when you can just say "this".

Method vs Functions, and other questions

With respect to JS, what's the difference between the two? I know methods are associated with objects, but am confused what's the purpose of functions? How does the syntax of each of them differ?
Also, what's the difference between these 2 syntax'es:
var myFirstFunc = function(param) {
//Do something
};
and
function myFirstFunc(param) {
//Do something
};
Also, I saw somewhere that we need to do something like this before using a function:
obj.myFirstFunc = myFirstFunc;
obj.myFirstFunc("param");
Why is the first line required, and what does it do?
Sorry if these are basic questions, but I'm starting with JS and am confused.
EDIT: For the last bit of code, this is what I'm talking about:
// here we define our method using "this", before we even introduce bob
var setAge = function (newAge) {
this.age = newAge;
};
// now we make bob
var bob = new Object();
bob.age = 30;
// and down here we just use the method we already made
bob.setAge = setAge;
To answer your title question as to what is the difference between a 'function' and a 'method'.
It's semantics and has to do with what you are trying to express.
In JavaScript every function is an object. An object is a collection of key:value pairs. If a value is a primitive (number, string, boolean), or another object, the value is considered a property. If a value is a function, it is called a 'method'.
Within the scope of an object, a function is referred to as a method of that object. It is invoked from the object namespace MyObj.theMethod(). Since we said that a function is an object, a function within a function can be considered a method of that function.
You could say things like “I am going to use the save method of my object.” And "This save method accepts a function as a parameter.” But you generally wouldn't say that a function accepts a method as a parameter.
Btw, the book JavaScript Patterns by Stoyan Stefanov covers your questions in detail, and I highly recommend it if you really want to understand the language. Here's a quote from the book on this subject:
So it could happen that a function A, being an object, has properties and methods, one of which happens to be another function B. Then B can accept a function C as an argument and, when executed, can return another function D.
There is a slight difference -
Method : Method is a function when object is associated with it.
var obj = {
name : "John snow",
work : function someFun(paramA, paramB) {
// some code..
}
Function : When no object is associated with it , it comes to function.
function fun(param1, param2){
// some code...
}
Many answers are saying something along the lines that a method is what a function is called when it is defined on an object.
While this is often true in the way the word is used when people talk about JavaScript or object oriented programming in general (see here), it is worth noting that in ES6 the term method has taken on a very specific meaning (see section 14.3 Method Definitions of the specs).
Method Definitions
A method (in the strict sense) is a function that was defined through the concise method syntax in an object literal or as a class method in a class declaration / expression:
// In object literals:
const obj = {
method() {}
};
// In class declarations:
class MyClass {
method() {}
}
Method Specificities
This answer gives a good overview about the specificities of methods (in the strict sense), namely:
methods get assigned an internal [[HomeObject]] property which allows them to use super.
methods are not created with a prototype property and they don't have an internal [[Construct]] method which means that they cannot be called with new.
the name of a method does not become a binding in the method's scope.
Below are some examples illustrating how methods (in the strict sense) differ from functions defined on objects through function expressions:
Example 1
const obj = {
method() {
super.test; // All good!
},
ordinaryFunction: function ordinaryFunction() {
super.test; // SyntaxError: 'super' keyword unexpected here
}
};
Example 2
const obj = {
method() {},
ordinaryFunction: function ordinaryFunction() {}
};
console.log( obj.ordinaryFunction.hasOwnProperty( 'prototype' ) ); // true
console.log( obj.method.hasOwnProperty( 'prototype' ) ); // false
new obj.ordinaryFunction(); // All good !
new obj.method(); // TypeError: obj.method is not a constructor
Example 3
const obj = {
method() {
console.log( method );
},
ordinaryFunction: function ordinaryFunction() {
console.log( ordinaryFunction );
}
};
obj.ordinaryFunction() // All good!
obj.method() // ReferenceError: method is not defined
A method is a property of an object whose value is a function. Methods are called on objects in the following format: object.method().
//this is an object named developer
const developer = {
name: 'Andrew',
sayHello: function () {
console.log('Hi there!');
},
favoriteLanguage: function (language) {
console.log(`My favorite programming language is ${language}`);
}
};
// favoriteLanguage: and sayHello: and name: all of them are proprieties in the object named developer
now lets say you needed to call favoriteLanguage propriety witch is a function inside the object..
you call it this way
developer.favoriteLanguage('JavaScript');
// My favorite programming language is JavaScript'
so what we name this: developer.favoriteLanguage('JavaScript');
its not a function its not an object? what it is? its a method
Your first line, is creating an object that references a function. You would reference it like this:
myFirstFunc(param);
But you can pass it to another function since it will return the function like so:
function mySecondFunction(func_param){}
mySecondFunction(myFirstFunc);
The second line just creates a function called myFirstFunc which would be referenced like this:
myFirstFunc(param);
And is limited in scope depending on where it is declared, if it is declared outside of any other function it belongs to the global scope. However you can declare a function inside another function. The scope of that function is then limited to the function its declared inside of.
function functionOne(){
function functionTwo(){}; //only accessed via the functionOne scope!
}
Your final examples are creating instances of functions that are then referenced though an object parameter. So this:
function myFirstFunc(param){};
obj.myFirst = myFirstFunc(); //not right!
obj.myFirst = new myFirstFunc(); //right!
obj.myFirst('something here'); //now calling the function
Says that you have an object that references an instance of a function. The key here is that if the function changes the reference you stored in obj.myFirst will not be changed.
While #kevin is basically right there is only functions in JS you can create functions that are much more like methods then functions, take this for example:
function player(){
this.stats = {
health: 0,
mana: 0,
get : function(){
return this;
},
set : function( stats ){
this.health = stats.health;
this.mana = stats.mana;
}
}
You could then call player.stats.get() and it would return to you the value of heath, and mana. So I would consider get and set in this instance to be methods of the player.stats object.
A function executes a list of statements example:
function add() {
var a = 2;
var b = 3;
var c = a + b;
return c;
}
1) A method is a function that is applied to an object example:
var message = "Hello world!";
var x = message.toUpperCase(); // .toUpperCase() is a built in function
2) Creating a method using an object constructor. Once the method belongs to the object you can apply it to that object. example:
function Person(first, last, age, eyecolor) {
this.firstName = first;
this.lastName = last;
this.age = age;
this.eyeColor = eyecolor;
this.name = function() {return this.firstName + " " + this.lastName;};
}
document.getElementById("demo").innerHTML = person.fullName(); // using the
method
Definition of a method: A method is a property of an object that is a function. Methods are defined the way normal functions are defined, except that they have to be assigned as the property of an object.
var myFirstFunc = function(param) {
//Do something
};
and
function myFirstFunc(param) {
//Do something
};
are (almost) identical. The second is (usually) just shorthand. However, as this jsfiddle (http://jsfiddle.net/cu2Sy/) shows, function myFirstFunc will cause the function to be defined as soon as the enclosing scope is entered, whereas myFirstFunc = function will only create it once execution reaches that line.
As for methods, they have a this argument, which is the current object, so:
var obj = {};
obj.func = function( ) {
// here, "this" is obj
this.test = 2;
}
console.log( obj.test ); // undefined
obj.func( );
console.log( obj.test ); // 2
The exact syntax you showed is because you can also do this:
function abc( ) {
this.test = 2;
}
var obj = {};
obj.func = abc;
obj.func( ); // sets obj.test to 2
but you shouldn't without good reason.
ecma document
4.3.31method :
function that is the value of a property
NOTE When a function is called as a method of an object, the object is
passed to the function as its this value.
It is very clear: when you call a function if it implicitly has a this (to point an object) and if you can't call the function without an object, the function deserves to name as method.

Binding function to another function in object

I try to bind a function but I dont really know how its work
For example
q={};
q.e=function(){return 1;}
q.e.i=function(){alert(this);}
q.e().i(); //Nothing happend I excepted that it will alert 1
So how does it work?
Thank you.
A function does also inherit from Object in Javascript. Hence you can assign properties to a function object, which you're just doing by calling
q.e.i = function() {};
but thats it. If you want to call it, you need to the same semantics
q.e.i();
in your current snippet, you're trying to execute .i() on the return value of e(), which happens to be the number 1.
You should be getting an error when calling q.e().i(); q.e() == 1 so (1).i() is an error since the Number object doesn't have an i method.
Hard to help since the code doesn't make any sense. I can only say that what you expected doesn't make sense in my head :)
Here's some code that would do what you expect
var q = {};
q.e = function() { return 1; };
q.e.i = function() { alert(this); }
// Call q.e.i, specifying what to use as this
q.e.i.call(q.e());
The trick is that in JS, this changes depending on how you call the function.
function a() {
console.log(this);
}
var obj = {
method: a
};
// Outputs the window object, calling a function without a `.` passes
// The window object as `this`
a();
// Outputs the obj, when you say obj.method(), method is called with obj as `this`
obj.method();
// You can also force the this parameter (to the number 1 in this case)
// outputs 1
obj.method.call(1);

Specifics of javascript cosntructors

Say I have a pure constructor function (containing nothing but this.Bar = bar)
1) When I call it from another function, can I pass the caller function's arguments directly when I call or must I do var myBar=new bar, myBar.Bar=thebar, where the bar is a caller argument?
2) Will the constructor still instantiate even if it doesn't get all the args?
3) How can I check if one of the args is unique, IE no other instance of the object has this value for the property in question? Specifically, I want to assign each object a unique index at creation. Maybe array?
Many thanks in advance
Say I have a pure constructor function (containing nothing but this.Bar = bar)
I'm going to assume you mean:
function MyConstructor(bar) {
this.Bar = bar;
}
(Note: The overwhelming convention in JavaScript is that property names start with a lower-case letter. So this.bar, not this.Bar. Initially-capped identifiers are usually reserved for constructor functions.)
1) When I call it from another function, can I pass the caller function's arguments directly when I call or must I do var myBar=new bar, myBar.Bar=thebar, where the bar is a caller argument?
You can pass them directly:
function foo(a, b, c) {
var obj = new MyConstructor(b);
}
2) Will the constructor still instantiate even if it doesn't get all the args?
The number of arguments passed is not checked by the JavaScript engine. Any formal arguments that you don't pass will have the value undefined when the function is called:
function MyConstructor(bar) {
console.log(bar);
}
var obj = new MyConstructor(); // logs "undefined"
3) How can I check if one of the args is unique, IE no other instance of the object has this value for the property in question? Specifically, I want to assign each object a unique index at creation. Maybe array?
In general, that's usually not in-scope for a constructor. But yes, you could use an array, or an object, to do that.
var knownBars = [];
function MyConstructor(bar) {
if (knownBars.indexOf(bar) !== -1) {
// This bar is known
}
else {
// Remember this bar
knownBars.push(bar);
}
}
Of course, indexOf may not be what you want for searching, so you may need to use some other method of Array.prototype or your own loop.
Another way would be to use an object; this assumes that bar is a string or something that can usefully be turned into a string:
var knownBars = {};
function MyConstructor(bar) {
if (knownBars.indexOf(bar) !== -1) {
// This bar is known
}
else {
// Remember this bar
knownBars[bar] = 1;
}
}
When I call it from another function, can I pass the caller function's arguments directly
There wouldn't be much point in having this.Bar = bar in the constructor function if you could not.
Will the constructor still instantiate even if it doesn't get all the args?
Assuming nothing inside it throws an exception if the argument is missing, yes. Arguments just get a value of undefined.
How can I check if one of the args is unique, IE no other instance of the object has this value for the property in question?
You'd need to have a shared store of them that you check against.
For example:
var Constructor = (function () {
var unique_check_store = {};
function RealConstructor(bar) {
if (typeof bar == 'undefined') {
throw "You must specify bar";
}
if (unique_check_store.hasOwnProperty(bar)) {
throw "You have already created one of these called '" + bar + "'";
}
this.Bar = bar;
unique_check_store[bar] = true;
}
return RealConstructor;
})();
var a, b, c;
try {
a = new Constructor();
} catch (e) {
alert(e);
}
try {
b = new Constructor("thing");
} catch (e) {
alert(e);
}
try {
c = new Constructor("thing");
} catch (e) {
alert(e);
}
alert(a);
alert(b);
alert(c);
​

Categories