<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??一站式輕松地調用各大LLM模型接口,支持GPT4、智譜、豆包、星火、月之暗面及文生圖、文生視頻 廣告
                &emsp;&emsp;在前面的章節中,已陸陸續續介紹了ES6為改良函數而引入的幾個新特性,本章將會繼續講解ES6對函數的其余改進,包括默認參數、元屬性、塊級函數和箭頭函數等。 ## 一、默認參數 &emsp;&emsp;在ES5時代,只能在函數體中定義參數的默認值,而自從ES6引入了默認參數(Default Parameter)后,就能讓參數在聲明時帶上它的默認值,如下代碼所示,func2()函數中的參數默認值在可讀性和簡潔性方面更為優秀。 ~~~ function func1(name) { name = name || "strick"; //ES5的參數默認值 } function func2(name = "strick") { //ES6的參數默認值 } ~~~ **1)undefined** &emsp;&emsp;只有當不給參數傳值或傳入undefined時,才會使用它的默認值。即使傳入和undefined一樣的假值(例如false、null等),也得不到它的默認值,如下所示。 ~~~ function func(name = "strick") { return name; } func(undefined); //"strick" func(false); //false func(null); //null ~~~ **2)位置** &emsp;&emsp;默認參數既可以位于普通參數之前,也可以位于其之后。例如下面的兩個函數,都包含兩個參數,其中一個帶有默認值,依次執行,都能得到預期的結果。 ~~~ function func1(name = "strick", age) { return name; } function func2(name, age = 28) { return age; } func1(undefined); //"strick" func2("strick"); //28 ~~~ **3)默認值** &emsp;&emsp;參數的默認值既可以是簡單的字面量,也可以是復雜的表達式。在每次調用函數時,不僅參數會被重新初始化,默認值如果是表達式的話,還會將其重新計算一次。 ~~~ function expression1(name, full = "pw" + name) { return full; } expression1("strick"); //"pwstrick" expression1("freedom"); //"pwfreedom" ~~~ &emsp;&emsp;在上面的代碼中,調用了兩次expression1()函數,返回的結果互不影響。并且full參數的默認值引用了前面的name參數,這是一種有效的語法,但反之就會報錯,如下所示。 ~~~ function expression2(name = full, full) { return name; } expression2(undefined, "strick"); //拋出未定義的引用錯誤 ~~~ **4)限制** &emsp;&emsp;第一條限制是在包含默認值的參數序列中,不允許出現同名參數。無論同名的是有默認值,亦或是無默認值,都是不允許的,如下所示。 ~~~ function restrict1(name = "strick", name) { } function restrict1(name = "strick", age, age) { } ~~~ &emsp;&emsp;第二條限制是不能在函數體中為默認參數用let或const重新聲明,如下代碼所示,會拋出重復聲明的語法錯誤。 ~~~ function restrict2(name = "strick") { let name = "freedom"; } ~~~ &emsp;&emsp;因為默認參數相當于是用let聲明的變量,所以是不允許重復聲明的。上面代碼中的restrict2()函數,它的name參數的初始化類似于下面這樣。 ~~~ let name = "strick"; ~~~ &emsp;&emsp;參數序列中只要包含了默認參數,那么其它普通參數也會用let聲明。知道這一點后,就能很容易的解釋上一節第二個示例,在調用expression2()函數時會拋出未定義的錯誤原因。函數中的兩個參數的初始化相當于下面這樣。 ~~~ let name = full, full; ~~~ &emsp;&emsp;在[第一篇](https://www.cnblogs.com/strick/p/10161595.html)中曾提到用let聲明的變量,在聲明之前都會被放到臨時死區中,而在此時訪問這些變量就會觸發運行時錯誤。 **5)三個作用域** &emsp;&emsp;根據ES6規范的9.1.2小節可知,當參數序列中包含默認參數時,將會出現三個作用域:參數作用域、函數外層作用域和函數體內作用域。關于這三個作用域需要注意兩點: &emsp;&emsp;(1)函數體內可以修改參數的值,但不能為其重新聲明。 &emsp;&emsp;(2)參數作用域可以訪問外層作用域中的變量,但不能訪問函數體內的變量。 &emsp;&emsp;第一點很好理解,已在上文中做過解釋。關于第二點,可先查看下面的兩個函數。 ~~~ let full = "freedom"; function scope1(name = full) { return name; } scope1(); function scope2(name = en) { let en = "justify"; return name; } scope2(); ~~~ &emsp;&emsp;調用scope1()函數得到的返回值是“freedom”,而調用scope2()函數非但得不到結果,還會拋出en未定義的錯誤。接下來改造scope1()函數,把full變量改成name變量,如下所示。 ~~~ let name = "freedom"; function scope1(name = name) { return name; } ~~~ &emsp;&emsp;此時再次調用scope1()函數,得到的卻是name未定義的錯誤。雖然在外層作用域中包含名為name的變量,但是參數擁有自己的作用域,會先從當前作用域中查找變量,此時的name正處在臨時死區中,因此在訪問它時會報錯。 &emsp;&emsp;除了以上所列的特性之外,在之前的[第三篇](https://www.cnblogs.com/strick/p/10172871.html)的參數解構中,還介紹了解構默認值和參數默認值結合使用時的注意點。 ## 二、函數屬性 **1)name** &emsp;&emsp;通過函數的name屬性可得到它聲明時所用的名稱。ES6規定此屬性既不可寫,也不可枚舉,只允許配置。在不同場景中,它的返回值會不同,具體如下所列,每一條規則后面都給出了相應的示例。 &emsp;&emsp;(1)利用Function構造器創建的函數,它的名稱是“anonymous”。 ~~~ var func = new Function("a", "b", "return a+b;"); func.name; //"anonymous" ~~~ &emsp;&emsp;(2)如果是用匿名函數表達式創建的函數,那么它的名稱就是變量名;如果改用命名函數表達式創建,那么它的名稱就是等號右側的函數名稱。 ~~~ var expression1 = function() { }; expression1.name; //"expression1" var expression2 = function named() { }; expression2.name; //"named" ~~~ &emsp;&emsp;(3)當用bind()方法綁定一個函數時,它的名稱就會加“bound”前綴。 ~~~ function age() { } age.bind(this).name; //"bound age" ~~~ &emsp;&emsp;(4)訪問器屬性包含寫入方法和讀取方法,它們的名稱會分別加“set”和“get”前綴。注意,需要調用Object.getOwnPropertyDescriptor()才能引用這兩個方法。 ~~~ var obj = { get age() { }, set age(value) { } }; var descriptor = Object.getOwnPropertyDescriptor(obj, "age"); descriptor.get.name; //"get age" descriptor.set.name; //"set age" ~~~ &emsp;&emsp;(5)如果對象的方法是用Symbol命名的,那么這個Symbol的描述就是它的名稱。 ~~~ var sym = Symbol("age"), obj = { [sym]: function() {} }; obj[sym].name; //"[age]" ~~~ **2)length** &emsp;&emsp;函數的length屬性可返回形參個數(即聲明時的參數),但它的值會受剩余參數(已在[第二篇](https://www.cnblogs.com/strick/p/10172721.html)中做過介紹)和默認參數的影響,如下代碼所示。 ~~~ (function rest(name, ...args){ }).length; //1 (function rest(name, age = 28){ }).length; //1 (function rest(name, age = 28, school){ }).length; //1 ~~~ &emsp;&emsp;根據上面的代碼可知,形參個數的統計會忽略剩余參數,并且止于默認參數。 ## 三、塊級函數 &emsp;&emsp;ES6允許塊級函數(Block-Level Function)的聲明,即在塊級作用域中聲明函數,而在ES5中如此操作的話,將會拋出語法錯誤的異常。 **1)嚴格模式** &emsp;&emsp;在嚴格模式中,塊級函數的聲明可提升至當前代碼塊的頂部,在代碼塊之外是不可見的,如下代碼所示。 ~~~ "use strict"; (function() { func("strick");   //拋出未定義的引用錯誤 if(true) { func("freedom");   //"freedom" function func(name) { return name; } { func("jane"); //"jane" } } func("justify"); //拋出未定義的引用錯誤 })(); ~~~ &emsp;&emsp;只有在func()函數所處的代碼塊或與之相鄰的代碼塊中,才能被正確調用。 **2)普通模式** &emsp;&emsp;在普通模式(即非嚴格模式)中,只有當塊級函數所在的代碼塊被成功執行后,它的聲明才能被提升至當前腳本文件或函數體的頂部,如下代碼所示。 ~~~ (function() { func("strick"); //拋出未定義的引用錯誤 if(true) { func("freedom"); //"freedom" function func(name) { return name; } { func("jane"); //"jane" } } func("justify"); //"justify" })(); ~~~ &emsp;&emsp;在代碼塊之外調用了兩次func()函數,由于第一次調用時,func()函數所處的代碼塊還未被執行(即還未聲明),因此會拋出未定義的引用錯誤。 ## 四、元屬性 &emsp;&emsp;元屬性(Meta Property)就是非對象的屬性,能夠以屬性訪問的形式讀取特殊的元信息。new.target是由ES6引入的一個元屬性,可檢測一個函數是否與new運算符組合使用,并且只能存在于函數體內。 &emsp;&emsp;在JavaScript中,new是一個關鍵字,而不是一個對象。但當函數作為構造函數被調用時,new.target能夠指向新創建的目標對象;而當函數作為普通函數被調用時,new.target的值為undefined,如下所示。 ~~~ function func1() { typeof new.target; //"function" } new func1(); function func2() { new.target === undefined; //true } func2(); ~~~ &emsp;&emsp;把func1()作為構造函數使用,在其函數體中利用typeof運算符檢測出new.target是一個函數對象;而在func2()函數中,讓new.target和undefined進行了全等比較,得到的結果為true。 ***** > 原文出處: [博客園-ES6躬行記](https://www.cnblogs.com/strick/category/1372951.html) [知乎專欄-ES6躬行記](https://zhuanlan.zhihu.com/pwes6) 已建立一個微信前端交流群,如要進群,請先加微信號freedom20180706或掃描下面的二維碼,請求中需注明“看云加群”,在通過請求后就會把你拉進來。還搜集整理了一套[面試資料](https://github.com/pwstrick/daily),歡迎瀏覽。 ![](https://box.kancloud.cn/2e1f8ecf9512ecdd2fcaae8250e7d48a_430x430.jpg =200x200) 推薦一款前端監控腳本:[shin-monitor](https://github.com/pwstrick/shin-monitor),不僅能監控前端的錯誤、通信、打印等行為,還能計算各類性能參數,包括 FMP、LCP、FP 等。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看