"use strict"; // needs to be used as string as most browsers didn't used to support this and so would throw error.
2:
We can use the Chrome Developer Tools Snippets to develop small pieces of code.
"use strict"; or someFunction() { "use strict"; ... }
strict mode checking works ont eh scope it is declared in.
Issues with non strict mode
var theVal = 0; thVal = 1; // spelling mistake wouldn't be caught in non-strict mode if (theVal > 0) { console.log('Hello') }
Uses:
1. Precents accidental global vartiable declarations.
2. Prevents using reserved keywords.
3. Prevents deleting avariables, functions or function parameters.
4. Makes eval safer to use.
—
eval allows to evaluate abstract bits of code, but not using strict mode will leak out information from the eval blovk to otuside of it’s own scope.
var a = 10; eval("var a = 2"); console.log(a); // a = 2 in non-strict mode // a = 10 in strict mode.
4: Does JavaScript pass variable by reference or value
For primitive datatypes, it is passed by value, and for objects, it is passed by reference.
In pass by value, a copy of the variable is used.
So,
var a= 1; function foo(arg) { arg = 2; } foo(a); console.log(a); // prints 1 as because the actual source was never changed.
In pass by reference, a pointer to the object is passed.
var a = { num: 1 }; function foo(arg) { arg.num = 2; arg = { num: 3 }; // console.log(arg); } foo(a); console.log('value', a.num); // this will log 2
In JS we can’t change the pointer to an object. So when we set the arg in the function to a new object, the actual object doesn’t get updated.
So when we set a new object, the previous one gets overwritten, or in the above case, creates a new instance of arg, leaving the a object as it is.
Quiz 1: 3 of 3 correct
SECTION 3: TYPES & EQUALITY
Lecture 5: 3 – What are the different types in javascript
ECMA 5 defines 6 types, 5 primitive and 1 non primitive
Boolean, Number, String, Null (with value as null), Undefined (wtih value as undefined)
Non-Primitive – Object
typeof(null) > object
undefined == null > true
Statically typed language
In terms of Java, the type is defined earlier and the type is maintained.
Dynamically types language
In cases like Javascript, the type is inferred from whatever data is passed to it.
It creates problem at runtiume rather than wjhil;e developmnent.
Difference between null and undefined
If something hasn’t been initialized yet, it is undefined.
Only a prgrammer sets the variable to null and the null is never set by the javascript engine. null is a value
What is the difference between == and ===
Equality and Strict-Equality
Lecture 7 – 5 – What is NaN and how can we check for it.
NaN is a result of bad calculation
NaN compared to itself is false (NaN != NaN)
isNan(1) = isNaN("1") = false; isNaN("A") = false;
if (a !== a) then a is NaN. This is because NaN is the only entity in JS which is not equal to itself.
NaN compared to anything is always false
Quiz 2: Quiz
SECTION 4: SCOPES
Lecture 8: 6: What are the different scopes in JS
Anything declared outside function is of global scope.
In browsers, the base object is global, whereas in node servers, the base object is global.
If variable is declared in a function, it is scoped to the function itself.
Lecture 9: 7: What is Variable hoisting
Automatic hositing of variable declarations to the top of the scope.Either global or in a function.
The same thing happens to functions also.
console.log(a); // prints undefined var a = 10; ~ var a; console.log(a); a = 10;
——
Similar in functions
foo(); function foo() { console.log('here'); // prints here } But if using anonymous function foo(); var foo = function() { console.log('here'); } // this would throw error because as per hositing, var foo; foo(); // would throw error that foo isn't a function foo = function() { ... }
10: 8: What is Scope chain
While executing a code, the JS engine starts looking from the current scope, and if not found, moves upwards till the global scope to look out for the definitions.
11: 9: What is IIFE and why mioght you use it.
IIFE – Immediately Invoked Function Expression
If we are creating mutliple javascript files and defning variables in the global scope, then there is a problem that one variable might override another one from a different file and thus create problems with managing/locating issues related to this.
main.js name = 'Murari'; other.js name = 'Mohan';
This is creating two problems, one is polluting the global scope.
Also overriding the name value that might be needed to stay the value of ‘Murari’
This can be solved using a function scope for those variables,
other.js function myScopedFunc() { name = 'Murari'; } myScopedFunc(); This can be rewritten to, simply wrapping an anonymous function with moon braces and then invoking them using a function call method. (function() { name = 'Murari'; })();
This will cause the function to be invoked as soon as the code is parsed, thus IIFE.
12: 10: What are Function Closures
According to scope rules, any varibale declared inside a function will get destroyed as soon as the functione xecution is complete.
But when a function returns a function (which is known as closure), the reurned function keeps a reference of the variable declared inside it’s parent function.
With this, the scope also has something called closure scope and can be found in the debugger.
Closure is a special functionality in JS which helps keep references to the parent function’s variables which are otherwise not available in the global scope.
function sayHello(name) { var text = "Hello " + name; return function() { console.log(text); } } var sayName = sayHello('Murari'); sayName();
//This would log “Hello Murari” keeping the scope of ‘text’ alive even after the function sayHello() has completed execution at an earlier time.
"use strict"; var foo = []; for (var i = 0; i < 10; i++) { foo[i] = function() { return i; }; } console.log(foo[0]()); console.log(foo[1]()); console.log(foo[2]());
// Would log 10 for each.
// When returning i, rather than a copy, the actual i is kept as a reference. So when the console.log() statement is executed, the value of i is 10. So the logs would print 10.
// When we are calling the functions later, the value of i has already been incremented to 10, as it is of global scope.
So using,
foo[i] = function() { var y = i; return y; }; would also fail as by the time the function is executed, i would have got incremented and so would the value of y would be 10.
To get the value of the i when the function was called, we can use IIFE.
for(var i = 0; i < 10; i++) { (function() { var y = i; // This would keep y in the local scope of this function, and as because it is Immediately invoked, so it would keep the value of i the same to what it has at that loop. foo[i] = function() { return y; } })(); } Also similar to, for(var i = 0; i < 10; i++) { (function(y) { foo[y] = function() { return y; } })(i); }
// Closure gives the current value of the outer scope variable and not the value when the function is called.
3 things:
1. What is a closure
2. How does closure ebhave with reference to values of variables in their parent scope.
3. How to get the desired behaviour of maintaining the vlaue of outer scope variables when calling them. Ans. Using IIFE
Quiz 3:
13: 11: What does the this keyword mean
checkThis() { console.log(this); // Window } ------------- var obj = { checkThis() { console.log(this); // obj } } obj.checkThis(); -------------------- var obj = { checkThis() { console.log(this); // window } } var func = obj.checkThis(); func(); -------------------- this is a little confusing. But simply put, this refers to the calling context. The this key can change based on how the same function is called from different places. -------------------- var obj = { checkThis() { console.log(this); // obj function checkOther() { this.name = 'Murari'; console.log(this); //window } checkOther(); console.log(this.name); // undefined as because on this line, this refers to obj and when we set the variable, it was on the window object. } } obj.checkThis(); --------------------- By default, this refers to the window object, and doesn't get updated unless ti gets anbother calling context. To avoid problems down the road. it is better "use strict" mode, which would render the this keyword undefined, if no execution context is available. var obj = { checkThis() { "use strict"; console.log(this); // obj function checkOther() { console.log(this); // undefined due to usage of "use strict" } checkOther(); } } obj.checkThis(); ---------------------- To handle such scenarios, the most common way is to assign the this to some antoher variable and contihnue using that inside the whole funciton. var obj = { checkThis() { var self = this; console.log(self); // obj function checkOther() { self.name = 'Murari'; console.log(self); // obj } checkOther(); } } obj.checkThis();
———————-
14: 12: What do the functions call, bind and apply do
While funcitons are normally called as,
funcName();
they can also be called in other manners.
The functions are also objects in which there are other properties, and also new properties can be added to them and accessed.
call, apply are used to stabilize the usage of the context of execution.
Rather than using,
funcName(a, b);
we can use,
funcName.call(this, a, b);
We can use the call method with the first argument as the context of the whole function.
Whjile mostly the this keyword is passed, we can pass anything in there.
funcName.apply(this, […]);
While call and apply work the same way, apply is preferable when there are an unknown number of arguments.
bind does the same thing of locking down the this keyword, but it works in a little different way. In the case of bind, the this keyword gets set at the place of the function defniton and not at the time of the execution. So irrespective of the call of the function, the this keyword within the function always maintains the same value.
var a = function() {
console.log(this); // someObj
}.bind(someObj);
a(); // someObj
tempObj = {
func: a
};
tempObj.func(); // someObj
—————
The bind keyword doesn’t work when the function is declared, but will only work on function expressions. This is because the bind function can only be applied on objects.
————————————————
15: 13: WHat is the prototype chain
When searching for an attribute in an Object, JS tries to search that attribute in the given object, and if not found tries to find in it’s __proto__ which is basically another object it is linked to.
The base __proto__ is the default Object which is the lat parent of any Object.
In ES6 we can write something like,
var animal = {
kind: ‘human’
};
var murari = {};
murari.__proto__ = animal; // ES6 way
———–
var murari = Object.create(animal); // ES5 way
var mohan = Object.create(animal, { food: { value: ‘mango’} }); // way of setting additional properties for the new object.
// It can take additional parameters like get/set
———–
console.log(murari.kind); // human
console.log(animal.isPrototypeOf(murari)); // true
————
16: 14: What is the difference between classical and prototypal inheritance
Classical inheritance is the one whihc is used by most of the languages to create objects. In this pattern, there is an architectural design which is called as class and the objects are made out of it.
In case of prototypal inheritance, newer objects are created on the base of already available objects.
In Javascript, there is actually no classical inheritance, but a way to actually fake the classical inheritance in a prototypal way.
17/18: 15: What is the Constructor OO pattern
Pseudo classical inheritance == Constructor OO pattern == function constructors
“use strict”;
function Person(first_name, last_name) {
this.first_name = first_name;
this.last_name = last_name;
}
var person1 = new Person(‘Murari’, ‘Nayak’);
——–
function Person(first_name, last_name) {
…
this.full_name = function() {
return first_name + ‘ ‘ + last_name;
}
}
and also
Person.prototype.full_name = function() {
return first_name + ‘ ‘ + last_name;
}
———————
Using the prototype method, the function gets added to the prototype of the Person object and not the Person object itself.
So it’s not available on any of it’s instances also. This reduces memory consumption, when there are thouisands of instances of the PErson object.
The help with using function inside function constructors is that we can take create private members using the help of closures.
——————-
function Professional(honorific, first_name, last_name) {
Person.call(this, first_name, last_name);
this.honorific = honorific;
}
This will set the first_name, last_name values of the Professional object, but would not be using inheritance.
This can confirmed by calling prof.full_name() which would return undefined.
To fix this situation, we can use prototype.
Professional.prototype = Object.create(Person.prototype);
————————————————————–
19: 16: What is the Prototypal OO Pattern
Object.create();
—-
var Person = {
full_name: function() {
return this.first_name + this.last_name;
}
};
var murari = Object.create(Person);
—–
Ways to initialize the object:
Imitiating the constructor
var Person = {
init: function(first_name. last_name) {
this.first_name = first_name;
this.last_name = last_name;
},
full_name: …
}
var murari = Object.create(Person);
murari.init(‘Murari’, ‘Nayak’);
—————
Using the create function to pass value:
var murari = Object.create(Person, {
first_name: {
value: ‘Murari’
},
last_name: {
value: ‘Nayak’
}
});
———–
function PersonFactory(first_name, last_name) {
var person = Object.create(Person);
person.first_name = first_name;
person.last_name = last_name;
return person;
}
var murari = PersonFactory(‘Murari’, ‘Nayak’);
————–
There is no particula to do inheritance using the prototypal OO pattern.
We need to create the values and functions as values to the prototype while doing Object.create()
Constructor pattern pros:
The most common method of creating objects.
Can create private variables
Prototypal pattern pros:
Simple to develop and understand.
——————————————
NETWORKING
20: 17: What is CORS
Cross Origin Resource Sharing
CORS allows to break the same origin browser requests
To selectively allow request to resources
When making the get request, the origin is set to the url the browser is serving from.
After the api processes the information, on the return it selts the Access-Control-Allow-Origin header.
Only if both the origin and the Access-Control-Allow-Origin header are same, the browser processes the information received from the api.
Setting the Access-Control-Allow-Origin: * will let anyone to access the resources on the server.
One thing to notice is that the request isn’t blocked, but the response is. This would work fine in the case of GET requests, but in the case POST, PUT, DELETE, this would create a problem as the resource would already be updated before the blocking happens.
So to handle such scenarios, the browser does a pre-flight request with the method OPTIONS and Access-Control-Request-Method PUT request. Then the api retyurns the request with an additonal header named Access-Control-Allow-Methods with PUT or any additional methods that are allowed on the server.
If anything is problematic, the browser won’t allow the actual request to pass through.
21:18: What is jsonp
jsonp is an older sibling of CORS,but has limited funcitonlaity to GET requests only. But it would work without playing around with the server code.
Using jsonp, what it does that it wraps the result in a function which will be executed, because the browser doesn’t stop anything to process within the script tag.
IN this we pretend that we are executing a script rather than making a request.
some_url?format=jsonp&callback=processCallback
Quiz 6
SECTION 7 – EVENTS
22: 19: What is the difference between event bubbling and event capturing.
Event moves from the windows object to the target and moves backwards.
The first pahse is event capturing pahse.
THe second return phase is event bubbling phase.
By default, the event lsteners are added for the event-bubbling phase.
xyz.addEventListener(‘click’, funcName, useCapture)
23: 20: What is difference between stopPropagation() and preventDefault()
stopPropagation stops the event from moving further down/up the capturing/bubbkling line
The next listener always waits for the current listener to complete execution.
preventDefault does not stop the event from propagating, but stops the default behaviour of the event.