久經沙場的前輩們,寫了無數代碼,踩了無數的坑。但有些坑,可能一生也踩不到摸不着,由於根本不會發生在業務代碼裏~~javascript
Function.prototype 居然是個函數類型。而自定義函數的原型倒是對象類型。java
typeof Function.prototype === 'function'; // true function People() {} typeof People.prototype === 'object'; // true
因此咱們設置空函數能夠這麼作:webpack
// Good const noop = Function.prototype; // Bad const noop = () => {};
一個變量真的會不等於自身嗎?es6
const x = NaN; x !== x // true
這是目前爲止js語言中惟一的一個不等於本身的數據。爲何?由於NaN表明的是一個範圍,而不是一個具體的數值。
在早期的 isNaN() 函數中,即便傳入字符串,也會返回true,這個問題已經在es6中修復。web
isNaN('abc'); // true Number.isNaN('abc') // false
因此若是您想兼容舊瀏覽器,用 x !== x 來判斷是否是NaN,是一個不錯的方案。瀏覽器
構造函數若是return了新的數據模塊化
// 不返回 function People() {} const people = new People(); // People {} // 返回數字 function People() { return 1; } const people = new People(); // People {} // 返回新對象 function Animal() { return { hello: 'world', }; } const animal = new Animal(); // { hello: 'world' }
在實例化構造函數時,返回非對象類型將不生效函數
.call.call 到底在爲誰瘋狂打call?oop
function fn1() { console.log(1); } function fn2() { console.log(2); } fn1.call.call(fn2); // 2
因此 fn1.call.call(fn2) 等效於 fn2.call(undefined)
。並且不管您加多少個 .call,效果也是同樣的。this
實例後的對象也能再次實例嗎?
function People() {} const lili = new People(); // People {} const lucy = new tom.constructor(); // People {}
由於lili的原型鏈指向了People的原型,因此經過向上尋找特性,最終在 Peopel.prototype 上找到了構造器即 People自身
setTimeout 嵌套會發生什麼奇怪的事情?
console.log(0, Date.now()); setTimeout(() => { console.log(1, Date.now()); setTimeout(() => { console.log(2, Date.now()); setTimeout(() => { console.log(3, Date.now()); setTimeout(() => { console.log(4, Date.now()); setTimeout(() => { console.log(5, Date.now()); setTimeout(() => { console.log(6, Date.now()); }); }); }); }); }); });
在0-4層,setTimeout的間隔是1ms,而到第5層時,間隔至少是4ms。
es6函數帶默認參數時將生成聲明做用域
var x = 10; function fn(x = 2, y = function () { return x + 1 }) { var x = 5; return y(); } fn(); // 3
函數表達式(非函數聲明)中的函數名不可覆蓋
const c = function CC() { CC = 123; return CC; }; c(); // Function
固然,若是設置var CC = 123
,加聲明關鍵詞是能夠覆蓋的。
嚴格模式下,函數的this是undefined而不是Window
// 非嚴格 function fn1() { return this; } fn1(); // Window // 嚴格 function fn2() { 'use strict'; return this; } fn2(); // undefined
對於模塊化的通過webpack打包的代碼,基本都是嚴格模式的代碼。
取整操做也能夠用按位操做
var x = 1.23 | 0; // 1
由於按位操做只支持32位的整型,因此小數點部分所有都被拋棄
indexOf() 不須要再比較數字
const arr = [1, 2, 3]; // 存在,等效於 > -1 if (~arr.indexOf(1)) { } // 不存在,等效於 === -1 !~arr.indexOf(1);
按位操做效率高點,代碼也簡潔一些。也可使用es6的includes()。但寫開源庫須要考慮兼容性的道友仍是用indexOf比較好
getter/setter 也能夠動態設置嗎?
class Hello { _name = 'lucy'; getName() { return this._name; } // 靜態的getter get id() { return 1; } } const hel = new Hello(); hel.name; // undefined hel.getName(); // lucy // 動態的getter Hello.prototype.__defineGetter__('name', function() { return this._name; }); Hello.prototype.__defineSetter__('name', function(value) { this._name = value; }); hel.name; // lucy hel.getName(); // lucy hel.name = 'jimi'; hel.name; // jimi hel.getName(); // jimi
0.3 - 0.2 !== 0.1 // true
class語法糖究竟是怎麼繼承的?
function Super() { this.a = 1; } function Child() { // 屬性繼承 Super.call(this); this.b = 2; } // 原型繼承 Child.prototype = new Super(); const child = new Child(); child.a; // 1
正式代碼的原型繼承,不會直接實例父類,而是實例一個空函數,避免重複聲明動態屬性
const extends = (Child, Super) => { const fn = function () {}; fn.prototype = Super.prototype; Child.prototype = new fn(); Child.prototype.constructor = Child; };
腦殼空了,收集中,可遇不可求。。。