<dfn id="w48us"></dfn><ul id="w48us"></ul>
  • <ul id="w48us"></ul>
  • <del id="w48us"></del>
    <ul id="w48us"></ul>
  • JavaScript中的with關鍵字

    時間:2024-07-24 19:40:31 JavaScript 我要投稿

    JavaScript中的with關鍵字

      JS中的with關鍵字有什么作用么?下面YJBYS小編帶大家一起來了解!

      說起js中的with關鍵字,很多小伙伴們的第一印象可能就是with關鍵字的作用在于改變作用域,然后最關鍵的一點是不推薦使用with關鍵字。聽到不推薦with關鍵字后,我們很多人都會忽略掉with關鍵字,認為不要去管它用它就可以了。但是有時候,我們在看一些代碼或者面試題的時候,其中會有with關鍵字的相關問題,很多坑是你沒接觸過的,所以還是有必要說說with這一個關鍵字。

      基本說明

      在js高級程序設計中是這樣描述with關鍵字的:with語句的作用是將代碼的作用域設置到一個特定的作用域中,基本語法如下:

    1
    
    with (expression) statement;
    

      使用with關鍵字的目的是為了簡化多次編寫訪問同一對象的工作,比如下面的例子:

    1
    2
    3
    
    var qs = location.search.substring(1);
    var hostName = location.hostname;
    var url = location.href;
    

      這幾行代碼都是訪問location對象中的屬性,如果使用with關鍵字的話,可以簡化代碼如下:

    1
    2
    3
    4
    5
    
    with (location){
        var qs = search.substring(1);
        var hostName = hostname;
        var url = href;
    }
    

      在這段代碼中,使用了with語句關聯了location對象,這就以為著在with代碼塊內部,每個變量首先被認為是一個局部變量,如果局部變量與location對象的某個屬性同名,則這個局部變量會指向location對象屬性。注意:在嚴格模式下不能使用with語句。

      with關鍵字的弊端

      前面的基本說明中,我們可以看到with的作用之一是簡化代碼。但是為什么不推薦使用呢?下面我們來說說with的缺點:

      1、性能問題

      2、語義不明,調試困難

      性能問題

      首先說說性能問題,關于使用with關鍵字的性能問題,首先我們來看看兩段代碼:

      第一段代碼是沒有使用with關鍵字:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    
    function func() {
        console.time("func");
        var obj = {
            a: [1, 2, 3]
        };
        for (var i = 0; i < 100000; i++) {
            var v = obj.a[0];
        }
        console.timeEnd("func");//0.847ms
    }
    func();
    

      第二段代碼使用了with關鍵字:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    
    function funcWith() {
        console.time("funcWith");
        var obj = {
            a: [1, 2, 3]
        };
        var obj2 = { x: 2 };
        with (obj2) {
            console.log(x);
            for (var i = 0; i < 100000; i++) {
                var v = obj.a[0];
            }
        }
        console.timeEnd("funcWith");//84.808ms
    }
    funcWith();
    

      在使用了with關鍵字后了,代碼的性能大幅度降低。第二段代碼的with語句作用到了obj2這個對象上,然后with塊里面訪問的卻是obj對象。有一種觀點是:使用了with關鍵字后,在with塊內訪問變量時,首先會在obj2上查找是否有名為obj的屬性,如果沒有,再進行下一步查找,這個過程導致了性能的降低。但是程序性能真正降低的原因真的是這樣嗎?我們修改一下第二段代碼,修改如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    
    function funcWith() {
        console.time("funcWith");
        var obj = {
            a: [1, 2, 3]
        };
        with (obj) {
            for (var i = 0; i < 100000; i++) {
                var v = a[0];
            }
        }
        console.timeEnd("funcWith");//88.260ms
    }
    funcWith();
    

      這段代碼將with語句作用到了obj對象上,然后直接使用a訪問obj的a屬性,按照前面說到的觀點,訪問a屬性時,是一次性就可以在obj上找到該屬性的,但是為什么代碼性能依舊降低了呢。真正的原因是:使用了with關鍵字后,JS引擎無法對這段代碼進行優化。

      JS引擎在代碼執行之前有一個編譯階段,在不使用with關鍵字的時候,js引擎知道a是obj上的一個屬性,它就可以靜態分析代碼來增強標識符的解析,從而優化了代碼,因此代碼執行的效率就提高了。使用了with關鍵字后,js引擎無法分辨出a變量是局部變量還是obj的一個屬性,因此,js引擎在遇到with關鍵字后,它就會對這段代碼放棄優化,所以執行效率就降低了。使用with關鍵字對性能的影響還有一點就是js壓縮工具,它無法對這段代碼進行壓縮,這也是影響性能的一個因素。

      語義不明,難以調試

      前面說到除了性能的問題,with還存在的一個缺點語義不明,難以調試,就是造成代碼的不易閱讀,而且可能造成潛在的bug。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    
    function foo(obj) {
        with (obj) {
            a = 2;
        }
    }
    
    var o1 = {
        a: 3
    };
    var o2 = {
        b: 3
    };
    
    foo(o1);
    console.log(o1.a); // 2
    
    foo(o2);
    console.log( o2.a ); // undefined
    console.log( a ); // 2
    

      這段代碼很容易理解了,在foo函數內,使用了with關鍵字來訪問傳進來的obj對象,然后修改a屬性。當傳入o1對象時,因為o1對象存在著a屬性,所以這樣沒有問題。傳入o2對象時,在修改a屬性時,由于o2對象沒有a這個屬性,所以被修改的a屬性則變成了全局變量。這就造成了潛在的bug。

      延伸分析

      前面說了那么多,相信大家已經理解了為什么不推薦使用with關鍵字以及可能存在的問題。下面我們來看看一些更復雜的情況,看下面的代碼:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    
    var obj = {
        x: 10,
        foo: function () {
            with (this) {
                var x = 20;
                var y = 30;
                console.log(y);//30
            }
        }
    };
    obj.foo();
    console.log(obj.x);//20
    console.log(obj.y);//undefined
    

      在這段代碼中,分別輸出30,20,undefined的。涉及的知識點也比較多:with關鍵字,this關鍵字,變量提升等等,我們來一一解釋一下。

      1、this關鍵字關于this關鍵字的文章google上面相當多,這里不再贅述,我們只需記住一點:this關鍵字始終指向調用函數的對象。在這里,foo函數中,this指向的就是obj對象。因此在with(this)語句塊里面,可以直接通過x變量來訪問obj的x屬性。

      2、變量提升js中的變量提升也是一個經常遇到的問題,我們可以簡單理解成在js中,變量聲明會被提升到函數的頂部,盡管有的時候,它是在后面聲明的。

      所以上面的代碼可以解析為:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    
    var obj = {
        x: 10,
        foo: function () {
            var x;//聲明局部變量x
            var y;//聲明局部變量y
            with (obj) {
                x = 20;//訪問變量x,在obj上找到x,則修改為20
                y = 30;//訪問變量y,在obj上找不到y,則進一步查找,找到局部變量y,修改為30
                console.log(y);//30//直接輸出局部變量y,
            }
        }
    };
    obj.foo();
    console.log(obj.x);//20,obj.x已被修改為20
    console.log(obj.y);//undefined,obj不存在y屬性,則為undefined
    

      上面的注釋中,解釋了代碼的執行過程,相信大家已經理解了為什么會出處30,20,undefined的原因。有興趣的同學可以看看下面這段代碼:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    
    ({
    x: 10,
    foo: function () {
        function bar() {
            console.log(x);
            console.log(y);
            console.log(this.x);
        }
        with (this) {
            var x = 20;
            var y = 30;
            bar.call(this);
        }
    }
    }).foo();
    

      這段代碼會輸出什么?為什么呢?

      總結

      本文總結了with語句的特點和弊端,總的來說,強烈不推薦使用with關鍵字。其實在日常編碼中,我們只需要知道不去使用with就可以了,但是有的時候我們可能會遇到一些關于with的奇奇怪怪的問題,想要找出真正的原因,就要深入理解with關鍵字,這有助于我們去深入學習JS這門語言,同時也是學習JS的一個樂趣。歡迎小伙伴們來交流!!

    【JavaScript中的with關鍵字】相關文章:

    淺談如何深入學習Javascript中的this關鍵字04-02

    在Java中執行JavaScript代碼04-01

    Javascript中typeof 用法歸納04-01

    perl- javascript中class的機制03-25

    JavaScript中的三種對象04-01

    抽象語法樹在JavaScript中的應用03-25

    JavaScript中push(),join() 函數實例詳解03-31

    詳解JavaScript中的splice()使用方法04-01

    javascript面向對象中的對象怎么理解03-30

    主站蜘蛛池模板: 精品成人一区二区三区四区| 无码精品人妻一区| 久久精品国产WWW456C0M| 国内精品久久久久久99| 久久精品国产亚洲Aⅴ香蕉| 99re这里只有精品6| 永久免费精品影视网站| 国产成人综合精品一区| 岛国精品一区免费视频在线观看| 久久久久无码精品国产app| 久久精品国产免费一区| 久久亚洲精品无码AV红樱桃| 欧美精品成人3d在线| 97精品伊人久久久大香线蕉| 国产精品无码专区| 最新国产成人精品2024| 国产午夜精品一本在线观看| 国产精品99久久久久久人| 无码囯产精品一区二区免费 | 中文字幕亚洲精品无码| 精品成人av一区二区三区| 91无码人妻精品一区二区三区L | 久久精品18| 国产L精品国产亚洲区久久| 久久91精品国产91久久麻豆| 国产精品无码专区| 精品欧洲av无码一区二区三区 | 久久成人国产精品二三区| 国产精品内射后入合集| 精品黑人一区二区三区| 日韩精品久久久肉伦网站| 亚洲国产精品无码AAA片| 亚洲精品美女久久久久99小说| 日本熟妇亚洲欧美精品区 | 国产日韩精品中文字无码| 日韩精品无码AV成人观看| 老司机亚洲精品影院| 久久国产乱子伦免费精品| 久久精品中文无码资源站| 久久久久久亚洲Av无码精品专口| 久久Av无码精品人妻系列|