摘要:默認參數(shù)中要為參數(shù)指定默認值,只能如下所示但是這樣有一個問題如果傳進來的值為,則也會賦值變成,所以更加完全的做法是檢測參數(shù)類型中直接可以為任意參數(shù)指定默認值,在已指定默認值的參數(shù)后可以繼續(xù)聲明無默認值參數(shù)是否使用函數(shù)默認值主要依賴于調(diào)用函數(shù)
默認參數(shù)
ES5中要為參數(shù)指定默認值,只能如下所示:
function makeRequst(url, timeout, callback) { timeout = timeout || 2000; callback = callback || function () { } }
但是這樣有一個問題如果timeout傳進來的值為0,則也會賦值變成2000,
所以更加完全的做法是檢測參數(shù)類型
function makeRequst(url, timeout, callback) { timeout = (typeof timeout !== "undefined") ? timeout : 2000; callback = (typeof callback !== "undefined") ? callback : function () { } }
ES6中直接
function makeRequst(url, timeout = 2000, callback = function () { }) { }
可以為任意參數(shù)指定默認值,在已指定默認值的參數(shù)后可以繼續(xù)聲明無默認值參數(shù)
function makeRequst(url, timeout = 2000, callback) { }
是否使用函數(shù)默認值主要依賴于調(diào)用函數(shù)是實參是否全等于undefined
ES5非嚴格模式下,函數(shù)命名參數(shù)的變化會體現(xiàn)在arguments對象中
function mixArgs(first, second) { console.log(first === arguments[0])//true console.log(second === arguments[1])//true first = "c" second= "d" console.log(first === arguments[0])//true console.log(second === arguments[1])//true } mixArgs("a", "b")
而在嚴格模式下,無論參數(shù)如何變化,arguments對象不再隨之改變
function mixArgs(first, second) { "use strict" console.log(first === arguments[0])//true console.log(second === arguments[1])//true first = "c" second = "d" console.log(first === arguments[0])//false console.log(second === arguments[1])//false } mixArgs("a", "b")
如果使用了函數(shù)默認值,則arguments對象的行為將與ES5在嚴格模式下保持一致:arguments對象保持與命名參數(shù)分離(備注:其實這種分離的特性可以將參數(shù)恢復(fù)為初始值)
function mixArgs(first, second="b") { console.log(first === arguments[0])//true console.log(second === arguments[1])//false first = "c" second = "d" console.log(first === arguments[0])//false console.log(second === arguments[1])//false } mixArgs("a")
函數(shù)默認值除了可以給原始值,還可以指定函數(shù),只不過只有未傳入?yún)?shù)需要默認值時才能去調(diào)用些此函數(shù),也就是說默認參數(shù)是在函數(shù)調(diào)用時才求值
指定默認值為函數(shù)不要忘記小括號,如果忘記小括號則傳入的是對函數(shù)的引用而不是函數(shù)調(diào)用的結(jié)果
function getValue(value) { return value + 5 } function add(first, second = getValue(first)) { return first + second } console.log(add(1))//7
函數(shù)參數(shù)有自己的作用域和臨時死區(qū),其與函數(shù)體的作用域是各自獨立的,也就是說參數(shù)的默認值是不可訪問函數(shù)體內(nèi)聲明的變量
處理無命名參數(shù)在函數(shù)命名參數(shù)前添加...三個點表明這是一個不定參數(shù)
function pick(obj, ...keys) { let result = Object.create(null) for (let i = 0, len = keys.length; i < len; i++) { result[keys[i]] = object[keys[i]] } return result }
函數(shù)的length屬性統(tǒng)計的是函數(shù)命名參數(shù)的數(shù)量,不定參數(shù)的加入不會影響length屬性的值
每個函數(shù)最多只能聲明一個不定參數(shù),而且一定要放在所有參數(shù)的末尾
不定參數(shù)不能用于對象字面量setter之中,因為對象字面量setter的參數(shù)有且只能有一個
let obj = { //Uncaught SyntaxError: Setter function argument must not be a rest parameter set name(...value) { console.log(value) } }
看一個有趣的例子:無論是否使用不定參數(shù),arguments對象總是包含所有傳入函數(shù)的參數(shù)
默認參數(shù)和不定參數(shù)的特性同樣適用于Function構(gòu)造函數(shù)
var add = new Function("first", "second=first", "return first+second") console.log(add(1))//2 var pickFirst=new Function("...args","return args[0]") console.log(pickFirst(1,2))//1展開運算符
舉例來說,Math.max可接受任意數(shù)量的參數(shù)并返回最大的那個,但如果傳入的是一個數(shù)組,則只能使用apply
console.log(Math.max(11, 2, 3, 12, 43, 904, 3543, 43)) let values = [11, 2, 3, 12, 43, 904, 3543, 43] console.log(Math.max.apply(Math, values))
使用展開運算符就變得特別簡單了
let values = [11, 2, 3, 12, 43, 904, 3543, 43] console.log(Math.max(...values))
如果你想限定Math.max返回的最小值為0,還可以如下使用
let values = [-11, -2, -3, -12] console.log(Math.max(...values, 0))函數(shù)的name屬性
函數(shù)的name屬性的值不一定引用同名變量,它只是協(xié)助調(diào)用用的額外信息,所以不能使用name屬性的值來獲取函數(shù)的引用
function doSomething() { } console.log(doSomething.name)//doSomething var doSome = function doSomeElse() { } var person = { get firstName() { return "angela" }, sayName: function () { } } console.log(doSome.name)//doSomeElse console.log(person.sayName.name)//sayName console.log(person.firstName.name)//undefined var doThing = function () { } console.log(doThing.bind().name)//bound doThing console.log((new Function()).name)//anonymous函數(shù)的多重用途
JS函數(shù)中有兩個不同的內(nèi)部方法:[[Call]]和[[Construct]]
當(dāng)通過new關(guān)鍵字調(diào)用函數(shù)時,執(zhí)行的是[[Construct]]函數(shù),它負責(zé)創(chuàng)建一個通常被稱作實例的新對象,然后再執(zhí)行函數(shù)體,將this綁定到實例上
如果不是通過new關(guān)鍵字調(diào)用函數(shù),則執(zhí)行[[Call]]函數(shù),從而直接執(zhí)行代碼中的函數(shù)體
不是所有函數(shù)都有[[Construct]]方法,因此不是所有方法都可以通過new來調(diào)用,具有[[Construct]]方法的函數(shù)被統(tǒng)稱為構(gòu)造函數(shù)
ES5中想確定一個函數(shù)是否通過new關(guān)鍵字被調(diào)用
function Person(name) { if (this instanceof Person) { this.name = name } else { throw new Error("必須通過new關(guān)鍵字來調(diào)用") } }
但是上述方法不是絕對完全可靠的,比方說如下調(diào)用就失效了
var person = new Person("angela") var notAPerson = Person.call(person, "Shing")//這樣對于函數(shù)本身是無法區(qū)分是通過Person.Call、Apply還是new調(diào)用得到的實例
ES6中可以如下絕對安全的判定
function Person(name) { //或者typeof new.target===Person if (typeof new.target !== "undefined") { this.name = name } else { throw new Error("必須通過new關(guān)鍵字來調(diào)用") } } var person = new Person("angela") var notAPerson = Person.call(person, "Shing")//拋出錯誤
當(dāng)調(diào)用函數(shù)的[[Construct]]方法時,new.target被賦值為new操作符的目標,如果調(diào)用的是[[Call]]方法,則new.target的值為undefined
在函數(shù)外使用new.target是一個語法錯誤
ES5嚴格模式下,在代碼塊內(nèi)部聲明函數(shù)程序會報錯
在ES6嚴格模式下,可以在代碼塊中聲明函數(shù),塊級函數(shù)聲明會被提升至此代碼塊頂部,超出此塊級作用域,則函數(shù)將不再存在
"use strict" if (true) { console.log(typeof doSomeThing) //function doSomeThing()//---------- function doSomeThing() { console.log("----------") } } console.log(typeof doSomeThing) //undefined
在ES6非嚴格模式下,這些函數(shù)不再提升至代碼塊的頂部而是提升至外圍函數(shù)或全局作用域的頂部
if (true) { console.log(typeof doSomeThing) //function doSomeThing()//---------- function doSomeThing() { console.log("----------") } } console.log(typeof doSomeThing) //function箭頭函數(shù)
箭頭函數(shù)與傳統(tǒng)函數(shù)有如下幾點不同
沒有this、super、arguments和new.target綁定--也就是說箭頭函數(shù)中的this、super、arguments和new.target這些值由外圍最近一層非箭頭函數(shù)決定
不能通過new關(guān)鍵字調(diào)用--因為箭頭函數(shù)沒有[[Construct]]
沒有原型--箭頭函數(shù)不存在prototype屬性
不可以改變this的綁定--函數(shù)內(nèi)的this值不可被改變
不支持arguments對象--只能通過命名參數(shù)和不定參數(shù)來訪問函數(shù)中的參數(shù)
不支持重復(fù)的命名參數(shù)
當(dāng)箭頭函數(shù)只有一個參數(shù)時,可以直接寫參數(shù)名,箭頭緊隨其后,箭頭右側(cè)的表達式被求值后便立即返回,即使沒有顯式的返回語句,
如果要傳入兩個或兩個以上參數(shù)則需要在參數(shù)兩側(cè)添加一對小括號
如果函數(shù)沒有參數(shù),也要在聲明時寫一組沒有內(nèi)容的小括號
let sum = (num1, num2) => num1 + num2 //相當(dāng)于 let sum = function (num1, num2) { return num1 + num2 }尾調(diào)用優(yōu)化
尾調(diào)用指的是函數(shù)作為另一個函數(shù)的最后一條語句被調(diào)用,其實也就是滿足以下三個條件
尾調(diào)用不訪問當(dāng)前棧幀的變量--函數(shù)不是一個閉包
在函數(shù)內(nèi)部,尾調(diào)用是最后一條語句
尾調(diào)用的結(jié)果作為函數(shù)值返回
ES6嚴格模式下,JS引擎才會進行尾調(diào)用自動優(yōu)化
function f(x){ return g(x); }
function factorial(n) { if (n <= 1) { return 1 } else { //無法優(yōu)化,必須在返回后執(zhí)行乘法操作 return n * factorial(n - 1) } } function factorial(n, p = 1) { if (n <= 1) return 1 * p else { let result = n * p; //優(yōu)化后 return factorial(n - 1, result) } }
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/112448.html
摘要:導(dǎo)入模塊的代碼執(zhí)行后,實例化過的模塊被保存在內(nèi)存中,只要另一個語句引用它就可以重復(fù)使用它和的一個重要的限制是它們必須在其它語句和函數(shù)之外使用,也就是說不允許出現(xiàn)在語句中,不能有條件導(dǎo)出或以任何方式動態(tài)導(dǎo)出。 什么是模塊 模塊是自動運行在嚴格模式下并且沒有辦法退出運行的Javascript代碼 在模塊的頂部this的值是undefined 其模塊不支持html風(fēng)格的代碼注釋除非用def...
摘要:導(dǎo)入模塊的代碼執(zhí)行后,實例化過的模塊被保存在內(nèi)存中,只要另一個語句引用它就可以重復(fù)使用它和的一個重要的限制是它們必須在其它語句和函數(shù)之外使用,也就是說不允許出現(xiàn)在語句中,不能有條件導(dǎo)出或以任何方式動態(tài)導(dǎo)出。 什么是模塊 模塊是自動運行在嚴格模式下并且沒有辦法退出運行的Javascript代碼 在模塊的頂部this的值是undefined 其模塊不支持html風(fēng)格的代碼注釋除非用def...
摘要:指數(shù)運算符是可以進行求冪運算的求冪運算符是兩個星號求冪運算符的優(yōu)先級高于其它二元運算符,但是一元運算符的優(yōu)先級高于求冪運算符求冪運算符左側(cè)的一元運算符只能是或者是語法錯誤可以這樣包裹也可以這樣包裹在中可通過方法來檢查給定字符串中是 指數(shù)運算符 Math.pow是可以進行求冪運算的求冪運算符是兩個星號 let result = 5 ** 2 console.log(result) //2...
摘要:指數(shù)運算符是可以進行求冪運算的求冪運算符是兩個星號求冪運算符的優(yōu)先級高于其它二元運算符,但是一元運算符的優(yōu)先級高于求冪運算符求冪運算符左側(cè)的一元運算符只能是或者是語法錯誤可以這樣包裹也可以這樣包裹在中可通過方法來檢查給定字符串中是 指數(shù)運算符 Math.pow是可以進行求冪運算的求冪運算符是兩個星號 let result = 5 ** 2 console.log(result) //2...
閱讀 1128·2021-10-27 14:13
閱讀 2635·2021-10-09 09:54
閱讀 896·2021-09-30 09:46
閱讀 2423·2021-07-30 15:30
閱讀 2165·2019-08-30 15:55
閱讀 3408·2019-08-30 15:54
閱讀 2847·2019-08-29 14:14
閱讀 2771·2019-08-29 13:12