摘要:一函數(shù)沒有函數(shù)重載函數(shù)參數(shù)對象,類數(shù)組對象正是由于函數(shù)體內(nèi)使用對象接收傳遞的參數(shù),所以即便你定義的函數(shù)只接收兩個(gè)參數(shù),在調(diào)用函數(shù)時(shí)也未必一定要傳遞兩個(gè)參數(shù)。
一、JavaScript函數(shù)沒有函數(shù)重載 1.函數(shù)參數(shù)arguments對象,類數(shù)組對象
正是由于函數(shù)體內(nèi)使用arguments對象接收傳遞的參數(shù),所以即便你定義的函數(shù)只接收兩個(gè)參數(shù),在調(diào)用函數(shù)時(shí)也未必一定要傳遞兩個(gè)參數(shù)。
2.函數(shù)重載在其他語言中如Java,所謂函數(shù)重載就是方法名相同參數(shù)不同的所有方法,因?yàn)樵贘ava中只要函數(shù)簽名(接受的參數(shù)類型和數(shù)量)不同,就認(rèn)為是不同的函數(shù)。但是在JavaScript中函數(shù)沒有簽名,所以做不到真正的函數(shù)重載
3.使用arguments對象來彌補(bǔ)沒有函數(shù)重載的缺憾function doAdd(){ if(arguments.length == 1){ return arguments[0]+10; }else if(arguments.length == 2){ return arguments[0]+arguments[1]; }else{ let sum = 0; for(let i = 0; i < arguments.length; i++){ sum += arguments[i]; } return sum; } }二、函數(shù)聲明與函數(shù)表達(dá)式 1.函數(shù)聲明語法
function 函數(shù)名(參數(shù):可選) { 函數(shù)體 }
如果函數(shù)在函數(shù)體內(nèi),或者位于程序的最頂部的話,那它就是一個(gè)函數(shù)聲明
2.函數(shù)表達(dá)式function 函數(shù)名(可選)(參數(shù):可選) { 函數(shù)體 }
如果函數(shù)作為表達(dá)式的一部分那么該函數(shù)就是函數(shù)表達(dá)式;
創(chuàng)建一個(gè)function關(guān)鍵字后沒有標(biāo)識(shí)符的函數(shù),這種情況創(chuàng)建的函數(shù)叫匿名函數(shù)
解析器會(huì)率先讀取函數(shù)聲明,并使其在執(zhí)行任何代碼之前可訪問;而函數(shù)表達(dá)式則必須等到執(zhí)行器執(zhí)行到它所在的代碼行,才會(huì)真正被解釋執(zhí)行
sayHello(); //hello function sayHello(){ console.log("hello"); }
上述代碼不會(huì)報(bào)錯(cuò),因?yàn)樵诖a開始執(zhí)行之前,解析器就已經(jīng)通過一個(gè)名為函數(shù)聲明提升的過程讀取并將函數(shù)聲明添加到執(zhí)行環(huán)境中
sayHello(); //報(bào)錯(cuò) var sayHello = function(){ console.log("hello"); }
上述代碼會(huì)產(chǎn)生錯(cuò)誤,因?yàn)楹瘮?shù)位于一個(gè)賦值語句中,在執(zhí)行到函數(shù)所在語句之前,變量sayHello中不會(huì)保存對函數(shù)的引用
三、遞歸 1.什么是遞歸函數(shù)遞歸函數(shù)是在一個(gè)函數(shù)中調(diào)用自身所構(gòu)成的
function recursion(num){ if(num <= 1){ return 1; } else{ return num * recursion(num-1); } }
上述函數(shù)表面上看沒什么問題,但是如果做如下操作就會(huì)出問題
var temp = recursion; recursion = null; temp(10); //報(bào)錯(cuò):recursion不是個(gè)函數(shù)
第一句代碼temp指向了原始函數(shù),recursion不再指向原始函數(shù),調(diào)用temp(10)的時(shí)候用到了recursion(num-1),但是recursion已經(jīng)不再指向原始函數(shù),所以運(yùn)行報(bào)錯(cuò)
2.arguments.callee上述情況使用arguments.callee來解決問題,arguments.callee是一個(gè)指向正在執(zhí)行的函數(shù)的指針,使用arguments.callee來代替函數(shù)名更保險(xiǎn)
function recursion(num){ if(num <= 1){ return 1; } else{ return num * arguments.callee(num-1); } }3.命名函數(shù)表達(dá)式
var recursion = (function recur(num){ if(num <= 1){ return 1; } else{ return num * recur(num-1); } })
上述代碼中即便把函數(shù)賦值給另一個(gè)變量,函數(shù)的名字recur仍然有效,所以不會(huì)影響遞歸
四、閉包 1.閉包的作用域鏈閉包是指有權(quán)訪問另一個(gè)函數(shù)作用域中的變量的函數(shù)
function createComparisonFunction(propertyName){ return function(object1,object2){ var value1 = object1[propertyName]; var value2 = object2[propertyName]; if(value1 < value2){ return -1; } else if(value1 > value2){ return 1; } else{ return 0; } } } var compare = createComparisonFunction("name"); var result = compare({name:"Nicholas"},{name:"Greg"}); compare = null;
在匿名函數(shù)從createComparisonFunction()中被返回后,它的作用域鏈被初始化為包含createComparisonFunction()函數(shù)的活動(dòng)對象和全局變量對象。createComparisonFunction()函數(shù)執(zhí)行完畢后,其執(zhí)行環(huán)境的作用域鏈會(huì)被銷毀但是它的活動(dòng)對象不會(huì)被銷毀,因?yàn)槟涿瘮?shù)的作用域鏈仍然在引用這個(gè)活動(dòng)對象;直到匿名函數(shù)被銷毀后,createComparisonFunction()的活動(dòng)對象才會(huì)被銷毀
閉包只能取得包含函數(shù)中任何變量的最后一個(gè)值,閉包所保存的是整個(gè)變量對象,而不是某個(gè)特殊的變量
function createFunctions(){ var result = new Array(); for(var i = 0; i < 10; i++){ result[i] = function(){ return i; }; } return result; } var result = createFunctions(); result.forEach(function(func){ console.log(func()); //10 })
上述代碼每個(gè)函數(shù)都會(huì)返回10,因?yàn)槊總€(gè)函數(shù)的作用域鏈中都保存著createFunctions()函數(shù)的活動(dòng)對象,所以它們引用的都是同一個(gè)變量i。當(dāng)createFunctions()函數(shù)返回后,變量i的值是10,此時(shí)每個(gè)函數(shù)都引用著保存變量i的同一個(gè)變量對象,所以每一個(gè)函數(shù)內(nèi)部的i的值都是10。如果上述代碼中的var i改成let i就會(huì)出現(xiàn)預(yù)期的效果,因?yàn)閘et聲明的變量i屬于for循環(huán)塊級作用域中不屬于createFunctions()函數(shù)的活動(dòng)對象
function createFunctions(){ var result = new Array(); for(var i = 0; i < 10; i++){ result[i] = function(num){ return function(){ return num; } }(i); } return result; } var result = createFunctions(); result.forEach(function(func){ console.log(func()); //10 })
把i作為參數(shù)傳給num,使得result數(shù)組中的每個(gè)函數(shù)都有自己的num變量副本
五、關(guān)于this 1.this對象this對象是在運(yùn)行時(shí)基于函數(shù)的執(zhí)行環(huán)境綁定的,在全局函數(shù)中this等于window,而當(dāng)函數(shù)作為某個(gè)對象的方法調(diào)用時(shí),this等于那個(gè)對象。不過,匿名函數(shù)的執(zhí)行環(huán)境具有全局性,因此其this對象通常指向window
var name = "The Window"; var object = { name: "The Object", getNameFunc: function(){ return function(){ return this.name; } } } console.log(object.getNameFunc()()); //The Window
var name = "The Window"; var object = { name: "The Object", getNameFunc: function(){ var that = this; return function(){ return that.name; } } } console.log(object.getNameFunc()()); //The Object2.this綁定規(guī)則 默認(rèn)綁定
最常用的函數(shù)調(diào)用類型:獨(dú)立函數(shù)調(diào)用
function foo(){ console.log(this.a); } var a = 2; foo(); //2
上述代碼中,this.a被解析成了全局變量a,這是因?yàn)楹瘮?shù)調(diào)用時(shí)應(yīng)用了this的默認(rèn)綁定,因此this指向全局對象。雖然this的綁定規(guī)則完全取決于調(diào)用位置,但是只有foo()運(yùn)行在非嚴(yán)格模式下,默認(rèn)綁定才能綁定到全局對象;嚴(yán)格模式下與foo()調(diào)用位置無關(guān),this會(huì)綁定到undefined
隱式綁定function foo(){ console.log(this.a); } var obj = { a:2, foo:foo }; obj.foo(); //2
當(dāng)foo函數(shù)被調(diào)用時(shí),調(diào)用位置會(huì)使用obj上下文來引用函數(shù),當(dāng)函數(shù)引用有上下文對象時(shí),隱式綁定規(guī)則會(huì)把函數(shù)調(diào)用中的this綁定到這個(gè)上下文對象,因此this.a和obj.a是一樣的
一個(gè)常見的this綁定問題就是隱式綁定的函數(shù)會(huì)丟失綁定對象,從而應(yīng)用默認(rèn)綁定規(guī)則
function foo(){ console.log(this.a); } var obj = { a:2, foo:foo }; var bar = obj.foo; //函數(shù)別名 var a = "global"; bar(); //"global"
雖然bar是obj.foo的一個(gè)引用,但是實(shí)際上它引用的是foo函數(shù)本身,因此此時(shí)的bar()其實(shí)是一個(gè)不帶任何修飾的函數(shù)調(diào)用,因此應(yīng)用了默認(rèn)綁定
顯式綁定使用call,apply以及bind方法進(jìn)行顯示綁定
function foo(){ console.log(this.a); } var obj = { a: 2 } foo.call(obj); //2new綁定
使用new來調(diào)用函數(shù)被稱為構(gòu)造函數(shù)調(diào)用,這種函數(shù)調(diào)用會(huì)自動(dòng)執(zhí)行如下操作:
創(chuàng)建一個(gè)全新的對象
這個(gè)新對象會(huì)被進(jìn)行原型連接
這個(gè)新對象會(huì)綁定到函數(shù)調(diào)用的this
如果函數(shù)沒有返回其他對象,那么new表達(dá)式中的函數(shù)調(diào)用會(huì)自動(dòng)返回這個(gè)新對象
function foo(a){ this.a = a; } var bar = new foo(2); console.log(bar.a); //23.判斷this
函數(shù)是否在new中調(diào)用(new綁定)?如果是的話,this綁定的是新創(chuàng)建的對象。var bar = new foo();
函數(shù)是否通過call,apply,bind(顯示綁定)調(diào)用?如果是的話,this綁定的是指定的對象。var bar = foo.call(obj);
函數(shù)是否在某個(gè)上下文對象中調(diào)用(隱式綁定)?如果是的話,this綁定的是那個(gè)上下文對象。var bar = obj.foo();
如果都不是的話使用默認(rèn)綁定。如果在嚴(yán)格模式下,就綁定到undefined,否則綁定到全局對象。var bar = foo();
參考文章:
深入理解JavaScript系列
JavaScript高級程序設(shè)計(jì)
你不知道的JavaScript
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/97483.html
摘要:基礎(chǔ)鞏固基礎(chǔ)總結(jié)使用已經(jīng)好幾年了,由于工作主要是做服務(wù)端開發(fā),在工作中逐漸發(fā)現(xiàn)的使用范圍原來越廣泛。這里要注意,務(wù)必將基礎(chǔ)部分掌握牢靠,磨刀不誤砍柴功,只有將基礎(chǔ)部分掌握并建立起系統(tǒng)的知識(shí)體系,在后面學(xué)習(xí)衍生的其他模式才能游刃有余。 基礎(chǔ)鞏固:JavaScript基礎(chǔ)總結(jié) 使用JavaScript已經(jīng)好幾年了,由于工作主要是做服務(wù)端開發(fā),在工作中逐漸發(fā)現(xiàn)JavaScript的使用范圍原...
摘要:在定義函數(shù)的作用域外調(diào)用,得到的返回仍然是函數(shù)創(chuàng)建時(shí)所在的作用域的局部變量。這是因?yàn)樗诘哪涿瘮?shù)的閉包中存放的是第一行的,而不是在循環(huán)中獲得的的當(dāng)前值。 原文: http://pij.robinqu.me/JavaScript_Core/JavaScript_Basics/Function.html 源代碼: https://github.com/RobinQu/Pr...
摘要:之前寫過一篇天學(xué)通前端開發(fā),內(nèi)容主要講的就是前端學(xué)習(xí)路徑,今天再來寫一篇零基礎(chǔ)的學(xué)習(xí)路徑,希望能幫編程零基礎(chǔ)的前端愛好者指明方向。十框架三選一,零基礎(chǔ)的初學(xué)者強(qiáng)烈推薦,如果是后臺(tái)轉(zhuǎn)前端推薦,如果技術(shù)型前端,推薦。 之前寫過一篇26天學(xué)通前端開發(fā),內(nèi)容主要講的就是前端學(xué)習(xí)路徑,今天再來寫一篇零基礎(chǔ)的JavaScript學(xué)習(xí)路徑,希望能幫編程零基礎(chǔ)的前端愛好者指明方向。 一、開發(fā)環(huán)境和Ja...
摘要:變量定義變量使用關(guān)鍵字變量名變量名可以任意取名,但要遵循命名規(guī)則變量必須使用字母下劃線或者美元符開始。語法參數(shù)說明在消息對話框中要顯示的文本返回值值。返回值點(diǎn)擊確定按鈕,文本框中的內(nèi)容將作為函數(shù)返回值。 簡述 本系列將持續(xù)更新Javascript基礎(chǔ)部分的知識(shí),誰都想掌握高端大氣的技術(shù),但是我覺得沒有一個(gè)扎實(shí)的基礎(chǔ),我認(rèn)為一切高階技術(shù)對我來講都是過眼云煙,要成為一名及格的前端工程師,必...
摘要:用和包裹的內(nèi)容,稱為字符串。關(guān)系運(yùn)算符用于進(jìn)行比較的運(yùn)算符。強(qiáng)制依賴于,非強(qiáng)制依賴于。使用場合全局環(huán)境構(gòu)造函數(shù)對象的方法閉包閉包是指有權(quán)訪問另一個(gè)函數(shù)作用域中的變量的函數(shù)。所有全局對象函數(shù)以及變量均自動(dòng)成為對象的成員。 1 什么是JavaScript JavaScript一種直譯式腳本語言,一種基于對象和事件驅(qū)動(dòng)并具有安全性的客戶端腳本語言;也是一種廣泛應(yīng)用客戶端web開發(fā)的腳本語言。...
摘要:數(shù)組創(chuàng)建數(shù)組數(shù)組字面量使用構(gòu)造函數(shù)數(shù)組本質(zhì)上是所以要判斷是不是數(shù)組,需要通過判斷。數(shù)組長度使用屬性獲取元素的個(gè)數(shù)。例如函數(shù)的對象就是這樣 原文: http://pij.robinqu.me/JavaScript_Core/JavaScript_Basics/Array.html 源代碼: https://github.com/RobinQu/Programing-In-...
閱讀 2106·2021-11-23 10:06
閱讀 3456·2021-11-11 16:54
閱讀 3337·2019-08-29 17:31
閱讀 3563·2019-08-29 17:05
閱讀 2166·2019-08-26 13:36
閱讀 2155·2019-08-26 12:17
閱讀 520·2019-08-26 12:12
閱讀 1668·2019-08-26 10:19