1 - Object Properties
var engineer = {
name: "Erdi Taner Gokalp",
languages: ["JavaScript", "Scala"],
"&description": function() {
return "I am a Front-end Engineer";
}
};
var _name = "name";
engineer.name // Erdi Taner Gokalp
engineer["name"] // Erdi Taner Gokalp
engineer[_name] // Erdi Taner Gokalp
engineer["&description"]() // // I am a Front-end Engineer
engineer.&description() // ERROR!
2 - Function Arguments
/*
JavaScript function's arguments are special data type which is called "array-like object" contains an index for each argument and a length property. However, if you want to use them as an array, you need to call the "Array.prototype.slice.call(arguments, 0)" method.
*/
function concat() {
var args = Array.prototype.slice.call(arguments, 0);
return (function _concat(_args) {
if (_args.length === 0) {
return "";
}
return _args[0] + _concat(_args.slice(1, _args.length));
})(args);
}3 - Truthy & Falsy Values
/* the followings are considered as falsy */
false
null
undefined
0
""
person.x // undefined property
/* result of a logical expression is not always a real boolean */
var obj = {
x: "hello",
y: 0
};
var defaultGreet = obj.x || "hallo"; // "hello"
var defaultNumber = obj.y || 1; // ?
var defaultBoolean = obj.z || true; // ?4 - Equality
1 == 1 // true
2 == "2" // true
1 == 2 // false
"" == false // true
[] == false // true
null == undefined // true
/* the triple equality check (=== or !==) compares value and type */
1 === 1 // true
1 === "1" // false
1 === parseInt("1") // true
[] === false // false
null === undefined // false
/* Objects are always compared by their reference!!! */
var person = { name: "taner};
var otherPerson = person;
person === otherPerson // true
person === {name: "taner"} // false5 - Scope
/*
Until ES6, JavaScript only supported the "function scopes". Block scoping was not available for control structures like switch, if, for, while.
*/
var args = [1, 2, 3, 4, 5];
function sum() {
console.log(args); // ?
var args = Array.prototype.slice.call(arguments, 0);
var result = _sum(args);
console.log(args); // ?
function _sum(_args) {
var result = 0;
console.log(result); // ?
for (var i = 0; i < _args.length; i++) {
var currentItem = _args[i];
result += currentItem;
}
console.log(currentItem); // ?
console.log(i); // ?
return result;
}
console.log(result); // ?
console.log(currentItem); // ?
return result;
}
console.log(args);
var result = sum(args);
console.log(result);
6 - Closures
/*
How would the output of these execution of given code be ?
What is the problem here ?
How would you provide the output like :
5, 6
10, 11
15, 16
20, 21 ?
*/
var data = [5, 10, 15, 20];
for (var i = 0; i < 4; i++) {
asyncIncrement(data[i], function(result) {
console.log(i, result); // ?
});
}
function asyncIncrement(data, callback) {
setTimeout(function() {
callback(++data);
}, 4000);
}6 - Global Variables
/*
variables declared without "var" keyword will automatically become global. (in Node, they will be global to the module)
*/
var result = 15;
function sum() {
result = Array.prototype.slice.call(arguments, 0).reduce(function(result, current) {
result += current;
return result;
}, result);
return result;
}
result = sum(1,2,3,4); // ?
/*
use ECMAScript's strict mode by adding "use strict";
*/
/*
If you want to access global variables, then access them via global object (window in browser, global in Node)
*/
var PI = 3.14;
function floorPI() {
window.PI - window.PI % 0;
}
console.log(PI); // ?
floorPI(); // ?
console.log(PI); // ?7 - What is "this" ?
/*
"this" keyword in JavaScript refers to the "owner" of the function.
*/
var person = {
name: "taner",
printName: function() {
return "my name is " + this.name;
}
};
person.printName(); // my name is taner
/*
"this" also refers to the element(s) that triggered the event
*/
document.getElementById("user-name").addEventListener("click", function() {
this.innerHTML = "my name is taner";
});
/*
rules to define "this" :
- object which the function is called on
- the object itself when a function called with the "new" operator
- the owner has been set with "call", "apply" or "bind"
*/
var person = {
name: "taner",
printName: function() {
return "my name is " + this.name;
}
};
function Dog(name) {
this.name = name;
}
var otherPerson = {name: "erdi"};
person.printName(); // my name is taner
person["printName"](); // my name is taner
var karabas = new Dog("karabas");
karabas.name; // karabas
person.printName.call(otherPerson); // my name is erdi
var printName = person.printName.bind(otherPerson);
printName(); // my name is erdi
/*
otherwise, "this" will be the global object or undefined in "strict mode".
*/
Q 1 : Scope : What will be printed in the console ?
(function() {
var a = b = 5;
})();
console.log(b); // ?Q 1 : Create "native" methods
/*
declare a native function over String like "a string".repeat(3)
*/
String.prototype.repeat = String.prototype.repeat || function repeat(times) {
if (!times) {
return "";
}
return this + repeat(times - 1);
};Q 3 : Hoisting
function test() {
// var a;
console.log(a);
console.log(foo());
var a = 1;
function foo() {
return 2;
}
}
test();
/*
what's the result of the executing code ?
*/Q 4 : this
var fullName = "John Doe";
var obj = {
fullName: "Colin Ihrig",
prop: {
fullName: "Aurelio De Rosa",
getFullName: function() {
return this.fullName;
}
}
};
console.log(obj.props.getFullName()); // ?
var test = obj.prop.getFullName; // what is the other way of printing this out as "John Doe" ?
console.log(test()); // ?Q 5 : call() and apply()
/*
fix the previous question's issue that the console.log() prints "Aurelio De Rosa".
*/Q 1 :
/*
What is the pitfall with using typeof bar === "object" to determine if "bar" is an object ?
*/
1 - null is considered as object
2 - Arrays are also objects ;)Q 2 :
/*
what is the output of the following code ?
*/
var myObject = {
foo: "bar",
func: function() {
var self = this;
console.log("this.foo :", this.foo);
console.log("self.foo :", self.foo);
(function() {
console.log("this.foo :", this.foo);
console.log("self.foo :", self.foo);
})();
}
};
myObject.func();Q 3 :
/*
what is the significance of, and reason for, wrapping the entire content of a javascript source file in a function block ?
*/
/*
this is a common practise employed by many js libraries (jquery, node, etc). This technique creates a closure around the entire contents of the file which, perhaps most importantly, creates a private namespace and thereby helps avoid potential name clashes between different js modules and libraries.
another feature of this technique is to allow for an easily referencable alias for a global variable. this is often used, for example, in jQuery plugins, jQuery allows you to disable the $ reference to the jQuery namespace, using jQuery.noConflict(). If this has been done, your code can still use $ employing this closure technique, as follows :
*/
(function($) { /* jQuery plugin code referencing $ */ })(jQuery);Q 4 :
/*
What is the significance of the "strict mode" -> "use strict"; ?
*/
1 - easy to debug - shuts down the silent errors
2 - prevent accidental globals - assigning an undeclared value will throw error
3 - eliminates "this" coercion - undefined or null is automatically coerced to the "global" without strict mode.
4 - disallows multiple property names or parameter values - throws error
5 - makes "eval" safer - in strict mode, variables and functions declared inside of an "eval()" statement are not created in the containing scope.
6 - throws error on invalid usage of "delete" - the "delete" operator (used to remove props from objects) can not be used on non-configurable properties of the object. Non-strict code will fail silently when an attempt is made to delete a non-configurable property, whereas strict mode will throw an error.
Q 5 :
/*
consider the two functions below. will they both return the same thing ? why or why not ?
*/
function f1() {
return {
bar: "hello"
};
}
function f() {
return
{
bar: "hello"
};
}
console.log(f1()); // ?
console.log(f2()); // ?Q 6 :
/*
what is NaN ? What is its type ? How can you reliably test if a value is equal to NaN ?
*/
console.log(typeof NaN === "number"); // ?
console.log(NaN === NaN); // ?Q 7 :
/*
what will the code below produces ?
*/
console.log(0.1 + 0.2); // ?
console.log(0.1 + 0.2 == 0.3); // ?Q 8 :
/*
what is the order of the numbers logged to console ?
*/
(function() {
console.log(1);
setTimeout(function() { console.log(2); }, 1000);
setTimeout(function() { console.log(3); }, 0};
console.log(4);
})();
Q 9 :
/*
write a sum method which will work properly when invoked using either syntax below ?
*/
console.log(sum(2, 3));
console.log(sum(2)(3));Q 10 :
/*
what will the code below output to the console and why ?
*/
console.log(1 + "2" + "2");
console.log(1 +"2" + "2");
console.log(1 + -"1" + "2");
console.log(+"1" + "1" + "2");
console.log("A" - "B" + "2");
console.log("A" - "B" + 2);Q 11:
/*
the following recursive code will cause a stack overflow if the array is to large. How can you fix this and still retain the recursive pattern ?
*/
var list = readHugeList();
var nextListItem = function() {
var item = list.pop();
if (item) {
nextLisItem();
}
};
Q 12:
/*
what will be the output of the following code ?
*/
for (var i = 0; i < 5; i++) {
setTimeout(function() { console.log(i), i * 1000);
}Q 13:
/*
what will be the output of the following code ?
*/
var a = {},
b = {key: "b"},
c = {key: "c"};
a[b] = 123;
a[c] = 456;
console.log(a[b]); // ?Q 14:
/*
what will be the output of the following code ?
*/
(function(x) {
return (function(y) {
console.log(x); // ?
})(2);
})(1);
Q 15:
/*
what will be the output of the following code ?
*/
var hero = {
_name: "John Doe",
getSecretId: function() {
return this._name;
}
};
var stoleSecretId = hero.getSecretId;
console.log(stoleSecretId()); // ?
console.log(hero.getSecretId()); // ?
Q 16:
/*
create a function that, given a DOM element on the page, will visit the element itself and "all" of its descendants (not just immediate children). for each element visited, the function should pass that element to a provided callback function. The arguments to the function should be :
* a dom element
* a callback function(that takes a dom element as its argument)
*/
function f(DOMElement, callback) {
callback(DOMElement);
Array.prototype.slice.call(DOMElement.querySelectorAll("*"), 0).forEach(function(descendant) {
f(descendant, callback);
});
}