With parentheses when calling sayIt function.
function Fruit(type){
this.type = type;
this.taste = "Awful";
this.thought = sayIt();
}
function sayIt(){
return this.taste+" "+ this.type;
}
window.onload = function (){
var lemon= new Fruit("Lemon");
alert(lemon.thought);
};
This will alert "undefined undefined", why?
sayIt function without parentheses.
function Fruit (type){
this.type = type;
this.taste = "Awful";
this.thought = sayIt;
}
function sayIt(){
return this.taste +" "+ this.type;
}
window.onload = function (){
var lemon= new Fruit("Lemon");
alert(lemon.thought);
};
This will literally write down the function on the alert box, why?
Thank you in advance.
Notes inline, discussion below, references and further reading at the end:
With parentheses when calling sayIt function.
function Fruit(type){
this.type = type;
this.taste = "Awful";
// Here, you're *calling* the `sayIt` function and assigning its
// return value to `this.thought`. During the call, `this` will
// refer to the global object (not to the `Fruit` instance).
this.thought = sayIt();
}
function sayIt(){
// If this is called as it is above, `this` is the global object,
// which is `window` in browsers. Since `window` doesn't have
// `taste` or `type` properties, this returns "undefined undefined".
// That's what `this.thought` above receives.
return this.taste+" "+ this.type;
}
window.onload = function (){
var lemon= new Fruit("Lemon");
// You've said this alerts "undefined undefined", but I think you'll
// find it just alerts "undefined" (singular). There is no `sayIt`
// property on the `lemon` instance at all. If you alerted
// `lemon.thought` instead, you'd see the "undefined undefined" we
// stored there above.
alert(lemon.sayIt);
};
sayIt function without parentheses.
function Fruit (type){
this.type = type;
this.taste = "Awful";
// Here you're assigning the `sayIt` function to `this.thought`.
// Perfectly normal stuff.
this.thought = sayIt;
}
function sayIt(){
return this.taste +" "+ this.type;
}
window.onload = function (){
var lemon= new Fruit("Lemon");
// Here you're also *referring* to the function object, not calling
// it. (To call a function, you use `()` after it.) So since functions
// are objects, you're passing an object reference into `alert`.
// Alert will try to convert that to a string, and the
// implementation of `toString` on `Function` objects in most
// environments is to dump out a version of the source code of
// the function (although this behavior is *not* standardized and
// some browsers, esp. mobile browsers, don't do it).
alert(lemon.thought);
};
Key concepts from the above:
Functions are objects. You call a function by using a reference to it followed by (), e.g.:
x = foo();
means "call foo and assign its return value to x".
You refer to the function object by just using its name, sans (), e.g.:
x = foo;
means "assign the function object foo to x. (You could then call it: x().)
Unlike some other languages, in JavaScript, this is defined entirely by how a function is called, not where it's defined. When you call a function via a free variable (e.g., foo()), you're doing nothing to explicitly set the this for the function call, and so this will be the default value, which is the global object (window on browsers).
You can set what this is in two different ways:
A. Put the function reference on an object property and call the function via the property's reference to it, e.g.:
// To put it on whatever `this` is at the moment:
this.thought = sayIt;
// Or to put it on an object we have in the variable `x`:
x.thought = sayIt;
You'd then call it via the property:
this.thought();
x.thought();
Within the function call, this will refer to the object from which you retrieved the property.
B. Using the function object's intrinsic call or apply functions:
sayIt.call(lemon);
means "call the sayIt function, making this = lemon within the function call." If you pass further arguments to call, they'll be passed to the function, so:
sayIt.call(lemon, 1, 2, 3);
means "call sayIt with this = lemon and pass in 1, 2, and 3.
There's also the apply function, which is just the same thing except you pass the arguments as an array rather than individually:
// note ------------v-------v---- the square brackets create an array
sayIt.applyl(lemon, [1, 2, 3]);
// More explicitly:
var a = [1, 2, 3];
sayIt.apply(lemon, a);
means "call sayIt with this = lemon and pass in 1, 2, and 3.
I've blogged a bit on these subjects, FWIW:
thisMore to explore:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With