Using a new operator - from John Resig #36 - javascript

This example code below is #36 in John Resig`s Learning Advnaced JavaScript. http://ejohn.org/apps/learn/#36
It is called We need to make sure the
new operator is always used.
Six Questions - I would appreciate as much detail as you can provide
1) Is function User ever actually called in this code? I note that when it says assert(user...), user is lower case. If the function gets called, how? does it get called when it asserts the variable user, which has a function call attached to it i.e. User("John," name)
2) If Im correct in assuming that function User is never called, is there a way that the codethis.name = first + " " + last;` is run?
3) If the function User is called, or if it were to be called, can you please explain the order of operations inside the function User. For example, it returns new User before it does this.name = first + " " + last; how would that work if this function were called or is called?
4) in what way could !(this instanceof User) if be true. since the function User is the object, wouldn`t "this" always be an instance of itself?
5) regarding the first assert i.e. assert(user, "this was defined correctly, even if it was by mistake"), can you please explain how it was defined correctly, and, importantly, please explain how it was a mistake? How should it have been done so it`s not a mistake?
6) regarding the second assert, why is it a noteworthy that the right name was maintained? Isnt it as simple as variablenamehaving been assignedResig`. In what way might you have expected name to change?
function User(first, last){
if ( !(this instanceof User) )
return new User(first, last);
this.name = first + " " + last;
}
var name = "Resig";
var user = User("John", name);
assert( user, "This was defined correctly, even if it was by mistake." );
assert( name == "Resig", "The right name was maintained." );

This example is demonstrating a fundamental flaw in JavaScript's design, which is that calling functions intended to be used as constructors without the new operator can cause unintentional modification of the global object.
User is called on this line: var user = User("John", name);. Lowercase user holds a reference to the new uppercase User instance.
See #1.
If User is called without new, then this will not be an instanceof User. When this happens, we immediately call new User(...). In this second call, this will be an instanceof User, so the conditional block is skipped and we simply continue on with the constructor, creating a new instance of User as originally intended.
When it's called without the new operator, the value of this in a function simply refers to the global object, which is window in a browser. This is a serious mistake in the design of JavaScript, for which this exercise is demonstrating a workaround.
Because there is no explict return from the User constructor (without the instanceof check's block) , if User were called without new it would return undefined and the assert would fail. The instanceof check prevents this.
Without the protection of the instanceof check, calling User without new would cause unexpected results. Since this would refer to window, the assignment to this.name would update window.name, not the name property of a new User instance, and the assert would fail.

Any given function object can be used two ways.
As a function
As a constructor
The difference being the value of the this binding. When you use a function as a constructor the this binding will be a new object that inherits from the constructor's public prototype. Normally calling a function will set the this binding to the global object. (With strict mode in ES5 this will not happen.)
The second assert is very important now that you know that the this binding can be coerced to the global object.
A Simplification of Calling a Constructor
function ConstructUser(fname, lname) {
var obj = {}; // Empty Object
// In reality a special internal Prototype property
// is assigned rather than 'obj.prototype'.
if (User.prototype instanceof Object) {
obj.prototype = User.prototype;
} else {
obj.prototype = Object.prototype;
}
// Now call the User function with the
// new object as the 'this' binding.
User.call(obj, fname, lname);
return obj;
}

1) Is function User ever actually called in this code? I note that when it says assert(user...), user is lower case. If the function gets called, how? does it get called when it asserts the variable user, which has a function call attached to it User("John," name)
Yes. It is first called with this bound to the global object (see caveat below), and then it calls itself with a blank object whose prototype is User.prototype bound to this.
The first "call" invokes the builtin function call operator, and the second "call" invokes the builtin function construct operator. For user defined functions the two are the same, but the spec does distinguish between the two.
2) If I'm correct in assuming that function User is never called, is there a way that the code this.name = first + " " + last; is run?
Yes. The second invocation will reach that since in the second invocation this is a User.
3) If the function User is called, or if it were to be called, can you please explain the order of operations inside the function User. For example, it returns new User before it does this.name = first + " " + last; how would that work if this function were called or is called?
A call does not return until the body finishes. So the "call" invocation starts, which starts the "construct" invocation, which returns, yielding the new User which is then returned by the first invocation.
4) in what way could !(this instanceof User) if be true. since the function User is the object, wouldn`t "this" always be an instance of itself?
No. If the if statement were not there, User.call({}, "John", "Doe") would cause User to be "called" with this bound to a blank object. Try running
var notAUser = {};
User.call(notAUser, "John", "Doe")
alert(JSON.stringify(notAUser));
and you should get
{ "name": "John Doe" }
5) regarding the first assert i.e. assert(user, "this was defined correctly, even if it was by mistake"), can you please explain how it was defined correctly, and, importantly, please explain how it was a mistake? How should it have been done so it`s not a mistake?
It is the author's opinion that not putting new before User was a programmer error.
6) regarding the second assert, why is it a noteworthy that the right name was maintained? Isnt it as simple as variablenamehaving been assignedResig`. In what way might you have expected name to change?
The global variable name is a property of the global object. If this is bound to the global object, then assigning this.name would change the global variable.
Caveat:
For language-lawyers,
According to the language spec when you call a function as a function, not as a method, this is bound to null. Another part of the spec says that when you read this, if it is null, what you get back is the global object instead. This difference is significant in the case of EcmaScript 5 strict mode, because that changes the second part so that no funny stuff is done when reading this. If this is null, reading it will give you back the value null.
EDIT:
The construct operator is only defined in the JavaScript spec. The new operator in the JavaScript language is the way you invoke it.
For user defined functions, it works as follows:
Code calls new f(arg1, arg2)
JS interpreter allocates space for a new object and sets its prototype to f.prototype.
JS interpreter invokes f with this set to the new object and with arg1 and arg2 as the actual parameters.
If f returns an object, that is used as the result of new instead.
Otherwise, the new object is used. If you return any non-object value, even a string or number, then the new object is the result of new.

1.the function User is called at var user = User("John", name);
2.pass
3.I didn't understand your question.
4.
user = User("a", "b");
would do that.
5.user = new User("a", "b"); is the correct one.
6.I don't know.

Related

javascript dynamic object

I've created an array of 1000 cars. When I call run on the first car, I want it to run as normal. When I call run on any of the others and any cars created in the future, I want it to run as normal, but also log The {color} car is now running. to the console.
Solution:
`cars[0].run = cars[0].run;
var oldRun = Car.prototype.run;
Car.prototype.run = function () {
console.log("The " + this.color + " car is now running");
return oldRun.apply(this, arguments);
};
Could someone explain how this function works?It is from javacript interview question list.
Lets dissect this one line at a time:
cars[0].run = cars[0].run;
I assume that the run method was originally a prototype function. By assigning the cars run method to its own run method name we are essentially just returning a regular function and not a prototype function for the Car object. This means it won't be affected by any changes made to the prototype function which later gets a new definition.
var oldRun = Car.prototype.run;
Same thing as above except we are storing it in its own function name as opposed to assigning to a specific car. This can be used globally now.
Car.prototype.run = function () {
Ok now we are redefining the prototype method named run to all Cars. The first car is unaffected by this because its run method is just a normal function now that belongs only to that car.
console.log("The " + this.color + " car is now running");
pretty straight forward.
return oldRun.apply(this, arguments);
since we stored the original run method call to oldRun, we can now call it and return anything that this function returns. Instead of just calling it like this oldRun(); we use the apply method call so we can pass in a 'this' reference which is referring to the car we are calling this from. Here is a link to MDN for more info on 'apply':
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/apply
So why do we have to pass 'this'. Its because the oldRun function doesn't belong to any object and is completely detached from it. The new 'run' prototype method does have a reference to the car and already has use of 'this' so we just pass that reference down to the new function oldRun. That way if oldRun ever uses the keyword 'this' it will know what its referring to now.
arguments is an object referring to the arguments passed through the function prototype run. All functions have access to this. So if you run cars[1].run(param1, param2) both parameters get passed down to the oldRun function.
I was in a bit of a rush when writing this so if I missed anything or did a bad job explaining anything let me know in the comments.

OOP Programming with javascript: Making sure that this points to the right thing regardless of how the object is instantiated

from https://developer.mozilla.org/en-US/docs/Web/JavaScript/Introduction_to_Object-Oriented_JavaScript
Making sure that this points to the right thing regardless of how the
object is instantiated can be difficult. However, there is a simple
idiom to make this easier.
var Person = function(firstName) {
if (this instanceof Person) {
this.firstName = firstName;
} else {
return new Person(firstName);
}
}
Why are we returning new Person?
How can the else case actually occur?
The Person is just a regular function. The difference makes how it is invoked:
1) It can be invoked as a constructor
var p = new Person('Bill Gates');
The this context in the constructor is an instance of the Person. this instanceof Person evaluates to true.
The newly created object is automatically returned when invoking the function as a constructor.
2) Invoked as a regular function
var p = Person('Bill Gates');
this is the Window object or undefined in strict mode. this instanceof Person evaluates to false.
However to still receive an object on simple invocation, new Person(firstName) is called manually to return the correct object.
Check more details in this post.
There is no requirement that your "class" function Person gets called with the new operator.
If it does, the value of this inside the function will be an instance of the Person class.
If it doesn't, as in var p = Person('Toskan'), then the value of this will be the global object, and the prototype won't be set correctly to the Person.prototype object. To get around that, the function explicitly returns the result of calling the function with the new keyword.

Can you get the property name through which a function was called?

I've done a lot of searching and some playing around, and I'm pretty sure the answer to this question is no, but I'm hoping a JavaScript expert might have a trick up his sleeve that can do this.
A JavaScript function can be referenced by multiple properties, even on completely different objects, so there's no such thing as the object or property that holds the function. But any time you actually call a function, you must have done so via a single object (at the very least, the window object for global function calls) and property on that object.
(A function can also be called via a function-local variable, but we can consider the function-local variable to be a property of the activation object of the scope, so that case is not an exception to this rule.)
My question is, is there a way to get that property name that was used to call the function, from inside the function body? I don't want to pass in the property name as an argument, or closure around a variable in an enclosing scope, or store the name as a separate property on the object that holds the function reference and have the function access that name property on the this object.
Here's an example of what I want to do:
var callName1 = function() { var callName = /* some magic */; alert(callName); };
var obj1 = {'callName2':callName1, 'callName3':callName1 };
var obj2 = {'callName4':callName1, 'callName5':callName1 };
callName1(); // should alert 'callName1'
obj1.callName2(); // should alert 'callName2'
obj1.callName3(); // should alert 'callName3'
obj2.callName4(); // should alert 'callName4'
obj2.callName5(); // should alert 'callName5'
From my searching, it looks like the closest you can get to the above is arguments.callee.name, but that won't work, because that only returns the name that was fixed to the function object when it was defined, and only if it was defined as a named function (which the function in my example is not).
I also considered that maybe you could iterate over all properties of the this object and test for equality with arguments.callee to find the property whose value is a reference to the function itself, but that won't work either (in the general case), because there could be multiple references to the function in the object's own (or inherited) property set, as in my example. (Also, that seems like it would be kind of an inefficient solution.)
Can this be done?
Short answer:
No, you cannot get "the property name" used to call your function.
There may be no name at all, or multiple names across different scopes, so "the property name" is pretty ill defined.
arguments.callee is deprecated and should not be used.
There exists no solution that does not use arguments or closure.
Long answer:
As thefourtheye commented, you should rethink what you are trying to do and ask that instead in a new question. But there are some common misconceptions, so I will try to explain why you cannot get the "simple property name".
The reason is because it is not simple.
Before we go ahead, let us clarify something. Activation Objects are not objects at all.
The ECMAScript 5.1 specification calls them Environment Records (10.2.1), but a more common term is Scope chain.
In a browser the global scope is (often) the window object, but all other scopes are not objects.
There may be an object that you use to call a function, and when you call a function you must be in some scope.
With few exceptions, scopes are not objects, and objects are not scopes.
Then, there are many names.
When you call a function, you need to reference it, such as through an object property. This reference may have a name.
Scope chain has declarations, which always have a name.
A Function (the real function, not reference) may also have a function name - your arguments.callee.name - which is fixed at declaration.
Not only are they different names, they are not (always) the "the property name" you are seeking.
var obj = { prop : function f(){} }, func = obj.prop;
// "obj" and "func" are declarations.
// Function name is "f" - use this name instead of arguments.callee
// Property name is "prop"
func(); // Reference name is "func"
obj.prop(); // Reference names are "obj" and "prop"
// But they are the same function!
// P.S. "this" in f is undefined (strict mode) or window (non-strict)
So, a function reference may comes from a binding (e.g. function declaration), an Object (arguments.callee), or a variable.
They are all References (8.7). And reference does have a name (so to speak).
The catch is, a function reference does not always come from an object or the scope chain, and its name is not always defined.
For example a common closure technique:
(function(i){ /* what is my name? */ })(i)
Even if the reference does have a name, a function call (11.2.3) does not pass the reference or its name to the function in any way.
Which keeps the JavaScript engine sane. Consider this example:
eval("(new Function('return function a(){}'))()")() // Calls function 'a'.
The final function call refers the eval function, which refers the result of a new global scope (in strict mode, anyway), which refers a function call statement, which refers a group, which refers an anonymous Function object, and which contains code that expresses and returns a function called 'a'.
If you want to get the "property name" from within a, which one should it get? "eval"? "Function"? "anonymous"? "a"? All of them?
Before you answer, consider complications such as function access across iframes, which has different globals as well as cross origin restriction, or interaction with native functions (Function.prototype.bind for example), and you will see how it quickly becomes hell.
This is also why arguments.caller, __caller__, and other similar techniques are now all deprecated.
The "property name" of a function is even more ill defined than the caller, almost unrealistic.
At least caller is always an execution context (not necessary a function).
So, not knowing what your real problem is, the best bet of getting the "property name" is using closure.
there is no reflection, but you can use function behavior to make adding your own fairly painless, and without resorting to try/catch, arguments.callee, Function.caller, or other strongly frowned-upon behavior, just wasteful looping:
// returning a function from inside a function always creates a new, unique function we can self-identify later:
function callName() {
return function callMe(){
for(var it in this) if(this[it]===callMe) return alert(it);
}
};
//the one ugly about this is the extra "()" at the end:
var obj1 = {'callName2':callName(), 'callName3':callName() };
var obj2 = {'callName4':callName(), 'callName5':callName() };
//test out the tattle-tale function:
obj1.callName2(); // alerts 'callName2'
obj2.callName5(); // alerts 'callName5'
if you REALLY want to make it look like an assignment and avoid the execution parens each time in the object literal, you can do this hacky routine to create an invoking alias:
function callName() {
return function callMe(){
for(var it in this) if(this[it]===callMe) return alert(it);
}
};
//make an alias to execute a function each time it's used :
Object.defineProperty(window, 'callNamer', {get: function(){ return callName() }});
//use the alias to assign a tattle-tale function (look ma, no parens!):
var obj1 = {'callName2': callNamer, 'callName3': callNamer };
var obj2 = {'callName4': callNamer, 'callName5': callNamer };
//try it out:
obj1.callName2(); // alerts 'callName2'
obj2.callName5(); // alerts 'callName5'
all that aside, you can probably accomplish what you need to do without all the looping required by this approach.
Advantages:
works on globals or object properties
requires no repetitive key/name passing
uses no proprietary or deprecated features
does not use arguments or closure
surrounding code executes faster (optimized) than
a try/catch version
is not confused by repeated uses
can handle new and deleted (renamed) properties
Caveats:
doesn't work on private vars, which have no property name
partially loops owner object each access
slower computation than a memorized property or code-time repetition
won't survive call/bind/apply
wont survive a setTimeout without bind() or a wrapper function
cannot easily be cloned
honestly, i think all the ways of accomplishing this task are "less than ideal", to be polite, and i would recommend you just bite the coding bullet and pass extra key names, or automate that by using a method to add properties to a blank object instead of coding it all in an object literal.
Yes.
Sort Of.
It depends on the browser. (Chrome=OK, Firefox=Nope)
You can use a factory to create the function, and a call stack parsing hack that will probably get me arrested.
This solution works in my version of Chrome on Windows 7, but the approach could be adapted to other browsers (if they support stack and show the property name in the call stack like Chrome does). I would not recommend doing this in production code as it is a pretty brittle hack; instead improve the architecture of your program so that you do not need to rely on knowing the name of the calling property. You didn't post details about your problem domain so this is just a fun little thought experiment; to wit:
JSFiddle demo: http://jsfiddle.net/tv9m36fr/
Runnable snippet: (scroll down and click Run code snippet)
function getCallerName(ex) {
// parse the call stack to find name of caller; assumes called from object property
// todo: replace with regex (left as exercise for the reader)
// this works in chrome on win7. other browsers may format differently(?) but not tested.
// easy enough to extend this concept to be browser-specific if rules are known.
// this is only for educational purposes; I would not do this in production code.
var stack = ex.stack.toString();
var idx = stack.indexOf('\n');
var lines = ex.stack.substring(idx + 1);
var objectSentinel = 'Object.';
idx = lines.indexOf(objectSentinel);
var line = lines.substring(idx + objectSentinel.length);
idx = line.indexOf(' ');
var callerName = line.substring(0, idx);
return callerName;
}
var Factory = {
getFunction: function () {
return function () {
var callName = "";
try {
throw up; // you don't *have* to throw to get stack trace, but it's more fun!
} catch (ex) {
callName = getCallerName(ex);
}
alert(callName);
};
}
}
var obj1 = {
'callName2': Factory.getFunction(),
'callName3': Factory.getFunction()
};
var obj2 = {
'callName4': Factory.getFunction(),
'callName5': Factory.getFunction()
};
obj1.callName2(); // should alert 'callName2'
obj1.callName3(); // should alert 'callName3'
obj2.callName4(); // should alert 'callName4'
obj2.callName5(); // should alert 'callName5'

confusion about the 'this' keyword in Javascript

I can claim that 'this' keyword is the most confusing part of Javascript for those who comes from languages like C#.
I have read a lot about this on the internet and on StackOverflow too. like here and here.
I know that 'this' keyword will be bound to the context. and in constructor function it will be bound to the object being created, and when there is no immediate context it will bound to global object (i.e window)
I know all that , however confusion is still not fully cleared; So the best way to understand is by testing codes.
So I decided to write small code and I was surprised by how much convoluted the this keyword.
here is the code i tested:
function sayHi(name){
var tt = name;
return {
ss: tt,
work: function(anotherName){
alert ("hiiiii " + anotherName);
}
};
}
//this method invocation has no effect at all right now
sayHi("John");
var hi2 = new sayHi("wallace");
hi2.work("May");
alert(hi2.ss);
as expected the alert window will show (Hiiiiii May ) then ( wallace). Notice now that the line sayHi("John"); has no effect at all.
and Now the confusion will start when I change one thing ONLY (change var tt => this.tt):
function sayHi(name){
//this is the ONLY change I did.
this.tt = name;
return {
ss: tt,
work: function(anotherName){
alert ("hiiiii " + anotherName);
}
};
}
// Now this line invocation will be problematic
sayHi("John");
var hi2 = new sayHi("wallace");
hi2.work("May");
alert(hi2.ss);
the result surprised me when the alert mthod gave ( Hiiiiiii May ) and then (John) not (wallace);
so I had the idea to comment the line sayHi("John"); but that resulted in the whole code being no-functional and not working.
the demo is here
I know this might be newbee question. But it is really confusing here and I did try to read many articles and SO questions but i m missing this point.
Why does the line sayHi("John"); setting the hi2.ss to John?? and why does it break the code when we delete it ; although we invoke the sayHi method by using the new keyword afterward ??
Because you assign the parameter "name" to a property of the object referenced by this (which in this case will be window), your subsequent reference to "tt" in that object literal will be to the "tt" property of the global object, since that's the next enclosing scope.
Your first call to "sayHi" is made without the new operator, so in that call this will refer to the global object (window). The first line in the second version
this.tt = name;
therefore will set window.tt to "John".
The next call is made with the new operator. Because of that, this in the function refers to the newly-instantiated object. The line
this.tt = name;
will therefore really have no net effect on anything, because the function returns a different object in all cases. The last line of your test:
alert(hi2.ss);
says "John" because that's what's in window.tt. Why does that matter? Because "sayHi" returns an object with a property ("ss") set from the value of the symbol "tt". The only "tt" in scope will be window.tt, which was set back in the first call to the function.
When you first invoke sayHi("John");, this will point to the global object window. That means this.tt = name actually creates a global tt variable.
Then when you invoke new sayHi("wallace");, this correctly points to a new instance of sayHi, but you are returning another object instead of letting new naturally return the instance.
If you carefully look at your object literal, you define ss like ss: tt,. Since you aren't using this.tt and there is no tt symbol found in the constructor's scope, the value will then be resolved as a global variable (which was previously set to John).
When invoking a constructor function, if no return statement exists in the function then this is implicitly returned otherwise the return value is returned and this is simply ignored.
In your second example you are saving the name argument as this.tt but returning a different object. That's why things aren't working. Basically use this or return a custom object, but don't do both.

Why does setting a variable (outside of the object scope) equal to an object method return an undefined result?

The code below was copied and pasted from the MDN page on OOP with JavaScript. I have researched general questions on OOP with JavaScript. However, I'm a beginner and have the following questions about this code snippet:
What is the purpose of the line Person.prototype.gender = '';? If I take it out and run the code, I get the same results.
Why exactly does calling genderTeller() cause an 'undefined' alert? The MDN explanation seems a bit thin from a beginner's perspective. Is this a scope issue?
function Person(gender) {
this.gender = gender;
}
Person.prototype.gender = '';
Person.prototype.sayGender = function () {
alert(this.gender);
};
var person1 = new Person('Male');
var genderTeller = person1.sayGender;
person1.sayGender(); // alerts 'Male'
genderTeller(); // alerts undefined
alert(genderTeller === person1.sayGender); // alerts true
alert(genderTeller === Person.prototype.sayGender); // alerts true
What is the purpose of the line Person.prototype.gender = '';? If I take it out and run the code, I get the same results.
This seems to establish a default value for the gender property. With it, the property is still set even when an instance is created without calling the constructor:
var person2 = Object.create(Person.prototype);
console.log(person2.gender); // ""
Which could be useful when creating a child type:
function Employee() {}
Employee.prototype = Object.create(Person.prototype);
console.log(new Employee().gender); // ""
Why exactly does calling genderTeller() cause an 'undefined' alert?
MDN's document on this should explain it further, especially the section on "Function context." But, the value of this is determined when a function is called rather than by when or where it's defined.
By assigning person1.sayGender to genderTeller, it's being disassociated from person1. So, it's no longer a "method" of a particular object.
Instead, it's called as a regular function with the value of this being defaulted to the global object, which is window in browsers.
window.gender = 'n/a';
var genderTeller = person1.sayGender;
genderTeller(); // logs: 'n/a'
For question 1, the line
Person.prototype.gender = '';
gives the gender property a default value so that even if it is not assigned some other value when a new Person object is created, then it has a default value that is not undefined. There is a difference between '' and undefined that is important sometimes and not important other times, but there is a difference.
For question 2, when you do this:
var person1 = new Person('Male');
var genderTeller = person1.sayGender;
genderTeller(); // alerts undefined
Your variable genderTeller contains a function pointer and only a function pointer. It has NO association with your person1 object. When you call it as just a function, the this pointer inside the function will be set to either the global object (window in a browser) or undefined (if running in strict mode) and thus because this is not a Person object, this.gender will not contain an appropriate value and will likely be undefined.
There is a very important lesson in this error. In javascript, the this pointer is set according to how a method is called. When you call genderTeller(), you're just calling a function and thus there is no association whatsoever with any particular Person object. The this pointer will NOT point to a Person object and thus any references to this.xxx that assume it's a Person object will not work.
When you call person1.sayGender(), this is a very different way of calling the same function. Because you're calling it via an object reference, javascript will set the this pointer to the person1 object and it will work.
The difference between these two scenarios is subtle, but very important in javascript so I'll try to explain a bit more.
After you create your person1 object, it's an object that contains a property called sayGender. That property contains a value that points to the function for the sayGender operation. sayGender is just a function that's contained in a property (technically in the prototype chain on the person1 object, but you can just think of it as a property on that object.
When you do this:
var genderTeller = person1.sayGender;
You're creating a new variable called genderTeller that now ALSO holds a pointer to that same function. But, just like when it's in the sayGender property, it is just a function. It has no innate binding to any object. It only gets a binding to an object if you call it via an object reference (or if you use .call() or .apply() to force an object reference but that's beyond what you're doing here). When you just call
genderTeller()
you are just calling a function and it will have no object reference associated with it and thus this will not point to a Person object when the function runs.
As I mentioned above, it is possible to force an object reference. For example, you could do all of these:
var genderTeller = person1.sayGender;
genderTeller.call(person1);
// .apply() only differs from .call() in how
// arguments are passed to the function
// since you have no arguments to sayGender() it looks the same as .call()
var genderTeller = person1.sayGender;
genderTeller.apply(person1);
var genderTeller = person1.sayGender.bind(person1);
genderTeller();
And, it would again work because you were forcing an association with the person1 object when the function is called.
See MDN's reference for .call() and .apply() and .bind() if you want more info on this, but you should generally not need to use those just to call methods on an object because just calling it with the form obj.method() creates the object association and causes the this pointer to be set appropriately for you.
I looked over the article and was struck by how confusing this would indeed be to somebody not already intimately familiar with javascript.
Regarding #1, I believe this is a hint to the JIT compiler that "gender" is a string. Javascript JIT compilers like it when object properties stay the same type (in this case, String). It's silly that the article does not describe this, or that this line is there at all. Maybe it's there to demonstrate that you can override prototype properties in a "new Person" instance
Regarding #2, when you call object.method() in automatically calls method where the stack fills in "object" as "this". but if you do something like var detachedmethod = curobject.method and then call detachedmethod(), it does not call with "this" bound as curobject (instead, in the method body, this === undefined. Or maybe "window" I'm not sure :-))
All in all, it's a bunch of nitpicking, and not very important for day to day javascript usage, and can be picked up as you go along.
Here is the correct answer.
1) The prototype definition is not for a default value for Person. In fact, if you create another new Person with no gender, you will see it remains undefined.
var person2 = new Person();
person2.sayGender; // alerts undefined
The point here is to show that the constructor definition overrides a prototype definition.
2) Calling genderTeller() causes undefined because genderTeller is a global function which happens to have same function definition that it copied from person1.sayGender method. genderTeller is same as window.genderTeller.
Therefore when you execute genderTeller(), 'this' = window. Since window does not have a 'gender' property, you get an undefined. You can see it by this code
genderTeller(); // returns undefined
gender = 'hi there';
genderTeller(); // returns 'hi there'
Hope that helps. Here is a Plunker. http://plnkr.co/edit/wwc2vYIvH9QdFYStesVW

Categories

Resources