I am just starting to learn Javascript and was experimenting with functions. I wrote the following thinking that it would work. Is something like this possible or is it just wrong?
function foo() {
console.log(this.language);
}
foo.language = "English";
foo();
It is not possible, because to gain access to this as the current object, you'll need to instantiate the (constructor) function, which is what invoking new will do for you. Accessing this for a reference to the current instance is not only the case in Javascript though; in Java, this also isn't accessible from static context.
What you're looking for is something like:
function Foo(language) {
this.language = language;
}
Foo.prototype.log = function(){
console.log(this.language);
}
var bar = new Foo("English");
bar.log();
You can make a foo object (an instance of foo) using the new keyword. Then set the language property of that instance. If foo has a function to output its language property, then you can invoke that function on your instance to see its language.
function foo() {
this.outputLanguage = function() {
console.log(this.language);
}
}
var f1 = new foo();
f1.language = "English";
var f2 = new foo();
f2.language = "French";
f1.outputLanguage();
f2.outputLanguage();
In this example, we make 2 foo objects, and assign each a different language.
The foo() function is a constructor function. We usually pass the initial values of the instance variables to it, like this:
function foo(language) {
this.language = language;
this.outputLanguage = function() {
console.log(this.language);
}
}
var f1 = new foo("English");
var f2 = new foo("French");
f1.outputLanguage();
f2.outputLanguage();
Javascript only supports prototypal Inheritance. So to assign a property (in your case language is the property) to an Object (in your case foo) you need to use constructor. And by convention constructor are written Initcap.
function Foo(lang){
this.language = lang;
}
Foo.prototype.getLanguage = function(){
return this.language;
}
var lang1 = new Foo('english');
var lang2 = new Foo('bengali');
console.log(lang1.getLanguage()); // english
console.log(lang2.getLanguage()); // bengali
this is available on instance variables, in your case it's named function
function foo() {
console.log(foo.language); //instead of this, use function property
}
foo.language = "English";
foo();
If you want to dive more, checkout my other answer for the same topic
Related
function DoIHavePrototype()
{
var a = 10;
}
CheckIt = new DoIHavePrototype();
DoIHavePrototype.prototype.GetFnName = function()
{
return "DoIHavePrototype"
}
alert(CheckIt.GetFnName())
In the above code,I observe that prototype is an in-built property for the function using which we can append property/method to a function.
But if I remove the prototype keyword in the above code like the following:
DoIHavePrototype.GetFnName = function()
{
return "DoIHavePrototype"
}
I don't get error in function definition but instead I get error while calling the method
alert(CheckIt.GetFnName()) as "CheckIt.GetFnName is not a function"
What does the JS interpreter assume this to be??
In order to be able to invoke some function a method on an object, there are 4 ways to introduce it to the object.
The first way is what you've done in your original code, which is to assign the function to the object prototype:
Foo.prototype.myFunc = function () { .... }
Another way is to assign it to this within the constructor.
function Foo() {
this.myFunc = function () { .... }
}
We can also assign it directly to the instance:
var foo = new Foo();
var myFunc = function () { .... }
foo.myFunc = myFunc
Finally, we can bind a function to the instance:
var foo = new Foo();
var myFunc = function () { .... }
var myFuncFoo = myFunc.bind(foo)
The last case is a bit special since we have a function that's not a property of the instance, but behaves like an instance method because it's invocation context is affixed to the instance.
The most common way of defining instance methods is assignment to the prototype. The prototype property on the constructor is what the instances inherit from, so that's where we put stuff. It's important to keep in mind that the instances inherit from the prototype property, not the constructor function. Assigning anything to a constructor property does not make it available as an instance property.
Assignment to this can sometimes be used if we want to have a method that's bound. For instance:
function Foo() {
this.boundMeth = this.meth.bind(this)
this.val = "foo"
}
Foo.prototype.meth = function () {
console.log(this.val)
}
This is useful if we want to pass instance.boundMeth() as a value to another function (e.g., event handler). In JavaScript, unlike many OO languages, methods are unbound:
// Using Foo from the previous example
function runner(fn) {
fn()
}
var obj = new Foo()
runner(obj.meth) // Logs `undefined`
runner(obj.boundMeth) // Logs `foo`
When assigning to the constructor prototype, you can assign in bulk:
Foo.prototype = {
meth1: function () { .... },
meth2: function () { .... },
}
If you use ES6, you can also use the class keyword:
class Foo {
myFunc() { .... }
}
This is the same as Foo.prototype.myFunc = function () { .... }.
If you append your function straight to the class it will generate so called static method which you can only call from you class like in Array.from.
So in your case you should call it using you class (not its instances) like so DoIHavePrototype.GetFnName();
you can read about this on MDN
This can also be done, in case if you still want to use it as instance method.
function DoIHavePrototype()
{
var a = 10;
this.GetFnName = function() {
return "DoIHavePrototype";
}
}
CheckIt = new DoIHavePrototype();
alert(CheckIt.GetFnName())
I keep on trying to assign a function to a variable and I keep getting a message saying foo is not a function. I am not sure why it is saying that. When I invoke the method by itself it works, but when I assign it to a variable it won't work.
Can anyone please help me figure this out? Thank you!!!
Below is my code:
function Test(){
function foo(){
return "foo";
}
this.bar = function () {
var foo = foo();
console.log(foo);
};
}
var test = new Test();
test.bar();
The culprit is this line var foo = foo();. The statement var foo is redeclaring the local foo variable. By the time you try to access it with foo() it has become an undefined variable.
Rename the variable or the function and everything works correctly.
Following code will work. As Now we are not trying to assign same function variable to variable.
The problem is because JavaScript is function scoped. It is failing because this.bar function will try to evaluate foo first and foo is name of variable in this function so interpreter will try to execute the foo but foo is variable in this scope it will not consider foo mentioned above. Hence it fails.
Where as foo1 will work because when interpreter hits the term foo1 it will look for current scope and all parent scopes and it will get it.
function Test(){
function foo1(){
return "foo";
}
this.bar = function () {
var foo = foo1();
console.log(foo);
};
}
var test = new Test();
test.bar();
Error is at this line
var foo = foo();
Your variable foo has the same name as the function, that hides the function outside.
Renaming it will resolve the error.
var foo1 = foo();
There error you're seeing is from this line:
var foo = foo();
When you use var there you are saying that foo is being defined for the current level of scope (this.bar) - meaning it won't bubble up to Test. You can either rename the variable to something else:
var result = foo();
console.log(result);
or just forgo that variable altogether like this:
console.log(foo());
totally your choice.
If you are learning how to create and work with JavaScript objects, you may want to rewrite your code like so:
// This function constructs the object when called with new
function Test(prop) {
// Some arbitrary property
if (typeof prop === "undefined") {
prop = null;
}
this.prop = prop;
}
// The two functions
Test.prototype.foo = function() {
return "foo";
}
Test.prototype.bar = function() {
var foo = this.foo();
console.log(foo);
}
// Create the object and call foo
var test = new Test('p');
test.bar();
All JavaScript objects inherit the properties and methods from their
prototype. Objects created using an object literal, or with new
Object(), inherit from a prototype called Object.prototype. Objects
created with new Date() inherit the Date.prototype. The
Object.prototype is on the top of the prototype chain.
From: http://www.w3schools.com/js/js_object_prototypes.asp
When I use new to instainciate an instance of a certain class, I got the actual instance. When the constructor function has a return value, the new sentence gives out the actual instance also. However, when the constructor returns itself, I can't get the instance. Instead I get the constructor. I wander what's wrong with this.
Here are my test code fragment:
function foo() {
this.x = 1;
return foo;
}
console.log(new foo()); // prints the defination of foo
As we consider, in most situations, it makes no sence to return a function like this. However, why does JS has such a feature? Is there any consideration when designing JS? Or is it just a bug of JS?
If you return an object from a constructor, the result of the new ... expression will be the object you returned:
function myWackyConstructor() {
return new Date();
}
var d = new myWackyConstructor();
console.log(d);
If you return a primitive, the result will be the constructed object:
function myWackyConstructor() {
this.gotAValue = true;
return 3;
}
var v = new myWackyConstructor();
console.log(v.gotAValue);
Typically, you should not return anything from a constructor:
function myNormalConstructor() {
this.gotAValue = true;
}
var v = new myNormalConstructor();
console.log(v.gotAValue);
The question is, why are you returning the constructor from itself?
Your code does raise an eyebrow. It does not make sense to me why you would return a static class in your constructor.
I think if you returned the actual instance it might make more sense to you but it isn't necessary.
example
function foo() {
this.x = 1;
return this;
}
var aFooInstance = new foo();
console.log(aFooInstance); // prints a instance of foo
However, you might want to have private variables so you can return an object like so, in this example you can also pass in the data to the constructor.
function foo(x) {
var _x = x;
this.getX = function(){ return _x;}
}
var aFooInstance = new foo(1);
console.log(aFooInstance.getX()); // prints 1
I would suggest reading more on simple class instantiation.
In JS, when we declare a function as a class and when we create an object of that class, that function gets called first.
Dont return from the function.
The Javascript constructor does not need a return. This will work:-
function foo() {
this.x = 1;
}
var myfoo = new foo();
console.log(myfoo.x);
Conventional wisdom is that to simulate OOP in Javascript, we do everything in terms of functions and prototypes:
var fooObject = function () {
//Variables should be defined in the constructor function itself,
//rather than the prototype so that each object will have its own variables
this.someProperty = 5; //Default value
};
//Functions should be defined on the prototype chain so that each object does not
//have its own, separate function methods attached to it for performing the same
//tasks.
fooObject.prototype.doFoo = function () {
//Foo
}
Now, to create a derived class, we do:
var derivedFromFoo = new foo();
But what happens if we want to do some other stuff in our constructor for the derived object? Like set other properties? Can we do something like
var derivedFromFoo = function () {
this = new foo();
};
new foo();
That's an instance, not a class.
To create a derived class, you need to make a new function, call the base ctor from inside of it, then set the new function's prototype to an object created from the base prototype:
function Derived() {
Base.call(this);
}
Derived.prototype = Object.create(Base.prototype);
For more details, and a longer, more-correct implementation, see my blog post.
I thought I understood the concept of the JavaScript prototype object, as well as [[proto]] until I saw a few posts regarding class inheritance.
Firstly, "JavaScript OOP - the smart way" at http://amix.dk/blog/viewEntry/19038
See the implementation section:
var parent = new this('no_init');
And also "Simple JavaScript Inheritance" on John Resig's great blog.
var prototype = new this();
What does new this(); actually mean?
This statement makes no sense to me because my understand has been that this points to an object and not a constructor function. I've also tried testing statements in Firebug to figure this one out and all I receive is syntax errors.
My head has gone off into a complete spin.
Could someone please explain this in detail?
In a javascript static function, you can call new this() like so,
var Class = function(){}; // constructor
Class.foo = function(){return this;} // will return the Class function which is also an object
Therefore,
Class.foo = function(){ return new this();} // Will invoke the global Class func as a constructor
This way you get a static factory method. The moral of the story is, not to forget functions are just like any other objects when you are not calling them.
What is confusing you, I think, is just where "this" is really coming from. So bear with me-- here is a very brief explanation that I hope will make it quite clear.
In JavaScript, what "this" refers to within a function is always determined at the time the function is called. When you do:
jimmy.nap();
The nap function (method) runs and receives jimmy as "this".
What objects have references to nap is irrelevant. For example:
var jimmy = {}, billy = {};
jimmy.nap = function(){ alert("zzz"); };
var jimmy_nap = jimmy.nap;
jimmy_nap(); // during this function's execution, this is *NOT* jimmy!
// it is the global object ("window" in browsers), which is given as the
// context ("this") to all functions which are not given another context.
billy.sleep = jimmy.nap;
billy.sleep(); // during this function's excution, this is billy, *NOT* jimmy
jimmy.nap(); //okay, this time, this is jimmy!
In other words, whenever you have:
var some_func = function(arg1, arg2){ /*....*/ };
// let's say obj and other_obj are some objects that came from somewhere or another
obj.some_meth = some_func;
other_obj.some_meth = some_func;
obj.some_meth(2, 3);
other_obj.some_meth(2, 3);
What it's getting "translated" into (not literally-- this is pedagogical, not about how javascript interpreters actually work at all) is something like:
var some_func = function(this, arg1, arg2){ /* ...*/ };
// let's say obj and other_obj are some objects that came from somewhere or another
obj.some_meth = some_func;
other_obj.some_meth = some_func;
obj.some_meth(obj, 2, 3);
other_obj.some_meth(other_obj, 2, 3);
So, notice how extend is used in the example on that page:
UniversityPerson = Person.extend({ /* ... */ });
Pop quiz: When extend runs, what does it think "this" refers to?
Answer: That's right. "Person".
So the puzzling code above really is the same as (in that particular case):
var prototype = new Person('no_init');
Not so mysterious anymore, eh? This is possible because unlike in some languages,
a JavaScript variable-- including "this"-- can hold any value, including a function such as Person.
(There is nothing that makes Person specifically a constructor. Any function can be invoked with the new keyword. If I recall the exact semantics, I think they are that when a function is called with the new keyword, it is automatically given an empty object ({}) as its context ("this") and when the function returns, the return value is that same object unless (maybe?) the function returns something else)
This is a cool question because it speaks to a pretty essential part of JavaScript's neatness or oddness (depending on how you see it).
Does that answer your question? I can clarify if necessary.
AJS.Class effectively* translates this:
var Person = new AJS.Class({
init: function(name) {
this.name = name;
Person.count++;
},
getName: function() {
return this.name;
}
});
Person.count = 0;
into this:
var Person = function (name) {
this.name = name;
Person.count++;
};
Person.prototype = {
getName: function() {
return this.name;
}
};
Person.extend = AJS.Class.prototype.extend;
Person.implement = AJS.Class.prototype.implement;
Person.count = 0;
Therefore, in this case, this in AJS.Class.prototype.extend refers to Person, because:
Person.extend(...);
// is the same as
Person.extend.call(Person, ...);
// is the same as
AJS.Class.prototype.extend.call(Person, ...);
* There are a lot of cases I don't go over; this rewrite is for simplicity in understanding the problem.
Imagine the following situation :
var inner = function () {
var obj = new this;
console.log(obj.myProperty);
};
var f1 = function () {
this.myProperty = "my Property"
}
f1.f2 = inner;
f1.f2();
Here the calling object is itself a function, so this will return a function, and we can instantiate it.
In order to use this()(not this) the outer function(the context) must itself return smth that can be instantiated(another function):
var inner = function () {
var obj = new this();
console.log(obj.myProperty);
};
var f1 = function () {
var func = function () {};
func.myProperty = 'my property';
return func;
};
f1.f2 = inner;
f1.f2();
A simpler code explaination:
class User {
constructor() {
this.name = '';
this.age = '';
}
static getInfo() {
let user = new this();
console.log(user);
}
}
User.getInfo()
Output:
Object {
age: "",
name: ""
}
see this link http://www.quirksmode.org/js/this.html It will tell you about the this keyword, but I am not sure what this() is, may be its some kind of user defined function...... that you are not aware of...
"this" means the context of the function currently running.
The code you are posting surely appears in a function that act as a method for an object.
So the object is the context of the function.
"new this()" will return a clone of the current object after running its constructor function with the passed arguments.
this() refers to the the function that the code is in, but this() would have to be within that function. Calling new this(); within a function would create a never ending loop. Calling it outside of a function would be redundant because there is no function/class set as this().