JavaScript objects defined in different ways - javascript

I'm fairly new to JavaScript and have a question regarding how objects are defined in below code snippet.
In the first instance domStrings object is defined as domStrings= and in the second instance the returning object is defined as getinput:function() what is the difference? And why if I change the returning object as getinput=function, it doesn't work? Please help me understand.
var UIcontroller = (function() {
var domStrings = {
inputType: '.add__type',
inputDescription: '.add__description',
inputValue: '.add__value',
addButton: '.add__btn'
}
return {
getinput: function() {
return {
type: document.querySelector(domStrings.inputType).value,
description: document.querySelector(domStrings.inputDescription).value,
value: document.querySelector(domStrings.inputValue).value
};
},
getDomStrings: function() {
return domStrings;
}
}
})();

var domStrings is an object, objects have keys and values. inputType, inputDescription, inputValue, addButton are the keys and to the right of them are their values. You can access these by doing domStrings.inputType etc..
your function here is returning another object return {}
so getinput is actually a key for that object that's why it's defined like that

What you are looking at is called an immediately invoked function expression (or IIFE, pronounced "iffy"). It is a work around for (ECMAScript 5) JavaScript to avoid hoisting and create closures.
In your example the variable domString is being assigned using the equals sign and the part on the right is something called an object literal and uses object literal syntax. The two functions being returned in the return statement are being declared as properties no different than they are in the object literal domStrings inputType: for example. The difference is that the value of properties in the return statement object literal are functions rather than strings. Variables and object properties in JavaScript can contain functions as their values.
In your example: domStrings is a private property of the UIcontroller function and is not accessible from anywhere else but inside the UIcontroller function. It exposes two public functions: getDomStrings and getinput and returns them to be used by callers upon instantiation.
Those two methods have access to domStrings but outside of the UIcontroller function nothing else does unless you also return a reference to domString in the return statement.
You could call UIcontroller.getDomStrings() and UIcontroller.getinput() but you can not call UIcontroller.domStrings. Returning domStrings in the return statement would make it a public property of UIcontroller which anyone could change anywhere.
Hope that helps. Does that answer it for you?
Happy coding!!!

This is an assignment and a declaration of two things:
var domStrings = {
inputType: '.add__type',
inputDescription: '.add__description',
inputValue: '.add__value',
addButton: '.add__btn'
}
The variable domstrings is declared var domStrings and assigned =.
The variable now points to a location in memory. In that location in memory is an object that just got created.
An object in JavaScript is a dictionary: it is a set of key: value pairs, where the key can be a string or a number (or a Symbol, but don't worry about that for now).
The syntax for an object declaration is: { 'key': 'value' .... }.
The value can be any of the JS types - so, basically, a string, a number, void, a function, or another object.
You can point another variable at the same object in memory:
var a = domStrings;
a.inputType /// '.add__type'
If I now assign something else to domStrings:
domStrings = "nope"
domStrings is now pointing to a different location in memory:
domStrings.inputType // undefined - "nope" doesn't have a property inputType
a is still pointing to the object:
a.inputType // '.add__type'
So that statement does more than one thing. It declares a variable domStrings, it creates an object in memory, and it assigns the object to domStrings so that domStrings is a reference to the object.
Does that make that part clearer?
The second part:
What you are looking at there is called a closure. It is an IIFE - "Immediately Invoked Function Execution" - an immediately executing function that creates something like the singularity around a black hole. All of the internal machinery inside that function closure can see what's in there, but the value of UIController from outside is:
{
getinput:() => {...},
getDomStrings: () => domstrings
}
The getDomStrings function inside the UIController can see the domstrings variable, and pass a pointer to it back to code outside, but it is the only way anything outside the closure can access it.
The getInput function can also see it, and uses it to calculate the object that it returns when it is called.
So you can share code/data between functions inside a closure, but the only way anything outside the closure can see it is if you pass a reference out like getDomStrings does.
This is not very safe, because something outside this closure can call getDomStrings and get a reference to the object. It could then change the values in the object, which will change the behaviour of the getInput function in unpredictable ways.
It looks like the author wanted people to be able to read it that object, but not access it to modify it - in which case the way to do that is to return a copy of the object. That gives the caller an object with the same values, but not in the same memory location. Changing the copy will not change the object inside the closure.
If that wasn't their intention (making it read-only), they may have wanted the interface to that closure to have two functions instead of a function and an object.
I think it is the first, because it has a get but not a corresponding set method.
Because an object is a location in memory, and objects can be nested, copying an object is not trivial. You have to make a copy of all the objects inside it.
Check this out:
const a = {z: 3, k: {a: 3}}
const b = {...a} // "Spread" the keys of a onto b, a "shallow copy"
> b
{ z: 3, k: { a: 3 } } // looks b is a copy of a
> b.k.a = 4 // change a "deep value" of b
> b
{ z: 3, k: { a: 4 } }
> a
{ z: 3, k: { a: 4 } } // the object in a has changed!
> b.z = 2 // change a shallow property of b
> b
{ z: 2, k: { a: 4 } } // b has changed
> a
{ z: 3, k: { a: 4 } } // a has not
What happened here is that the objects a and b are in different memory locations. However, each of these objects has a property k that points to another location, and they point to the same location!
We can check this:
> a == b
false
> a.k === b.k
true // !
So returning domStrings from getDomStrings actually allows code outside this controller to change its behaviour.
Returning a spread would work in this case, because domStrings has no keys that have object references assigned to them.
I would write that as:
getDomStrings: function() {
return {...domStrings};
}
That returns a copy that has the same values in it, so other parts of the program can use them to look things up, make decisions, or select things; but that copy cannot be used to mess with what's inside the closure.
There you go, the lesson on object references in JS that you didn't ask for. You're Welcome!

Related

Why is it not possible to set null to an Object passed by reference in JavaScript? [duplicate]

This question already has answers here:
Is JavaScript a pass-by-reference or pass-by-value language?
(33 answers)
Closed 2 years ago.
I don't know why in the following example it is not possible to define null to the object, however it is possible to add properties to it
function callByReference(myFunc) {
myFunc.b = 2;
myFunc = null; // this not set null to Object arg
// myFunc.b = 2; //If I set it after, throws error
}
let customObj = {
a: 1
};
console.log("Before call by reference method");
console.log(customObj);
callByReference(customObj);
console.log("After call by reference method");
console.log(customObj);
Even if I set it null first and then adding a property throws an error;
I don't understand this behavior well. Is there any reason? maybe I'm not understanding how javascript works when passing by reference a argument
The way Javascript works, every variable name is essentially a pointer (or reference) to some value. When you create a new variable by referencing an old object, or when you call a function, you're basically copying the pointer. Eg:
const fn = (param) => {
// ...
};
const obj = {};
const obj2 = obj;
fn(obj);
Above, obj2 and param both point to the empty object that was initially created in obj, you might think of it as:
obj: MemAddress1234
obj2: MemAddress1234
param: MemAddress1234
Whenever you use the = assignment operator, you reassign the binding for that variable name, but doing so doesn't affect any other variables that may have pointed at the same thing:
param = null;
results in something like
obj: MemAddress1234
obj2: MemAddress1234
param: MemAddress0
At least, that's one way to look at it. The link between obj and the empty object, and the link between obj2 and the empty object, remain unaffected, because it's only the param variable name was reassigned.
Reassigning a variable by itself will almost never have any side-effects on anything else. The two exceptions are with arguments in sloppy mode:
function foo(a, b) {
console.log(arguments);
a = 5;
console.log(arguments);
}
foo(1, 2);
and with mutable variables exported by ES6 modules.
This is the way the JavaScript works:
Parameter is always pass by value, but when a variable refers to an object, the "value" is a reference to the object.
Changing the value of a variable never changes the underlying primitive or object, it just points the variable to a new primitive or object (but if you change a property a property in underlying object is changed too).
First, you created a customObj object, that is stored somewhere in the memory.
Then you have a function with an argument function callByReference(myFunc).
If you call the function with your object callByReference(customObj) it will assign a reference pointing at customObj to the myFunc. So now myFunc points to the same place in memory as customObj.
Now, if you modify something inside myFunc, you are changing the same memory as customObj - that is why myFunc.b = 2; will modify customObj. But if you assign something new to the myFunc, you are modifying where it is pointing, not what is inside. So myFunc = null; is like telling "now myFunc points to null memory", but customObj is still pointing to the same part of the memory, so the data is the same.

Accessing function return value through nested object inside IIFE

I'm trying to set an object value to a function call using another value (array) as its parameter, however, for some reason the value comes back as undefined, I'm then trying access that value right after that. It's inside an IIFE.
I am unsure why this is happening because to the best of my knowledge the scoping is okay and the value should be initialized and executed by that time?
Here's a simplified example:
(function(){
var minefield = [1,2,3,'M',4,5,6];
function findMachine(minefieldMachine) {
return minefieldMachine === 'M';
}
var terrain = {
start:{initialMachienLocation:minefield.findIndex(findMachine)},
currentMutable:{mutableIndex:terrain.start.initialMachineLocation}//Error: "Uncaught type error cannot read property 'start' of undefined"
//Why isn't the above accessing the value declared in terrain.start.initialMachineLocation through the function call?
}
}());
However, doing this works, out of context from above:
function findMachine(minefield){return minefield === 'M'}
[1,2,3,'M',4,5,6].findIndex(findMachine);
//above returns the proper index value, 3.
This has nothing to do with the function.
What you are attempting to do is, essentially, this:
var foo = {
a: 1,
b: foo.a
}
You need to consider the order of operations.
The object literal constructs an object which is then assigned to the variable foo.
… except that while the object is being constructed, you are trying to read the value of foo. It doesn't have one yet, so this fails.
You need to do this in two steps.
var foo = {
a: 1,
}
foo.b = foo.a;

Javascript this when invoking a constructor? [duplicate]

I just came across an interesting situation in JavaScript. I have a class with a method that defines several objects using object-literal notation. Inside those objects, the this pointer is being used. From the behavior of the program, I have deduced that the this pointer is referring to the class on which the method was invoked, and not the object being created by the literal.
This seems arbitrary, though it is the way I would expect it to work. Is this defined behavior? Is it cross-browser safe? Is there any reasoning underlying why it is the way it is beyond "the spec says so" (for instance, is it a consequence of some broader design decision/philosophy)? Pared-down code example:
// inside class definition, itself an object literal, we have this function:
onRender: function() {
this.menuItems = this.menuItems.concat([
{
text: 'Group by Module',
rptletdiv: this
},
{
text: 'Group by Status',
rptletdiv: this
}]);
// etc
}
Cannibalized from another post of mine, here's more than you ever wanted to know about this.
Before I start, here's the most important thing to keep in mind about Javascript, and to repeat to yourself when it doesn't make sense. Javascript does not have classes (ES6 class is syntactic sugar). If something looks like a class, it's a clever trick. Javascript has objects and functions. (that's not 100% accurate, functions are just objects, but it can sometimes be helpful to think of them as separate things)
The this variable is attached to functions. Whenever you invoke a function, this is given a certain value, depending on how you invoke the function. This is often called the invocation pattern.
There are four ways to invoke functions in javascript. You can invoke the function as a method, as a function, as a constructor, and with apply.
As a Method
A method is a function that's attached to an object
var foo = {};
foo.someMethod = function(){
alert(this);
}
When invoked as a method, this will be bound to the object the function/method is a part of. In this example, this will be bound to foo.
As A Function
If you have a stand alone function, the this variable will be bound to the "global" object, almost always the window object in the context of a browser.
var foo = function(){
alert(this);
}
foo();
This may be what's tripping you up, but don't feel bad. Many people consider this a bad design decision. Since a callback is invoked as a function and not as a method, that's why you're seeing what appears to be inconsistent behavior.
Many people get around the problem by doing something like, um, this
var foo = {};
foo.someMethod = function (){
var that=this;
function bar(){
alert(that);
}
}
You define a variable that which points to this. Closure (a topic all its own) keeps that around, so if you call bar as a callback, it still has a reference.
NOTE: In use strict mode if used as function, this is not bound to global. (It is undefined).
As a Constructor
You can also invoke a function as a constructor. Based on the naming convention you're using (TestObject) this also may be what you're doing and is what's tripping you up.
You invoke a function as a Constructor with the new keyword.
function Foo(){
this.confusing = 'hell yeah';
}
var myObject = new Foo();
When invoked as a constructor, a new Object will be created, and this will be bound to that object. Again, if you have inner functions and they're used as callbacks, you'll be invoking them as functions, and this will be bound to the global object. Use that var that = this trick/pattern.
Some people think the constructor/new keyword was a bone thrown to Java/traditional OOP programmers as a way to create something similar to classes.
With the Apply Method
Finally, every function has a method (yes, functions are objects in Javascript) named "apply". Apply lets you determine what the value of this will be, and also lets you pass in an array of arguments. Here's a useless example.
function foo(a,b){
alert(a);
alert(b);
alert(this);
}
var args = ['ah','be'];
foo.apply('omg',args);
Function calls
Functions are just a type of Object.
All Function objects have call and apply methods which execute the Function object they're called on.
When called, the first argument to these methods specifies the object which will be referenced by the this keyword during execution of the Function - if it's null or undefined, the global object, window, is used for this.
Thus, calling a Function...
whereAmI = "window";
function foo()
{
return "this is " + this.whereAmI + " with " + arguments.length + " + arguments";
}
...with parentheses - foo() - is equivalent to foo.call(undefined) or foo.apply(undefined), which is effectively the same as foo.call(window) or foo.apply(window).
>>> foo()
"this is window with 0 arguments"
>>> foo.call()
"this is window with 0 arguments"
Additional arguments to call are passed as the arguments to the function call, whereas a single additional argument to apply can specify the arguments for the function call as an Array-like object.
Thus, foo(1, 2, 3) is equivalent to foo.call(null, 1, 2, 3) or foo.apply(null, [1, 2, 3]).
>>> foo(1, 2, 3)
"this is window with 3 arguments"
>>> foo.apply(null, [1, 2, 3])
"this is window with 3 arguments"
If a function is a property of an object...
var obj =
{
whereAmI: "obj",
foo: foo
};
...accessing a reference to the Function via the object and calling it with parentheses - obj.foo() - is equivalent to foo.call(obj) or foo.apply(obj).
However, functions held as properties of objects are not "bound" to those objects. As you can see in the definition of obj above, since Functions are just a type of Object, they can be referenced (and thus can be passed by reference to a Function call or returned by reference from a Function call). When a reference to a Function is passed, no additional information about where it was passed from is carried with it, which is why the following happens:
>>> baz = obj.foo;
>>> baz();
"this is window with 0 arguments"
The call to our Function reference, baz, doesn't provide any context for the call, so it's effectively the same as baz.call(undefined), so this ends up referencing window. If we want baz to know that it belongs to obj, we need to somehow provide that information when baz is called, which is where the first argument to call or apply and closures come into play.
Scope chains
function bind(func, context)
{
return function()
{
func.apply(context, arguments);
};
}
When a Function is executed, it creates a new scope and has a reference to any enclosing scope. When the anonymous function is created in the above example, it has a reference to the scope it was created in, which is bind's scope. This is known as a "closure."
[global scope (window)] - whereAmI, foo, obj, baz
|
[bind scope] - func, context
|
[anonymous scope]
When you attempt to access a variable this "scope chain" is walked to find a variable with the given name - if the current scope doesn't contain the variable, you look at the next scope in the chain, and so on until you reach the global scope. When the anonymous function is returned and bind finishes executing, the anonymous function still has a reference to bind's scope, so bind's scope doesn't "go away".
Given all the above you should now be able to understand how scope works in the following example, and why the technique for passing a function around "pre-bound" with a particular value of this it will have when it is called works:
>>> baz = bind(obj.foo, obj);
>>> baz(1, 2);
"this is obj with 2 arguments"
Is this defined behavior? Is it
cross-browser safe?
Yes. And yes.
Is there any reasoning underlying why
it is the way it is...
The meaning of this is pretty simple to deduce:
If this is used inside a constructor function, and the function was invoked with the new keyword, this refers to the object that will be created. this will continue to mean the object even in public methods.
If this is used anywhere else, including nested protected functions, it refers to the global scope (which in the case of the browser is the window object).
The second case is obviously a design flaw, but it's pretty easy to work around it by using closures.
In this case the inner this is bound to the global object instead of to the this variable of the outer function.
It's the way the language is designed.
See "JavaScript: The Good Parts" by Douglas Crockford for a good explanation.
I found a nice tutorial about the ECMAScript this
A this value is a special object which is related with the execution
context. Therefore, it may be named as a context object (i.e. an
object in which context the execution context is activated).
Any object may be used as this value of the context.
a this value is a property of the execution context, but not a
property of the variable object.
This feature is very important, because in contrary to variables, this value never participates in identifier resolution process. I.e. when accessing this in a code, its value is taken directly from the execution context and without any scope chain lookup. The value of this is determinate only once when entering the context.
In the global context, a this value is the global object itself (that means, this value here equals to variable object)
In case of a function context, this value in every single function call may be different
Reference Javascript-the-core and Chapter-3-this
All the answers here are very helpful but I still had a hard time to figure out what this point to in my case, which involved object destructuring. So I would like to add one more answer using a simplified version of my code,
let testThis = {
x: 12,
y: 20,
add({ a, b, c }) {
let d = a + b + c()
console.log(d)
},
test() {
//the result is NaN
this.add({
a: this.x,
b: this.y,
c: () => {
//this here is testThis, NOT the object literal here
return this.a + this.b
},
})
},
test2() {
//64 as expected
this.add({
a: this.x,
b: this.y,
c: () => {
return this.x + this.y
},
})
},
test3() {
//NaN
this.add({
a: this.x,
b: this.y,
c: function () {
//this here is the global object
return this.x + this.y
},
})
},
}
As here explained Javascript - destructuring object - 'this' set to global or undefined, instead of object it actually has nothing to do with object destructuring but how c() is called, but it is not easy to see through it here.
MDN says "arrow function expressions are best suited for non-method functions" but arrow function works here.
this in JS:
There are 3 types of functions where this has a different meaning. They are best explained via example:
Constructor
// In a constructor function this refers to newly created object
// Every function can be a constructor function in JavaScript e.g.
function Dog(color){
this.color = color;
}
// constructor functions are invoked by putting new in front of the function call
const myDog = new Dog('red');
// logs Dog has color red
console.log('Dog has color ' + myDog.color);
Normal function or method
// Browswer example:
console.log(this === window) // true
function myFn(){
console.log(this === window)
}
myFn(); // logs true
// The value of this depends on the context object.
// In this case the context from where the function is called is global.
// For the global context in the browser the context object is window.
const myObj = {fn: myFn}
myObj.fn() // logs false
// In this case the context from where the function is called is myObj.
// Therefore, false is logged.
myObj.fn2 = function myFn(){
console.log(this === myObj)
}
myObj.fn2() // logs true
// In this case the context from where the function is called is myObj.
// Therefore, true is logged.
Event listener
Inside the function of an event handler this will refer to the DOM element which detected the event. See this question: Using this inside an event handler

Why is my javascript argument not passed "by reference"?

I'm sure I'm missing something obvious here, but I'd expect the argument to the changeMe method to be passed "by reference" - in other words, that changes to the parameter inside the function will change the variable outside the function.
The following was run in jsfiddle, using Chrome's F12 developer tools to show the console output. http://jsfiddle.net/fzEpa/
var object1 = { Property1: 'Value1' };
changeMe(object1);
console.log(object1);
function changeMe(refToObject) {
console.log(refToObject);
refToObject = { Property1: 'Value2' };
console.log(refToObject);
}
It is passed by reference, but it is a reference to the object, not to the object1 variable (which is also a reference to the object).
You are overwriting the reference to the object with a reference to a new object.
This leaves the original reference to the original object intact.
To modify the object, you would do something like this:
function changeMe(refToObject) {
refToObject.Property1 = 'Value2';
}
A reference to the object is passed as the argument value. However:
refToObject = { Property1: 'Value2' };
At this point you lose the reference to the object formerly referenced by refToObject as you're assigning this variable to reference a different object.
Now if you were to edit the refToObject's properties instead of discarding the former object reference, your code would work as exepected (as firstly explained in #Quentin's answer).
If you're familiar with C++ this would be equal to doing something like this:
void f(int* ref) {
ref = new int(3);
}
int* a = new int(5);
f(a);
printf("%d",a); //Prints 5
you are trying to redefine the Property 1,so it wouldnt work. in order to work with pass by reference ypu have to do it this way refToObject.Property1='Value2' inside your ChangeMe() function . refer this for better understanding Pass Variables by Reference in Javascript

Prototype or inline, what is the difference?

I am just learning Javascript and I was wondering, is using the prototype declaration, like this:
function TSomeObj()
{
this.name="my object";
}
TSomeObj.prototype.showname = function() {
alert(this.name);
}
Basically the same as doing it like this:
function TSomeObj()
{
this.name="my object";
this.showname = function() {
alert(this.name);
}
}
When I dump the object's properties I get the same result:
TSomeObj (inline version) =
{
'name': 'my object',
'test': function
}
TSomeObj (prototype declaration) =
{
'name': 'my object',
'test': function
}
What exactly is the benefit of using prototype declarations? Except less cluttering and more orderly sourcecode perhaps.
Update: I should perhaps have made it more clear that it was the final result i was curious about. The end result is ofcourse the same (i.e both register a new function in the object prototype) - but the way they do it is wildly different. Thank you for all replies and info!
Note: This answer is accurate but does not fully reflect the new way to create classes in JavaScript using the ES6 class Thing {} syntax. Everything here does in fact apply to ES6 classes, but might take some translation.
I initially answered the wrong question. Here is the answer to your actually-asked question. I'll leave my other notes in just in case they're helpful to someone.
Adding properties to an object in the constructor function through this.prop is different from doing so outside through Object.prototype.prop.
The most important difference is that when you add a property to the prototype of a function and instantiate a new object from it, that property is accessed in the new object by stepping up the inheritance chain rather than it being directly on the object.
var baseobj = {};
function ObjType1() {
this.prop = 2;
}
function ObjType2() {}
ObjType1.prototype = baseobj;
ObjType2.prototype = baseobj; // these now have the *same* prototype object.
ObjType1.prototype.prop = 1;
// identical to `baseobj.prop = 1` -- we're modifying the prototype
var a = new ObjType1(),
b = new ObjType2();
//a.hasOwnProperty('prop') : true
//b.hasOwnProperty('prop') : false -- it has no local property "prop"
//a: { prop = 2 }, b : { prop = 1 } -- b's "prop" comes from the inheritance chain
baseobj.prop = 3;
//b's value changed because we changed the prototype
//a: { prop = 2 }, b : { prop = 3 }
delete a.prop;
//a is now reflecting the prototype's "prop" instead of its own:
//a: { prop = 3 }, b : { prop = 3 }
A second difference is that adding properties to a prototype occurs once when that code executes, but adding properties to the object inside the constructor occurs each time a new object is created. This means using the prototype performs better and uses less memory, because no new storage is required until you set that same property on the leaf/proximate object.
Another difference is that internally-added functions have access to private variables and functions (those declared in the constructor with var, const, or let), and prototype-based or externally-added functions do not, simply because they have the wrong scope:
function Obj(initialx, initialy) {
var x = initialx,
y = initialy;
this.getX = function() {
return x;
}
var twoX = function() { // mostly identical to `function twoX() { ... }`
return x * 2;
}
this.getTwoX = function() {
return twoX();
}
}
Obj.prototype.getY = function() {
return y; // fails, even if you try `this.y`
}
Obj.prototype.twoY = function() {
return y * 2; // fails
}
Obj.prototype.getTwoY = function() {
return twoY(); // fails
}
var obj = new Obj();
// obj.y : fails, you can't access "y", it is internal
// obj.twoX() : fails, you can't access "twoX", it is internal
// obj.getTwoX() : works, it is "public" but has access to the twoX function
General notes about JavaScript objects, functions, and inheritance
All non-string and non-scalar variables in JavaScript are objects. (And some primitive types undergo boxing when a method is used on them such as true.toString() or 1.2.valueOf()). They all act somewhat like a hash/dictionary in that they have an unlimited(?) number of key/value pairs that can be assigned to them. The current list of primitives in JavaScript is: string, number, bigint, boolean, undefined, symbol, null.
Each object has an inheritance chain of "prototypes" that go all the way up to the base object. When you access a property of an object, if that property doesn't exist on the object itself, then the secret prototype of that object is checked, and if not present then that object's prototype, so on and so forth all the way up. Some browsers expose this prototype through the property __proto__. The more modern way to get the prototype of an object is Object.getPrototypeOf(obj). Regular objects don't have a prototype property because this property is for functions, to store the object that will be the prototype of any new objects created using that function as their constructor.
A JavaScript function is a special case of an object, that in addition to having the key/value pairs of an object also has parameters and a series of statements that are executed in order.
Every time a function object is invoked it is paired with another object that is accessed from within the function by the keyword this. Usually, the this object is the one that the function is a property of. For example, ''.replace() boxes the string literal to a String, then inside the replace function, this refers to that object. another example is when a function is attached to a DOM element (perhaps an onclick function on a button), then this refers to the DOM element. You can manually choose the paired this object dynamically using apply or call.
When a JavaScript function is invoked with the new keyword as in var obj = new Obj(), this causes a special thing to happen. If you don't specifically return anything, then instead of obj now containing the return value of the Obj function, it contains the this object that was paired with the function at invocation time, which will be a new empty object with the first parent in its inheritance chain set to Obj.prototype. The invoked Obj() function, while running, can modify the properties of the new object. Then that object is returned.
You don't have to worry much about the keyword constructor, just suffice it to say that obj.constructor points to the Obj function (so you can find the thing that created it), but you'll probably not need to use this for most things.
Back to your question. To understand the difference between modifying the properties of an object from within the constructor and modifying its prototype, try this:
var baseobj = {prop1: 'x'};
function TSomeObj() {
this.prop2 = 'y';
};
TSomeObj.prototype = baseobj;
var a = new TSomeObj();
//now dump the properties of `a`
a.prop1 = 'z';
baseobj.prop1 = 'w';
baseobj.prop2 = 'q';
//dump properties of `a` again
delete a.prop1;
//dump properties of `a` again
You'll see that setting a.prop1 is actually creating a new property of the proximate object, but it doesn't overwrite the base object's prop1. When you remove prop1 from a then you get the inherited prop1 that we changed. Also, even though we added prop2 after a was created, a still has that property. This is because javascript uses prototype inheritance rather than classic inheritance. When you modify the prototype of TSomeObj you also modify all its previously-instantiated objects because they are actively inheriting from it.
When you instantiate a class in any programing language, the new object takes on the properties of its "constructor" class (which we usually think of as synonymous with the object). And in most programming languages, you can't change the properties or methods of the class or the instantiated object, except by stopping your program and changing the class declaration.
Javascript, though, lets you modify the properties of objects and "classes" at run-time, and all instantiated objects of that type class are also modified unless they have their own properties that override the modification. Objects can beget objects which can beget objects, so this works in a chain all the way up to the base Object class. I put "classes" in quotes because there really isn't such a thing as a class in JavaScript (even in ES6, it's mostly syntactic sugar), except that the new keyword lets you make new objects with the inheritance chain hooked up for you, so we call them classes even though they're just the result of constructor functions being called with the new keyword.
Some other notes: functions have a Function constructor, objects have an Object constructor. The prototype of the Function constructor is (surprise, surprise) Object.
Inheriting from an object without the constructor function running
In some cases, it's useful to be able to create a new "instance of an object" without the constructor function running. You can inherit from a class without running the class's constructor function like so (almost like manually doing child.__proto__ = parent):
function inheritFrom(Class) {
function F() {};
F.prototype = Class.prototype;
return new F();
}
A better way to do this now is Object.setPrototypeOf().
The accepted answer missed the most important distinctions between prototypes and methods bound to a specific object, so I'm going to clarify
Prototype'd functions are only ever declared once. Functions attached using
this.method = function(){}
are redeclared again and again whenever you create an instance of the class. Prototypes are, thus, generally the preferred way to attach functions to a class since they use less memory since every instance of that class uses the same functions. As Erik pointed out, however, functions attached using prototypes vs attached to a specific object have a different scope, so prototypes don't have access to "private" variables defined in a function constructor.
As for what a prototype actually is, since it's an odd concept coming from traditional OO languages:
Whenever you create a new instance of a function:
var obj = new Foo();
the following logic is run (not literally this code, but something similar):
var inheritsFrom = Foo,
objectInstance = {};
objectInstance.__proto__ = inheritsFrom.prototype;
inheritsFrom.apply( objectInstance, arguments );
return objectInstance;
so:
A new object is created, {}, to represent the new instance of the function
The prototype of the function is copied to __proto__ of the new object. Note that this is a copy-by-reference, so Foo.prototype and objectInstance.__proto__ now refer to the same object and changes made in one can be seen in the other immediately.
The function is called with this new object being set as this in the function
and whenever you try to access a function or property, e.g.: obj.bar(), the following logic gets run:
if( obj.hasOwnProperty('bar') ) {
// use obj.bar
} else if( obj.__proto__ ){
var proto = obj.__proto__;
while(proto){
if( proto.hasOwnProperty('bar') ){
// use proto.bar;
}
proto = proto.__proto__;
}
}
in other words, the following are checked:
obj.bar
obj.__proto__.bar
obj.__proto__.__proto__.bar
obj.__proto__.__proto__.__proto__.bar
... etc
until __proto__ eventually equals null because you've reached the end of the prototype chain.
Many browsers actually expose __proto__ now, so you can inspect it in Firebug or the Console in Chrome/Safari. IE doesn't expose it (and may very well have a different name for the same thing internally).

Categories