中文字幕在线一区二区在线,久久久精品免费观看国产,无码日日模日日碰夜夜爽,天堂av在线最新版在线,日韩美精品无码一本二本三本,麻豆精品三级国产国语,精品无码AⅤ片,国产区在线观看视频

      JavaScript中的with關(guān)鍵字

      時(shí)間:2024-07-24 19:40:31 JavaScript 我要投稿

      JavaScript中的with關(guān)鍵字

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

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

        基本說明

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

      1
      
      with (expression) statement;
      

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

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

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

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

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

        with關(guān)鍵字的弊端

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

        1、性能問題

        2、語義不明,調(diào)試?yán)щy

        性能問題

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

        第一段代碼是沒有使用with關(guān)鍵字:

      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關(guān)鍵字:

      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關(guān)鍵字后了,代碼的性能大幅度降低。第二段代碼的with語句作用到了obj2這個對象上,然后with塊里面訪問的卻是obj對象。有一種觀點(diǎn)是:使用了with關(guān)鍵字后,在with塊內(nèi)訪問變量時(shí),首先會在obj2上查找是否有名為obj的屬性,如果沒有,再進(jìn)行下一步查找,這個過程導(dǎo)致了性能的降低。但是程序性能真正降低的原因真的是這樣嗎?我們修改一下第二段代碼,修改如下:

      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屬性,按照前面說到的觀點(diǎn),訪問a屬性時(shí),是一次性就可以在obj上找到該屬性的,但是為什么代碼性能依舊降低了呢。真正的原因是:使用了with關(guān)鍵字后,JS引擎無法對這段代碼進(jìn)行優(yōu)化。

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

        語義不明,難以調(diào)試

        前面說到除了性能的問題,with還存在的一個缺點(diǎn)語義不明,難以調(diào)試,就是造成代碼的不易閱讀,而且可能造成潛在的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函數(shù)內(nèi),使用了with關(guān)鍵字來訪問傳進(jìn)來的obj對象,然后修改a屬性。當(dāng)傳入o1對象時(shí),因?yàn)閛1對象存在著a屬性,所以這樣沒有問題。傳入o2對象時(shí),在修改a屬性時(shí),由于o2對象沒有a這個屬性,所以被修改的a屬性則變成了全局變量。這就造成了潛在的bug。

        延伸分析

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

      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的。涉及的知識點(diǎn)也比較多:with關(guān)鍵字,this關(guān)鍵字,變量提升等等,我們來一一解釋一下。

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

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

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

      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(tǒng),則進(jìn)一步查找,找到局部變量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
      

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

      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();
      

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

        總結(jié)

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

      【JavaScript中的with關(guān)鍵字】相關(guān)文章:

      淺談如何深入學(xué)習(xí)Javascript中的this關(guān)鍵字04-02

      在Java中執(zhí)行JavaScript代碼04-01

      Javascript中typeof 用法歸納04-01

      perl- javascript中class的機(jī)制03-25

      JavaScript中的三種對象04-01

      抽象語法樹在JavaScript中的應(yīng)用03-25

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

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

      s("download_bottom");

      主站蜘蛛池模板: 天堂Av无码Av一区二区三区| 日本一区二区精品在线观看| 新邵县| 国产成人精品人人做人人爽 | 国产av一区二区三区东北熟女| 囯产精品无码一区二区三区AV| 农安县| 日本一区二区三区小视频| 中国精品久久久久国产| 精品粉嫩国产一区二区三区| 日韩av无卡无码午夜观看| 蒲城县| 斗六市| 国产一区二区三区精品久久呦 | 巩留县| 国产精品一区成人亚洲| 无码三级国产三级在线电影| 国产欧美日本亚洲精品一4区 | 91精品国产91热久久p| av大片在线无码永久免费网址| 辽阳市| 霍林郭勒市| 玉田县| 汤原县| 国产激情视频在线| 沙洋县| 河曲县| 体育| jiZZ国产在线女人水多| 麻豆av一区二区天堂| 井陉县| 草莓视频中文字幕人妻系列| 国内精品久久久久久久亚洲| 亚洲国产成人久久综合三区| 日本高清色惰www在线视频| 亚洲日韩精品AⅤ片无码富二代| 亚洲国产免费av网站| 国产一区二区三区亚洲精品| 国产熟女av一区二区三区四季| 国产亚洲成人精品一区| 亚洲一区二区婷婷久久|