Created
January 12, 2019 17:23
-
-
Save 1kohei1/f217a976dc03fbe65079e6b2aeeed218 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var a = new String('abc'); | |
a.__proto__ === String.prototype; // true | |
- a.__proto__.constructor === String; // true | |
// JS internal [[Class]] can be revealed by calling Object.prototype.toString | |
Object.prototype.toString.call([1,2,3]); // "[object Array]" | |
Object.prototype.toString.call(/regex-literal/i); // "[object RegExp]" | |
Object.prototype.toString.call(null); // "[object Null]" | |
Object.prototype.toString.call(undefined); // "[object Undefined]" | |
// There are no Null() nor Undefined(), but still there are internal constructor | |
Object.prototype.toString.call(true); // "[object Boolean]" | |
Object.prototype.toString.call(false); // "[object Boolean]" | |
Object.prototype.toString.call({}); // "[object Object]" | |
Object.prototype.toString.call(1); // "[object Number]" | |
// Object.prototype.toStrng is used in lodash. https://github.com/lodash/lodash/blob/aa1d7d870d9cf84842ee23ff485fd24abf0ed3d1/.internal/getTag.js | |
// They have custom logic to return "[object Null]" and "[object Undefined]". Maybe this is because the implementation may be different across JS engine? | |
// The gotcha point for using object wrapper | |
a = new Boolean(false); | |
a ? true : false; // true | |
a.valueOf() ? true : false; // false. | |
// In similar manner, | |
a = new Number(0); | |
a ? true : false; // true | |
// Since they are now the object, not the primitive. So when they are evaluated, they use object evaluation. | |
new Boolean(false).valueOf() ? true : false; // false | |
new Number(0).valueOf() ? true : false; // false | |
// You have to use .valueOf() function | |
// Array | |
Array(1,2,3); // [1,2,3] | |
new Array(1,2,3); // [1,2,3] | |
[1,2,3]; // [1,2,3] | |
// It doesn't matter if you use new keyword with Array. Internally, it does the same thing. | |
// The Array constructor has a special form where if only one number argument is passed, create an array with that length | |
Array(3); // [empty * 3] Does not create [3] | |
// This happens only when the arguments length is 1 and the value is a number. | |
Array(null); // [null] | |
Array(undefined); // [undefined] | |
Array({}); // [{}] | |
Array(true); // [true] | |
Array(false); // [false] | |
// When array contains at least one empty slot, it's called sparse array. You can create a sparse array by setting bigger number to the arr.length and calling Array constructor with one number argument, or deleting an existing element. | |
a = new Array(3); | |
b = [undefined, undefined, undefined]; | |
c = []; | |
c.length = 3; | |
a; // [empty * 3]; | |
b; // [undefined, undefined, undefined]; | |
c; // [empty * 3]; | |
delete b[1]; | |
b; // [undefined, empty, empty]; | |
// More confusingly, some of the function behave the same way while other functions do not. | |
a = Array(3); | |
b = [undefined, undefined, undefined]; | |
a.join('-'); // -- | |
b.join('-'); // -- | |
a.map((v, i) => i); // [empty * 3] | |
b.map((v, i) => i); // [0,1,2] | |
// join behaves the same way, mean while .map returns the different result | |
// So if you want to create an array with specified length and filled with udnefined, this is how you do it. | |
a = Array.apply(null, { length: 3 }); // [undefined, undefined, undefined] | |
// .apply spreads the argsArray, so internall it's iterating each element in the second args and pass it to Array constructor. So it's equivalent calling Array(undefined, undefined, undefined) | |
// However, if you do the same thing with .call function, it doesn't work. | |
a = Array.call(null, { length: 3 }); // [{ length: 3}] | |
// This is beause apply spreads the second argument and call the callsite function with spread arguments. So the third argument is ignored. | |
a = Array.apply(null, { length: 3 }, 1, 2); | |
// On the other hand, .call just passes whatever passed to the parameter after the first. | |
Array.call(null, undefined, undefined, undefined); // [undefined, undefined, undefined] | |
// The difference is so obvious in the Syntax: | |
// function.apply(thisArg, [argsArray]); | |
// function.call(thisArg, arg1, arg2, ...); | |
// The common thing with .apply and .call is it binds the first argument to this. |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment