javascript dynamic object - javascript

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.

Related

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'

Why and/or How this works in JavaScript ? (returning the received arguments as if were a propertie in a method)

I'm following a js tutorial,then I noticed this way to create a class/objects
//create a Book like class function (construct),
//pretty normal unti I've learnt, except for the return part
var Book = function(name){
this.name = function(){
return name;
}
}
//then using the new operator, create and object of Book sending the "name" in the constructor
var myBook = new Book("Javscript book");
//and then I can get it back with the method name
//(which actually doesn't need to be named as "name")
console.log(myBook.name());
My concern is why/how it works, I mean How I'm able to get the property "name"? and if it's even a property in the myBook object, because there's no an explicit assignment or prop declaration, until I know it works or it's set when the constructor received the parameter in the "name" argument, but not sure and I'm probably need to know how js code is executed to understand how this works.
My theory, is that actually I'm returning the parameter I sent in the constructor, not a property from the object, the argument is still "alive" in the myBook instance then it can be used in the return statement, am I right ?
Welcome to the world of Closures!
Let me try to give you a brief introduction to it.
First off, let me give the formal definition: a closure is a link(present in the function object) from a function object to the scope in which it was defined.
Ok, that does not make much sense right now.
We need to know:
What is scope?
What is a function object?
What does the statement mean?
What is scope?
Scope of a variable refers to the places where a variable is accessible. Javascript has function scope, which means variables declared(with the var keyword) inside a function are visible only inside the function. Each function invocation has it's own scope object. So if you call myFunction(), and call it a second time myFunction(), the two function calls have separate scope objects. So, if you call a function, you are in effect creating a scope object for that function invocation.
What is a function object?
When you declare a function
function Functions_are_objects()
{
//your code
}
A function object is created and filled with your code, and a reference to that function object is stored in the variable Functions_are_objects. This way when you call Functions_are_objects(), Javascript knows which function you want to execute.
Now, let's understand how your code works:
When you write
var Book = function(name){
this.name = function(){
return name;
}
}
and when you call it
var myBook = new Book("Javscript book");
the following happens:
1.) A (anonymous) function object is created and Book stores it's reference.
2.) When a statement is encountered with the new operator it works in this way
i. A new empty object is created.
ii. If the (constructor) function Book has a prototype property, the internal prototype property of the newly created object is set to it.
iii. The execution context is set to this newly created object and the function Book is called. When we say "Set the execution context to this newly created object", we mean that the this refers to the newly created object inside the function Book. Now the function Book is executed, and the statement this.name is encountered. Since this is the newly created object, and since it has no name property, a new property "name" is implicitly created and assigned the function object. At this point, based on the formal definition of Closures that we saw earlier, the function object has a reference to the scope in which it was created. Recall that, Javascript has function scope, and at the point of running
this.name = function(){
return name;
}
The scope is the scope of the function invocation of the function Book.
When you called
var myBook = new Book("Javscript book");
to the function Book, the name parameter is a local variable to this function invocation, and by the above call, the local variable "name" gets the value "Javscript book". Make sense, so far?
Now, since the function object
function(){
return name;
}
was created in this invocation of the Book function, the above function object has the reference to this local variable name.
Now, putting it all together, when you do:
console.log(myBook.name());
myBook.name function is called, and since this function had a reference to the scope in which Book was called, and that scope has the value for the variable name, and it returns this value.
You are correct that the "name" value that you are seeing is not actually a property of the instance you are creating, but rather the parameter you are passing into the constructor of the object. The way this specific example works is that when you call the constructor, the name parameter that you passed in exists within the scope of that instance and is outputted by the name() method that is defined.
Yes, you are correct that the method is returning the value of the parameter.
The argument is not kept in the instance of the object. The parameter is a local variable in the scope where the inner function is created, so it's caught in the closure for that function. That's why the name method can still access the parameter after the function that creates the object has finished (and the scope is gone).
In javascript, this is call Closure.
A closure is a function that “captures” values near where it was born.
Basically Javascript automatically creates a local copy of the variable that is passed.
Please refer to this link for more information: How do JavaScript closures work?

context to use call and apply in Javascript?

Guys can any one explain context to use call and apply methods in Javascript?
Why to use call and apply instead of calling a function directly ?
You use call or apply when you want to pass a different this value to the function. In essence, this means that you want to execute a function as if it were a method of a particular object. The only difference between the two is that call expects parameters separated by commas, while apply expects parameters in an array.
An example from Mozilla's apply page, where constructors are chained:
function Product(name, price) {
this.name = name;
this.price = price;
if (price < 0)
throw RangeError('Cannot create product "' + name + '" with a negative price');
return this;
}
function Food(name, price) {
Product.apply(this, arguments);
this.category = 'food';
}
Food.prototype = new Product();
function Toy(name, price) {
Product.apply(this, arguments);
this.category = 'toy';
}
Toy.prototype = new Product();
var cheese = new Food('feta', 5);
var fun = new Toy('robot', 40);
What Product.apply(this, arguments) does is the following: The Product constructor is applied as a function within each of the Food and Toy constructors, and each of these object instances are being passed as this. Thus, each of Food and Toy now have this.name and this.category properties.
Only if you use call or apply you can modify the this context inside the function.
Unlike other languages - in JavaScript this does not refer to the current object - rather to the execution context and can be set by the caller.
If you call a function using the new keyword this will correctly refer to the new object (inside the constructor function)..
But in all other cases - this will refer to the global object unless set explicitly through call
You use .call() when you want to cause a function to execute with a different this value. It sets the this value as specified, sets the arguments as specified and then calls the function. The difference between .call() and just executing the function is the value of the this pointer when the function executes. When you execute the function normally, javascript decides what the this pointer will be (usually the global context window unless the function is called as a method on an object). When you use .call(), you specify exactly what you want this to be set to.
You use .apply() when the arguments you want to pass to a function are in an array. .apply() can also cause a function to execute with a specific this value. .apply() is most often used when you have an indeterminate number of arguments that are coming from some other source. It is often used too pass the arguments from one function call to another by using the special local variable arguments which contains an array of arguments that were passed to your current function.
I find the MDN references pages for .call() and .apply() helpful.
If you have experience with jQuery, you will know that most functions take use of the this object. For example, collection.each(function() { ... });
Inside this function, "this" refers to the iterator object. This is one possible usage.
I personally have used .apply() for implementing a queue of requests - I push an array of arguments into the queue, and when the time comes for executing it, I take an element, and pass it as the arguments for a handler function using .apply(), thus making the code cleaner then if having to pass an array of arguments as a first argument. That's another example.
In general, just keep in mind that those ways to call a function exist, and you may one day find them convenient to use for implementing your program.
If you have experience with Object Oriented Programming then call and apply will make sense if you compare it with inheritance and override the properties or method/functions of parent class from child class. Which is similar with call in javascript as following:
function foo () {
this.helloworld = "hello from foo"
}
foo.prototype.print = function () {
console.log(this.helloworld)
}
foo.prototype.main = function () {
this.print()
}
function bar() {
this.helloworld = 'hello from bar'
}
// declaring print function to override the previous print
bar.prototype.print = function () {
console.log(this.helloworld)
}
var iamfoo = new foo()
iamfoo.main() // prints: hello from foo
iamfoo.main.call(new bar()) // override print and prints: hello from bar
I can't think of any normal situation where setting the thisArg to something different is the purpose of using apply.
The purpose of apply is to pass an array of value to a function that wants those values as arguments.
It has been superseded in all regular everyday usage by the spread operator.
e.g.
// Finding the largest number in an array
`Math.max.apply(null, arr)` becomes `Math.max(...arr)`
// Inserting the values of one array at the start of another
Array.prototype.unshift.apply(arr1, arr2);
// which becomes
arr1 = [...arr2, ...arr1]

Javascript: How to access a public variable in the same class?

I recently started programming JavaScript and thought everything would be good...
Well today I faced a problem I can't solve on my own.
My tutorial/ learning project has a class called model. In this class there are several private and one public variable. This variable is of type CustomEvent:
function Model(){
/**
* Array in which the questions are stored
*/
var questions=new Array();
var db;
var valuesSplit="*";
var tableName="quests";
this.myEvent=new CustomEvent("my event");
So as you can see "myEvent" is public and can be called from outside. In this case it is an event which can be subscribed (this is done outside this class by other objects that want to listen) and it can be fired (this is done in the same class). And this is my problem.
How can I access myEvent within the model class?
I tried:
this.myEvent.fire()
and:
myEvent.fire()
But I always get "myEvent is not defined".
Probably the first thing to say is: JavaScript doesn't have classes. The sooner you stop thinking of "JavaScript classes," the better off you'll be. :-) JavaScript has OOP, but not the kind with classes. Your Model function is called a constructor function.
You can access myEvent from any code that has a reference to the object created by new Model, which includes code in your constructor (via this — e.g., the way you're setting it up) and any function called with this referring to that object (or, of course, "externally" via someObjReference.myEvent).
So probably this.myEvent.fire() is what you want, but the code you're calling it from doesn't have the right this value. That's because in JavaScript, this is controlled entirely by how a function is called, not where the function is defined as it is in some other languages. See my blog articles Mythical methods and You must remember this for more details, but I've done a somewhat truncated discussion below.
Here's an example of a fairly standard way to set up a constructor function with useful methods that all instances share:
function Foo() {
this.myEvent = new CustomEvent("my event");
}
Foo.prototype.bar = function() {
this.myEvent.fire();
};
// Usage:
var f = new Foo();
f.bar(); // Fires the event indirectly, via the code in `bar`
f.myEvent.fire(); // Fires it directly
Note that that only works if bar is called with this referring to an object with a myEvent property. It's easy to call bar with this set to something else entirely:
document.getElementById("someID").onclick = f.bar;
When the click occurs, the bar function gets called, but this does not refer to an object created via Model. (It will refer to the element with the id "someID" instead.) And so this line in bar
this.myEvent.fire();
...will fail.
If you're used to class-based languages, you can see how this is totally different from, say, Java, C#, or C++. In those langauges, this inside bar will always refer to an object created via new Model. Not so JavaScript, which is both awkward and powerful.
This flexibility of functions (not being bound to any particular object) is one of the biggest things to get used to, and take advantage of, in JavaScript. The other is how functions are closures, which is powerful but not complicated.
So if this is set by how a function is called, how do you do that? There are two ways:
Call the function by referencing it from an object property in the same expression as the call. That's an awkward way of saying do this:
var f = new Foo();
f.bar(); // <== The key bit
f["bar"](); // <== Also works
The expression f.bar() does two things, which interact: The first thing it does is retrieve the property bar of the object referenced by f, and get that property's value (which is a function reference). Then it calls that function (because of the ()). The way JavaScript works, because you did those two things in the same overall expression, the interpreter sets this to f during the call to bar for you. But note this key distinction:
var f = new Foo();
var b = f.bar;
b(); // <== Different!
Now when the bar function gets called, this will not be set to f (it'll be set to the global object, which is window on browsers), because we've separated the property retrieval from the function call.
Alternately, you can use the built-in features of JavaScript function objects, their call and apply functions. call and apply do exactly the same thing, the only difference between them is how you supply the arguments for the function. Example:
var f = new Foo();
f.bar(1, 2): // <== Calls `bar` with `this` === `f` and passing in
// the arguments 1 and 2
var b = f.bar;
b.call(f, 1, 2); // <== Does the same thing as f.bar(1, 2)
var args = [1, 2];
b.apply(f, args); // <== Does the same thing as f.bar(1, 2)
E.g., call and apply allow you to set what this should be explicitly when you call the function. The only difference between them is that call accepts the arguments to give the function as further arguments to call, and apply accepts them as an array.
If you want to use myEvent in a non public function in your Model than you have to create another reference to the myEvent which isn't using the this reference of your Model. Because the this in another function is something else than in your Model function. The easiest way to bypass this problem is if you define a new variable in your Model:
var that = this;
Then you can call your myEvent like:
that.myEvent
The myEvent member should be visible both in the inner & outer scope of the object :
function Model(){
this.myEvent = 'some value';
this.canAccessEvent = function(){
return 'myEvent' in this;
}
}
var m = new Model();
// access from outside :
alert(m.myEvent);
// access from inside :
alert('Model can access the even? ' + m.canAccessEvent());
However, it is very possible that your new CustomEvent function doesn't exist or does not return a valid object making your myEvent variable to be undefined. I suggest you attribute some other value to the myEvent property and see if it is defined. If it is defined, then the problem lies in your CustomEvent function.

Using a new operator - from John Resig #36

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.

Categories

Resources