1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

        JavaScript 里的奇葩知識

        共 5957字,需瀏覽 12分鐘

         ·

        2020-12-27 10:11

        作者:原罪
        https://segmentfault.com/a/1190000023941089

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

        1

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

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

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

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

        //?Good?
        const?noop?=?Function.prototype;

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

        2

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

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

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

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

        所以如果您想兼容舊瀏覽器,用?x !== x?來判斷是不是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?{}

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

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

        4

        .call.call?到底在為誰瘋狂打call?

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

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

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

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

        5

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

        function?People()?{}

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

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

        6

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

        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 層時(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

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

        10

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

        var?x?=?1.23?|?0;??//?1

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

        11

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

        const?arr?=?[1,?2,?3];

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

        }

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

        按位操作效率高點(diǎn),代碼也簡潔一些。也可以使用es6的?includes()?。但寫開源庫需要考慮兼容性的道友還是用?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)操作不精確,老生常談了,不過可以接受誤差

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

        14

        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

        正式代碼的原型繼承,不會(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)對象

        const?obj?=?{
        ??a:?{
        ????b:?1
        ??},
        ??c:?2
        };

        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

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

        {}?===?{}?//?false

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

        18

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

        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(2,?3);

        但是您可以用?use strict?嚴(yán)格模式來避免這一行為,這樣?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

        跟誰都不沾親~~

        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?=?{
        ??value:?0,
        ??toString()?{
        ????return?++this.value;
        ??}
        }

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

        通過隱式轉(zhuǎn)換,這樣不是什么難的事情。

        26

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

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

        clearInterval(timeout);
        clearTimeout(interval);

        答案是:YES?。大部分瀏覽器都支持互相清理定時(shí)器,但是建議使用對應(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)致成千上萬的程序出錯(cuò)。

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

        最后

        • 關(guān)注公眾號【前端宇宙】,每日獲取好文推薦
        • 添加微信,入群交流

        瀏覽 67
        點(diǎn)贊
        評論
        收藏
        分享

        手機(jī)掃一掃分享

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

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

        3. <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            欧美久久久久久久久久 | 亚洲另类性爱 | 91午夜在线观看 | 翔田千里被躁57分钟 | 中国精品一级毛片 | 北条麻妃熟女60分 | 哦┅┅快┅┅用力啊┅张素琴 | 午夜影视av | 日韩无码人妻一区二区 | 一级性生活片子 |