<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          JavaScript 奇葩知識(shí)大全

          共 11606字,需瀏覽 24分鐘

           ·

          2020-11-08 06:38

          點(diǎn)擊上方“逆鋒起筆”,公眾號(hào)回復(fù) pdf
          領(lǐng)取大佬們推薦的學(xué)習(xí)資料

          作者:原罪

          https://segmentfault.com/a/1190000023941089

          久經(jīng)沙場(chǎng)的前輩們,寫(xiě)了無(wú)數(shù)代碼,踩了無(wú)數(shù)的坑。但有些坑,可能一輩子也踩不到摸不著,因?yàn)楦静粫?huì)發(fā)生在業(yè)務(wù)代碼里~~

          1

          Function.prototype 竟然是個(gè)函數(shù)類型。而自定義函數(shù)的原型卻是對(duì)象類型。

          typeof Function.prototype === 'function';  // true

          function People() {}
          typeof People.prototype === 'object';      // true

          所以我們?cè)O(shè)置空函數(shù)可以這么做:

          // Good 
          const noop = Function.prototype;

          // Bad
          const noop = () => {};

          2

          一個(gè)變量真的會(huì)不等于自身嗎?

          const x = NaN;
          x !== x  // true

          這是目前為止 js 語(yǔ)言中唯一的一個(gè)不等于自己的數(shù)據(jù)。為什么?因?yàn)?nbsp;NaN 代表的是一個(gè)范圍,而不是一個(gè)具體的數(shù)值。在早期的 isNaN() 函數(shù)中,即使傳入字符串,也會(huì)返回 true ,這個(gè)問(wèn)題已經(jīng)在 es6 中修復(fù)。

          isNaN('abc');       // true
          Number.isNaN('abc'// false

          所以如果您想兼容舊瀏覽器,用 x !== x 來(lái)判斷是不是NaN,是一個(gè)不錯(cuò)的方案。

          3

          構(gòu)造函數(shù)如果 return了新的數(shù)據(jù)

          // 不返回
          function People() {}
          const people = new People();   // People {}

          // 返回?cái)?shù)字
          function People() {
            return 1;
          }
          const people = new People();   // People {}

          // 返回新對(duì)象
          function Animal() {
            return {
              hello'world',
            };
          }
          const animal = new Animal();  // { hello: 'world' }

          在實(shí)例化構(gòu)造函數(shù)時(shí),返回非對(duì)象類型將不生效

          4

          .call.call 到底在為誰(shuí)瘋狂打call?

          function fn1() {
            console.log(1);
          }

          function fn2() {
            console.log(2);
          }

          fn1.call.call(fn2); // 2

          所以 fn1.call.call(fn2) 等效于 fn2.call(undefined)。而且無(wú)論您加多少個(gè) .call,效果也是一樣的。

          5

          實(shí)例后的對(duì)象也能再次實(shí)例嗎?

          function People() {}

          const lili = new People();            // People {}
          const lucy = new tom.constructor();   // People {}

          因?yàn)?nbsp;lili 的原型鏈指向了 People 的原型,所以通過(guò)向上尋找特性,最終在 Peopel.prototype 上找到了構(gòu)造器即 People 自身

          6

          setTimeout 嵌套會(huì)發(fā)生什么奇怪的事情?

          console.log(0Date.now());

          setTimeout(() => {
            console.log(1Date.now());
            setTimeout(() => {
              console.log(2Date.now());
              setTimeout(() => {
                console.log(3Date.now());
                setTimeout(() => {
                  console.log(4Date.now());
                  setTimeout(() => {
                    console.log(5Date.now());
                    setTimeout(() => {
                      console.log(6Date.now());
                    });
                  });
                });
              });
            });
          });

          在0-4層,setTimeout 的間隔是 1ms ,而到第 5 層時(shí),間隔至少是 4ms 。

          7

          es6函數(shù)帶默認(rèn)參數(shù)時(shí)將生成聲明作用域

          var x = 10;

          function fn(x = 2, y = function (return x + 1 }) {
            var x = 5;
            return y();
          }

          fn();   // 3

          8

          函數(shù)表達(dá)式(非函數(shù)聲明)中的函數(shù)名不可覆蓋

          const c = function CC() {
            CC = 123;
            return CC;
          };

          c(); // Function

          當(dāng)然,如果設(shè)置 var CC = 123 ,加聲明關(guān)鍵詞是可以覆蓋的。

          9

          嚴(yán)格模式下,函數(shù)的 this 是 undefined 而不是 Window

          // 非嚴(yán)格
          function fn1() {
            return this;
          }
          fn1(); // Window

          // 嚴(yán)格
          function fn2() {
            'use strict';
            return this;
          }
          fn2(); // undefined

          對(duì)于模塊化的經(jīng)過(guò)webpack打包的代碼,基本都是嚴(yán)格模式的代碼。

          10

          取整操作也可以用按位操作

          var x = 1.23 | 0;  // 1

          因?yàn)榘次徊僮髦恢С?2位的整型,所以小數(shù)點(diǎn)部分全部都被拋棄

          11

          indexOf() 不需要再比較數(shù)字

          const arr = [123];

          // 存在,等效于 > -1
          if (~arr.indexOf(1)) {

          }

          // 不存在,等效于 === -1
          !~arr.indexOf(1);

          按位操作效率高點(diǎn),代碼也簡(jiǎn)潔一些。也可以使用es6的 includes() 。但寫(xiě)開(kāi)源庫(kù)需要考慮兼容性的道友還是用 indexOf 比較好

          12

          getter/setter 也可以動(dòng)態(tài)設(shè)置嗎?

          class Hello {
            _name = 'lucy';
           
            getName() {
              return this._name;
            }
            
            // 靜態(tài)的getter
            get id() {
              return 1;
            }
          }

          const hel = new Hello();

          hel.name;       // undefined
          hel.getName();  // lucy

          // 動(dòng)態(tài)的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

          13

          0.3 - 0.2 !== 0.1  // true

          浮點(diǎn)操作不精確,老生常談了,不過(guò)可以接受誤差

          0.3 - 0.2 - 0.1 <= Number.EPSILON // true

          14

          class 語(yǔ)法糖到底是怎么繼承的?

          function Super() {
            this.a = 1;
          }

          function Child() {
            // 屬性繼承
            Super.call(this);
            this.b = 2;
          }
          // 原型繼承
          Child.prototype = new Super();

          const child = new Child();
          child.a;  // 1

          正式代碼的原型繼承,不會(huì)直接實(shí)例父類,而是實(shí)例一個(gè)空函數(shù),避免重復(fù)聲明動(dòng)態(tài)屬性

          const extends = (Child, Super) => {
            const fn = function () {};
            
            fn.prototype = Super.prototype;
            Child.prototype = new fn();
            Child.prototype.constructor = Child;
          };

          15

          es6居然可以重復(fù)解構(gòu)對(duì)象

          const obj = {
            a: {
              b1
            },
            c2
          };

          const { a: { b }, a } = obj;

          一行代碼同時(shí)獲取 a 和 a.b 。在a和b都要多次用到的情況下,普通人的邏輯就是先解構(gòu)出 a ,再在下一行解構(gòu)出 b 。

          16

          判斷代碼是否壓縮居然也這么秀

          function CustomFn() {}

          const isCrashed = typeof CustomFn.name === 'string' && CustomFn.name === 'CustomFn';

          17

          對(duì)象 === 比較的是內(nèi)存地址,而 >= 將比較轉(zhuǎn)換后的值

          {} === {} // false

          // 隱式轉(zhuǎn)換 toString()
          {} >= {}  // true

          18

          intanceof 的判斷方式是原型是否在當(dāng)前對(duì)象的原型鏈上面

          function People() {}
          function Man() {}
          Man.prototype = new People();
          Man.prototype.constructor = Man;

          const man = new Man();
          man instanceof People;    // true

          // 替換People的原型
          People.prototype = {};
          man instanceof People;    // false

          如果您用es6的class的話,prototype原型是不允許被重新定義的,所以不會(huì)出現(xiàn)上述情況

          19

          Object.prototype.__proto__ === null// true

          這是原型鏈向上查找的最頂層,一個(gè) null

          20

          parseInt 太小的數(shù)字會(huì)產(chǎn)生 bug

          parseInt(0.00000000454);  // 4
          parseInt(10.23);          // 10

          21

          1 + null          // 1
          1 + undefined     // NaN

          Number(null)      // 0
          Number(undefined// NaN

          22

          arguments 和形參是別名關(guān)系

          function test(a, b{
            console.log(a, b); // 2, 3
            
            arguments[0] = 100;
            arguments[1] = 200;
            
            console.log(a, b); // 100, 200
          }
          test(23);

          但是您可以用 use strict 嚴(yán)格模式來(lái)避免這一行為,這樣 arguments 就只是個(gè)副本了。

          23

          void 是個(gè)固執(zhí)的老頭

          void 0 === undefined          // true
          void 1 === undefined          // true
          void {} === undefined         // true
          void 'hello' === undefined    // true
          void void 0 === undefined     // true

          跟誰(shuí)都不沾親~~

          24

          try/catch/finally 也有特定的執(zhí)行順序

          function fn1() {
            console.log('fn1');
            return 1;
          }

          function fn2() {
            console.log('fn2');
            return 2;
          }

          function getData() {
            try {
              throw new Error('');
            } catch (e) {
              return fn1();
            } finally {
              return fn2();
            }
          }

          console.log(getData());

          // 打印順序: 'fn1', 'fn2', 2

          在 try/catch 代碼塊中,如果碰到 return xxyyzz; 關(guān)鍵詞,那么 xxyyzz 會(huì)先執(zhí)行并把值放在臨時(shí)變量里,接著去執(zhí)行 finally 代碼塊的內(nèi)容后再返回該臨時(shí)變量。如果 finally 中也有 return aabbcc ,那么會(huì)立即返回新的數(shù)據(jù) aabbcc 。

          25

          是否存在這樣的變量 x ,使得它等于多個(gè)數(shù)字?

          const x = {
            value0,
            toString() {
              return ++this.value;
            }
          }

          x == 1 && x == 2 && x == 3;    // true

          通過(guò)隱式轉(zhuǎn)換,這樣不是什么難的事情。關(guān)注公眾號(hào) 逆鋒起筆,回復(fù) pdf,下載你需要的各種學(xué)習(xí)資料。

          26

          clearTimeout 和 clearInterval 可以互換~~~~使用嗎

          var timeout = setTimeout(() => console.log(1), 1000);
          var interval = setInterval(() => console.log(2), 800);

          clearInterval(timeout);
          clearTimeout(interval);

          答案是:YES 。大部分瀏覽器都支持互相清理定時(shí)器,但是建議使用對(duì)應(yīng)的清理函數(shù)。

          27

          下面的打印順序是?

          setTimeout(() => {
            console.log(1);
          }, 0);

          new Promise((resolve) => {
            console.log(2);
            resolve();
          }).then(() => console.log(3));

          function callMe() {
            console.log(4);
          }

          (async () => {
            await callMe();
            console.log(5);
          })();

          答案是:2, 4, 3, 5, 1

          主線任務(wù):2,4


          微任務(wù):3,5
          宏任務(wù):1


          28

          null 是 object 類型,但又不是繼承于 Object ,它更像一個(gè)歷史遺留的 bug 。鑒于太多人在用這個(gè)特性,修復(fù)它反而會(huì)導(dǎo)致成千上萬(wàn)的程序出錯(cuò)。

          typeof null === 'object';              // true
          Object.prototype.toString.call(null);  // [object Null]
          null instanceof Object;                // false

          腦袋空了,想到再加。。。


          一行能裝逼的 JavaScript 代碼
          14個(gè) JavaScript 代碼優(yōu)化技巧
          11 個(gè) JavaScript 技巧
          36 個(gè)助你成為專家需要掌握的 JavaScript 概念

          點(diǎn)個(gè)『在看』支持下 

          瀏覽 37
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  一区二区三区四区免费观看 | 一本久道AV一区二区三区 | 大香蕉视频更多资源 | 日逼大香蕉 | 国产精华7777777 |