Skip to content

Instantly share code, notes, and snippets.

@jamesyang124
Created September 17, 2015 23:07
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jamesyang124/e7c1784bbb3ebc4d84d4 to your computer and use it in GitHub Desktop.
Save jamesyang124/e7c1784bbb3ebc4d84d4 to your computer and use it in GitHub Desktop.
notes from udemy online course.

#Weird Part Of JS

  1. this is global object if there does not have receiver. If so, it also imply it is a window object, document === window.document.

  2. JS engine create this execution context(window object) in bottom of execution stack and run other execution context which is in top of it for you.

  3. When you declare a var or define as a function(function expression or function statement), you can find it through window.func() or func() in global environment.

  4. Hoisting: var and func are all firstly initialize but not assigned its value yet until the later code assign it. Check code example below.

    // case1
    
    b();
    console.log(a);
    // prints undefined.
    // var a has been initialized but not assigned yet.
    // the later code var a = 5; will assign its value.
    
    var a = 5;
    function b(){
    	console.log("func b");
    }
    
    // above code is equivalent to:
    // Code is parsed line by line.
    // Hoisting first => set up memory space for var and func
    // all var initially set to undefined.
    
    // case 2
    
    function b(){
    	console.log("func b");
    }
    var a;
    
    // start execute the code.
    b();
    // undefined
    console.log(a);
    
    a = 5;
    
    // Hoisting only load function code to memory,
    // so k() does not need to know b() exist or not, just load it.
    // It will print out "b"
    k();
    function k(){
    	b();
    }
    
    function b(){
    	console.log("b");
    }
  5. Global execution context will load at first, once create phase has done and start execution phase. so the execution stack will clear once all code runs in global has finished.

  6. var environment will seperately stay with each execution context in execution stack.

  7. Scope: outer execution context is usually global. If a fucntion define in global, it will set this to global which implies that this point to a function's outer execution context.

  8. Scope chain: The outer reference of execution context will based on where the function code defined in lexical env. it will go all way up until to global execution context. If the outer execution context cannot be not found, then thorw error.

    //case 1
    function b(){
    	console.log(myVar);
    	console.log(this);
    }
    
    function a(){
    	var myVar = 2;
    	b();
    	j.myVar();
    }
    
    var myVar = 5;
    var j = {
    	myVar: function(){
    		console.log(myVar);
    	}
    };
    
    a();
    
    // case 2
    function a(){
    
     // set b's lexical env to a
     function b(){
        console.log(myVar);
        // closure will set this to window obj.
        console.log(this);
     }
    
     var myVar = 2;
     // without above code, myVar will be found in global (5)
     b();
    }
    
    var myVar = 5;
    a();
  9. Only for function, this keyword refer to its receiver. if it does not have receiver, then this refers to global object(window) in default mode. if no receiver in strict mode, then this refers to undefined.

  10. For object, when a function is called as a method of an object, this sets to object instead global. Based on its receiver decide this refers to.

  11. For value property in object and declare in global, this sets to global in default by scope chain to find this var.

    function Zs(){
        // this.t is undefined because this.a refers to global
        console.log("t is " + this.t);
        console.log(this);
        console.log(this.a);

}

var p = {
	x: function(){
		var v = {
  			a: 5,
  			t: this,
  			s: Zs
		};
		console.log(v.t);
		// this bind to object p
		
		// Object { x: function() }, x is function, 
		// so this is set to p obj.
	
		v.s();
		// this bind to v obj
		
		// return function(){ console.log(this) };
		// return anonymous function declaration, not execute yet;
	
	    /*
		var d = function(){ console.log(this) };
		return d();
		// window obj
		
		return (function(){
  			console.log(this);
		})();
		// window obj
		
	    closure or anonymous function cannot access outer this,
	    so bind to global window object in default mode.
	    */
	}
};

var t = 99;
var a = 100;
p.x();
```
  1. this as a DOM event handler by MDN

  2. this inside the anonymous function cannot access the outer function’s this, so it is bound to the global window object, when strict mode is not being used.

  3. If a function have this, check where the function actually called. If it lost the receiver(a var assign to it also lost the receiver if we call that var instead directly call the function), then we have to use bind, apply, or set this to var from outside and pass it in.

  4. If an inner function is called inside another function, then this will refer to that another function's invoked object.

  5. let is another declaration for lazy loading(only be able to use until let is run), and use block scoping(valid in curly braces, not just function scope). - ECMA6

  6. Execution stack; event q: event q get event, once eecution stack empty, then it will load event from event q. This is called event loop.

  7. Create namespace by creatiing object property.

    var a = {};
    a.b.c = 5 // not work, a.b is undefined.
    
    // use b as namespace
    var a = { b: {} };
    a.b.c = 5;
  8. Object literal !== JSON exactly, JSON's property must be all string and value can only be list or primitive value.

  9. An object consist of primitive property, object properties, and methods.

  10. JSON.parse(json_string), JSON.stringify(object_literal);

  11. Function is just a special type of object.

    function k(){};
    k.greet = "greeting";
    
    console.log(k.greet);
  12. Js treat function as first class object. A function statement is a function code that not return value, a function expression is that assign the function(treat as result) to a var.

  13. Expression is a piece of code that result in a value

console.log(b);
var b = function(){}; 
// Function expression result an function object to var b.
// Also, b have not hoisted to function(), until later code assigned.
  1. If we passing a function B as argument of function C, then this of B will be lost and set to window object due to the this rule of closure or anonymous function, we can use apply or bind to pull itself in.

    var b = {
    	x: function(){ console.log(this); }, 
    	d: function(){ this.x(); },
    	t: function(func) { func(); },
    	v: function(func) { }
    };
    b.d(); // b obj

b.t(b.x); // window obj b.v(b.x()); // b.x() call first => b obj

var b = {
	x: function(){ console.log(this); }, 
	d: function(){ x(); }
};
b.d(); 
// cannot find x() in window global object.
// because we does not prefix this.
```
  1. Spread parameter replace arguments function(a, b...): access b as spread param. - ECMA6

  2. A function statment always have name:

    // function expression
    var s = function(){ console.log("ss"); }(); 
  3. Always end with semicolon, dont let parser do it for you:

    function z(){
     return
     { a: 5 }

} // Result undefined cuz parser add semicolon before line break. // Syntax parser ignore white space.


29. **IIFE**: imediately invode function expression.

 ```js
 (function(name){ console.log(name) })('name');
 // or
 (function(name){ console.log(name) }('name'));

 // use iife for multiple js loading to avoid data polluting.
 (function(name){ console.log(name); console.log(window); }('name'));
 ```
 
30. Closure knows its outer variable inside that outer function, this achieve by scope chain in lexical env.

 ```js
 function zz(what){
 	return function(boom){
 		console.log(what + " " + boom);
 	};
 }

 var v = zz("what");
 v("boom");
 ```

31. The outer function's execution context pop out exec stack, but still reside in memory. the inner function will still have reference of vars for that outer function. Then the gc will not clean outer function cuz some code sitll have reference on it. **It might cause memory leak or exhaust it out if too much inner function**. Closing in all vars of that is supposed to access to: **closure**.

32. Closure has lazy loading propery, so closure try get i which already increment to 3 in below example.

 ```js
 function hh(){
 	var ary = [];

     for (var i = 0; i < 3; i++) {
 		ary.push(function(){
   		// this is ary obejct
   		console.log(i);
 		});
 	};

 	return ary;
 }

 var t = hh();
 t[0](); // i all 3
 t[1](); // i all 3
 t[2](); // i all 3
 ``` 
 
33. To solve above case, use socpe variable `let` will bind the value to its first execution and that scope context in mean time so j can be 0, 1, 2 seperately.

 ```js
 function hh(){
 	var ary = [];

     for (var i = 0; i < 3; i++) {
 		let j = i;
 		ary.push(function(){
   		// this is ary obejct
   		console.log(j);
 		});
 	};

 	return ary;
 }
 ```


34. Or create an IIFE which pass `i` to it and return. **The only way to preserve the outer `var i` in each loop is to create another execution context instead(IIFE)**.

 ```js
 function hh_rev(){
 	var ary = [];
 	for (var i = 0; i < 3; i++) {
 		ary.push((function(j){
   			return function(){
     			console.log(j);
   			}
 		})(i));
 	};

 	return ary;
 }

 var t = hh_rev();
 t[0]();
 t[1]();
 t[2]();
 ```

35. Trick of `this`: [http://www.quirksmode.org/js/this.html](http://www.quirksmode.org/js/this.html)

36. [https://software.intel.com/zh-cn/blogs/2013/10/09/javascript-this](https://software.intel.com/zh-cn/blogs/2013/10/09/javascript-this)

 > What `this` is depends on how the callee to call a function.  
 > If there has no receiver for the func, then `this` point to global in default mode.  
 > If there has receiver, then it points to callee object.  
 > **Two patterns for it:**
 >>  ```js
 >>  obj.func(); 
 >>  // this for func point to obj.
 >>  func(); 
 >> 	// this for func point to global object in default mode.
 >>  ```

37. Examples:

 ```js
 // case 1
 var x = 10;
 var obj = {
 	x: 20,
 	f: function(){
 		console.log(this.x);
 		var foo = function(){ console.log(this.x); }
 		foo(); // 10, this point to global
 	}
 };

 obj.f();  // 20
 
 // case 2
 // To pass in obj as this instead, we can use apply, or set tmp var.
 var x = 10;
 var obj = {
 	x: 20,
 	f: function(){
 		console.log(this.x);
 		var that = this;
 		var foo = function(){ console.log(that.x); }
 		foo(); // 20, that point to global
 	}
 };

 obj.f();  // 20
 
 
 // case 3
 var x = 10;
 var obj = {
 	x: 20,
 	f: function(){ console.log(this.x); }
 };

 obj.f(); 
 // 20

// Should be very careful when you assign an func to a var.
// That means this will check whether that var has calllee or not,
// apply rule.
  
 var fOut = obj.f;
 fOut(); 
 // the fOut does not have callee, so this point to global => 10

 var obj2 = {
 	x: 30,
 	f: obj.f
 }

 obj2.f(); 
 // callee is obj2 => 30
 ```
 
38. In some js plugins, the callback function usually followed the pattern with `apply` or `call` method to set this to callee object.

 ```js
 var f = function(innerf){
 	innerf(arg1, arg2, arg3, ...);
 	// this of innerf will be global obj in default mode.
 }
 
 // The common pattern
 var f = function(innerf){
 	innerf.call(this, arg1, arg2, arg3, ...);
 }
 obj.f(function(){ // this of callback set to obj. });
 ```
39. Approach to work around `this`:

 [http://code.mforever78.com/translation/2015/05/19/understand-javascripts-this-with-clarity-and-master-it/](http://code.mforever78.com/translation/2015/05/19/understand-javascripts-this-with-clarity-and-master-it/)  
 [http://javascriptissexy.com/understand-javascripts-this-with-clarity-and-master-it/](http://javascriptissexy.com/understand-javascripts-this-with-clarity-and-master-it/)  
 
40. **Function factories**: a function return function, each time we run the factory, it returns a new function object. (not singular).

41. Clousre and Callback:

 ```js
 function sayHiLater(){
 	var g = "greeting";

 // The anonymous function; callback will execute after 3 sec. 
 // It will execute callback, and back by scope chain to 
 // find g's reference. This is closure feature.
 // You can think it just back to setTimeout code and go out to find g.
 	setTimeout(function(){
 		console.log(g);
 		console.log(this);
 	}, 3000);
 }

 var obj = {
 	p: sayHiLater,
 	pp: function() { sayHiLater(); },
 	ppp: function() {
 		var g = "greeting";
 		var self = this;
 		setTimeout(function(){
   			console.log(g);
   			console.log(self);
 		}, 3000);
 	}
 };

 obj.p(); // this is window object  => property not method.
 obj.pp(); // this is window Object => inner function.
 obj.ppp(); // this is obj Object now => object method
 ```

42. Callback: a functino call when another function is done.

 ```js
 function whenDone(callback){
 	var a = 5;
 	var j = 6;

 	callback();
 }

 whenDone(function{
 	console.log("I am callback");
 });
 ```
 
43. `bind`, `apply`, and `call`: `bind` replace `this` and return a new copy of that function. `call` and `apply` accept arguments.

 > bind(thisObj, args) => args prepend to argument list  
 > call(thisObj, ... arguments)  
 > apply(thisObj, argument_list = [] = null)  

44. Use `apply` and `call` we can implement the function currying feature. create function copy with preset params.

 ```js
 function bbb(a, b, c) {
 	console.log(arguments);
 	console.log(b);
 };

 var a = bbb.bind("thisObj", 1);
 a(2, 3); // [1,2,3] b = 2

 var a = bbb.bind("thisObj", 1, 5);
 a(3, 4, 5); // [1,5,3,4,5] b = 5
 ```
 
45. Functional programming:

 ```js
 var fu = function(limit, item){
 	//console.log(this); => window object
 	return item > limit;
 }

 function map(arr, fn){
 	var new_ary = [];
 	for (var i = 0; i < arr.length; i++) {
 		new_ary.push(fn(arr[i]));
 	}

 	return new_ary;
 }

 var result = map([1, 3, 4, 5], fu.bind(this, 3.5));

 // we can rewrite fu by wrapper

 var fu_wrapper = function(limit){
 	return function(limit, item){
 		return item > limit;
 	}.bind(this, limit);
 }

 var result_ver = map([1,3,4,5], fu_wrapper(1));
 ```

46. **Prototype chain is for object property/method, scope chain is for function to find access data/var/function/object**.

47. Dont ever do this below, performance issue.

 ```js
 __proto__
 // NON-STANDARD PROPERTY, THOUGH WIDELY SUPPORT
 dan.__proto__ = person;
 ```

48. Every object eventually proto type to Object object.
49. All `Object` object's prototype has `toString()` method.
50. All `Function` object's prototype is **Empty(anonymous) functio**n, its has `bind`, `call`, and `apply` methods.
51. `for-in` loop **go through every member/method in an object and its prototype**. Be sure to use it only for its object.

 ```js
 var john = { a: 4, b:5 }

 for(var prop in john){
 	if (john.hasOwnProperty(prop)){
 		console.log("This is " + prop + " " + john[prop]);
 	}
 }
 ```

52. `extend` in underscore.js: `_.extend(subclass, ... superclass object)`. It means to extend the property, but may overwrite or not.

53. Avoid using prototype to inherit property/methods, use `for-in` loop to add property/method, check below example instead.

 ```js
 var extend = createAssigner(allKeys);

 function allKeys(obj){
 	if (!obj.isPrototypeOf(Object)) return [];
 	var keys = [];
 	for(var x in obj){
 		keys.push(x);
 	}
 	return keys;
 }

 // initiate, undefinedOnly will only create empty object.
 var createAssigner = function(keysFunc, undefinedOnly){
 	return function(obj){
 		var len = arguments.length
 		if (len < 2 || obj == null) return obj;

 		for (var i = 1; i < len; i++) {
   			var source = arguments[i],
   			keys = KeysFunc(source),
   			l = keys.length;

   			for (var i = 0; i < keys.length; i++) {
     			var key = keys[i];
     			if(obj[key] === void(0) || 
     					!undefinedOnly) obj[key] = source[key];
   			};
 		};

 		return obj;
 	};
 }
 ```
 
54. Function constructor use `this` to point to new object. 	new	: create object, `new Person() === new(function(){ something same as person });`.

55. Function constructor usually only set properties, the object method will set in its prototpye for **gloal use**. Put method to prototype so **only one copy of that method need to initialize**. Otherwise it will copy that function to every new objects, unless you want to customized that function for each created object.

56. What `new` operator internally doing:

 ```js
 function newObject(fn_constrcutor){
 	var params = Array.prototype.slice.call(arguments, 1);
 	
 	var obj = Object.create(fn_constructor.prototype);
 	
 	fn_constructor.apply(obj, params);
 	
 	return obj;
 }
 
 var empty = newObject(function(){});
 var c = newObject(function(a, b){
 	this.a = a;
 	this.b = b;
 }, 1, 2);
 ```
 
57. Only **`Function` and `Object` has prototype, instance not**. prototype is a property to help that function object to build an object via new.  
 [http://stackoverflow.com/questions/9959727/proto-vs-prototype-in-javascript](http://stackoverflow.com/questions/9959727/proto-vs-prototype-in-javascript)

58. Sometimes you might forget a function is a constructor then call it without a `new` keyword. By convention we named that function with **first capitalize letter to distinquish this**.

59. JS engine will try convert String prmitive to String object for you if you access some `String.prototype.method`. ex: `"John".length`. **JS engine looks `String` object for you instead just primitive string**.

60. This is because **JS engine will automatically coeirce from primitive to object for you then `"John".__proto__` is point to `String.prototype`**.

61. Besides String, **JS engine will not coerce for primitive Number to Number object for you. But you can add paranthesis to work around(let JS coerce for you)**.

 ```js
 typeof "1234";
 // string
 typeof new String("1245");
 // object

 Number.prototype.getSelf = function(){
 	return (typeof this);
 };

 (3).getSelf();
 // object

 (3)
 // 3, is a primitive => js not coerce yet.

 (3) === 3
 // true

 3.getSelf();
 // error
 ```

62. **Caveat:** caution to use built-in function constructor(new String, Number) for primitives.

63. Array Object: index as key, value is array[index]. So avoid to use `for-in` loop for iterating the Array.

64. Though `__proto__` is not an standard but popular, you can use `Object.getprototypeOf(obj)` to know its `__proto__`.

65. **Polyfill**: add features that an engine may lack.

66. what `Object.create` do is set the prototype to its first param.

 ```js
 if (!Object.create) {
 	Object.create = function(proto){
 		if (arguments.lenght > 1) 
 			return "Object.create only accepts one argument."

 		// return will be Func {} ...
 		function Func(){  /* construcotr */ };

 		// set prototype.constructor and prototype.
 		Func.prototype = proto;
 		Func.prototype.constructor = Func;

 		return new Func();
 	}
 }
 
 // then instead use apply, manually assign it.
 var obj = function Obj(f, l){
 	this.firstName = f;
 	this.lastname = l;
 };

 var new_obj = Object.create(obj.prototype);
 new_obj.firstName = "First name";
 new_obj.lastName = "last name";
 // or obj.apply(new_obj, ["First name","last name"]);
 ```
 
67. Function name maybe duplicate but not the same if use function expression instead function assignment.

 ```js
 var x = function Func(){
 	console.log("Hi-X");
 };

 // function assignment
 function Func(){
 	console.log("Hi-Func");
 };

 x.prototype === Func.prototype
 // false, even though name are the same, 
 // but actually Func() is a method create in Window object, 
 // which key is also named Func(). 
 // x is a property which point to another Func() object.
 ```

68. In **ECMA6**, `class` is a constructor keyword.

 ```js
 // class still an object, not class in JAVA or C or Ruby
 class Person {
 	constructor(f, l){
 		this.firstName = f;
 		this.LastName = l;
 	}

 	method() {
 		return "Hi " + firstName;
 	}
 }

 var new_pl = new Person("First", "last");

 // use extends to set prototype
 class Baby extends Person {
 	constructor(f, l){
 		// if you need use prototype's constructor to set property
 		super(f, l)
 	}
 }
 ```
 
69. `var p = new (function P(){});` is just function expression, will not registered in current this object. 

70. `function.prototype` is an object. `typeof` is possible `(__proto__)` in its prototype chain, `instanceof`: just father `__proto__`. Better approach: use `Object.prototpye.toString.call(obj);` to list all prototypes in chain.

71. table of `typeof`: 
 
 ```js
 typeof null // bug, forever... === object
 typeof undefined === undefined	

 // typeof possible return string value: string, number, boolean, 
 // undefined, (any object)object, function, symbol.	
 // dont use below...
 typeof new Number(1) // object
 typeof Number(1) // number
 var n = Number(1)
 typeof n // number
 // so be careful, not use typeof if it is too ambiuity
 ```
 [https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/typeof](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/typeof)

72. **Conclusion of `typeof`**: `typeof` only good for knowing the target is `undefined` or has been set. **Better use `Object.prototype.toString.call(obj)` to know obj's superclass**. 

 ```js
 Object.prototype.toString.call([])      // "[object Array]"
 Object.prototype.toString.call({})      // "[object Object]"
 Object.prototype.toString.call(2)       // "[object Number]"
 ```
73. `instanceof` only useful when compare a **customed type obejct**. O.w. useless as `typeof`.

 ```js
 3 instanceof Number // false, 3 is primitive
 new Numbwe(3) instanceof Number // true
 [] instanceof Array // true
 ```

74. If `document` object is not the same, then use the `instanceof` to compare  other object will not have the correct result due to different constructor object.(see below `Func()` vs `var x` example)

 ```js
 var x = function Func(){
 	console.log("Hi-X");
 };

 // function assignment
 function Func(){
 	console.log("Hi-Func");
 };

 x.prototype === Func.prototype
 ```
75. If `'use strict'` is only put inside a function, then **it will switch to strict mode only in that scope**.

76. Jquery is an mutation of Array object, it returns an array, but then overwrite its prototype point to `Jquery.fn` which support JQuery api. 
77. We can provide return a type of object for function constructor, which will create that object extend constructor customed property/methods.

 [https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/new](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/new)

 > The object returned by the constructor function becomes the result of the whole new expression. If the constructor function doesn't explicitly return an object, the object created in step 1 is used instead. (Normally constructors don't return a value, but they can choose to do so if they want to override the normal object creation process.)

 ```js
 // JQuery like array object, with merge
 
 function F(){
 	var b = [];
 	this.x = 100;
 	this.j = 1000;
 	for (var p in this){
 		Object.defineProperty(b, p, {
 			value: this[p]
 		});
 	}
 	return b;
 }
 
 var d = new F();
 d.x === 100;
 d.push(5)
 d.length === 1
 ```
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment