Skip to content

Instantly share code, notes, and snippets.

@1kohei1
Created January 12, 2019 17:23
Show Gist options
  • Save 1kohei1/f217a976dc03fbe65079e6b2aeeed218 to your computer and use it in GitHub Desktop.
Save 1kohei1/f217a976dc03fbe65079e6b2aeeed218 to your computer and use it in GitHub Desktop.
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