javascript
第一百零二节,JavaScript函数
JavaScript函數
?
學習要點:
?
1.函數聲明
?
2.return返回值
?
3.arguments對象
?
函數是定義一次但卻可以調用或執行任意多次的一段JS代碼。函數有時會有參數,即函數被調用時指定了值的局部變量。函數常常使用這些參數來計算一個返回值,這個值也成為函數調用表達式的值。
?
一.函數聲明
函數對任何語言來說都是一個核心的概念。通過函數可以封裝任意多條語句,而且可以在任何地方、任何時候調用執行。ECMAScript中的函數使用function關鍵字來聲明,后跟一組參數以及函數體。
function關鍵字聲明函數
無參函數:
function box() { //沒有參數的函數alert('只有函數被調用,我才會被之執行'); } box(); //直接調用執行函數有參函數:
如果有參函數在調用時沒有傳參數,會自動賦值參數為undefined
function box(name, age) { //帶參數的函數alert('你的姓名:'+name+',年齡:'+age); } box('李炎恢',28); //調用函數,并傳參?
二.return返回值,關鍵字,給函數定義返回值
帶參和不帶參的函數,都沒有定義返回值,而是調用后直接執行的。實際上,任何函數都可以通過return語句跟后面的要返回的值來實現返回值。
無參定義返回值:
function box() { //沒有參數的函數return '我被返回了!'; //通過return把函數的最終值返回 } alert(box()); //調用函數會得到返回值,然后外面輸出有參定義返回值:
function box(name, age) { //有參數的函數return '你的姓名:'+name+',年齡:'+age;//通過return 把函數的最終值返回 } alert(box('李炎恢', 28)); //調用函數得到返回值,然后外面輸出我們還可以把函數的返回值賦給一個變量,然后通過變量進行操作。
function box(num1, num2) {return num1 * num2; } var num = box(10, 5); //函數得到的返回值賦給變量 alert(num);return語句還有一個功能就是退出當前函數,注意和break的區別。
PS:break用在循環和switch分支語句里。
注意:函數里一旦遇到return返回關鍵字后,下面還有代碼就不會執行了
function box(num) {if (num < 5) return num; //滿足條件,就返回numreturn 100; //返回之后,就不執行下面的語句了 } alert(box(2)); //打印函數變量?
三.arguments對象
ECMAScript函數不介意傳遞進來多少參數,也不會因為參數不統一而錯誤。實際上,函數體內可以通過arguments對象來接收傳遞進來的參數。
也就是函數可以不設置形式參數,在函數里可以用arguments來接收實際參數的傳參,
arguments以數組下標方式類獲取實際參數
function box() {return arguments[0]+' | '+arguments[1]; //arguments[0],將調用函數時傳的參數,當做數組索引下標的方式獲取到//arguments[0],就是獲取傳參的第一個參數1//arguments[1],就是獲取傳參的第二個參數2 } alert(box(1,2,3,4,5,6)); //傳遞參數arguments對象的length屬性可以得到參數的數量。
也就是arguments對象的length屬性可以檢查到,調用函數時傳了多少個實際參數
function box() {return arguments.length; //得到6 } alert(box(1,2,3,4,5,6));我們可以利用length這個屬性,來智能的判斷有多少參數,然后把參數進行合理的應用。比如,要實現一個加法運算,將所有傳進來的數字累加,而數字的個數又不確定。
function box() {var sum = 0;if (arguments.length == 0) return sum; //如果沒有參數,返回sum變量for(var i = 0;i < arguments.length; i++) { //如果有,就統計有多少位參數,循環對應次數,然后就累加sum = sum + arguments[i];}return sum; //返回累加結果26 } alert(box(5,9,12));ECMAScript中的函數,沒有像其他高級語言那種函數重載功能。
function box(num) {return num + 100; } function box (num) { //會執行這個函數return num + 200; } alert(box(50)); //返回結果?
函數補充,Function類型
學習要點:
1.函數的聲明方式
2.作為值的函數
3.函數的內部屬性
4.函數屬性和方法
?
在ECMAScript中,Function(函數)類型實際上是對象。每個函數都是Function類型的實例,而且都與其他引用類型一樣具有屬性和方法。由于函數是對象,因此函數名實際上也是一個指向函數對象的指針。
?
一.函數的聲明方式
1.普通的函數聲明
function box(num1, num2) {return num1+ num2; } alert(box(1,2));2.使用變量初始化函數
var box= function(num1, num2) {return num1 + num2; }; alert(box(1,2));3.使用Function構造函數【不推薦】
var box= new Function('num1', 'num2' ,'return num1 + num2'); alert(box(1,2));PS:第三種方式我們不推薦,因為這種語法會導致解析兩次代碼(第一次解析常規ECMAScript代碼,第二次是解析傳入構造函數中的字符串),從而影響性能。但我們可以通過這種語法來理解"函數是對象,函數名是指針"的概念。
?
二.作為值的函數
ECMAScript中的函數名本身就是變量,所以函數也可以作為值來使用。也就是說,不僅可以像傳遞參數一樣把一個函數傳遞給另一個函數,而且可以將一個函數作為另一個函數的結果返回。
將一個函數當做參數傳給另外一個函數
function box(sumFunction, num) { //定義函數boxreturn sumFunction(num); //返回執行box函數,并傳出參數10 }function sum(num) { //定義函數sumreturn num + 10; //返回傳入參數加10 }var result = box(sum, 10); //執行函數box,將sum函數當做參數傳入box函數 alert(result);?
三.函數內部屬性
在函數內部,有兩個特殊的對象:arguments和this。arguments是一個類數組對象,包含著傳入函數中的所有參數,主要用途是保存函數參數。但這個對象還有一個名叫callee的屬性,該屬性是一個指針,指向擁有這個arguments對象的函數。
階乘遞歸
function box(num) {if (num <= 1) {return 1;} else {return num * box(num-1); //4 * 3 * 2 * 1=24階乘,遞歸 } } alert(box(4));?
對于階乘函數一般要用到遞歸算法,所以函數內部一定會調用自身;如果函數名不改變是沒有問題的,但一旦改變函數名,內部的自身調用需要逐一修改。為了解決這個問題,我們可以使用arguments.callee來代替。
callee屬性,該屬性是一個指針,指向擁有這個arguments對象的函數
function box(num) {if (num <= 1) {return 1;} else {return num * arguments.callee(num-1); //使用callee來執行box函數自身 } } alert(box(4));?
this屬性
函數內部另一個特殊對象是this,其行為與Java和C#中的this大致相似。換句話說,this引用的是函數,數據以執行操作的對象,或者說函數調用語句所處的那個作用域。PS:當在全局作用域中調用函數時,this對象引用的就是window。
window是一個對象,而且是js里面最大的對象,是最外圍的對象
alert(window); //打印對象,返回[object Window] alert(typeof window); //查看對象類型this在全局作用域中時this就是window對象
alert(this); //返回[object Window]全局變量都是Window的屬性
//全局變量都是Window的屬性 var color = "紅色的"; //聲明一個變量 alert(window.color); //通過Window屬性打印變量通過this打印全局變量
var color = "紅色的"; //聲明一個變量 alert(this.color); //通過this屬性打印變量,全局變量也可以通過this來打印,也等同于通過Window打印window.color = "紅色"; 相當于var color = "紅色";
window.color = "紅色"; //相當于var color = "紅色"; alert(color); var color = "紅色"; alert(color);?
this在對象里面的指向的對象本身
注意:this在對象里面的指向的對象本身
var box = { //創建一個對象color:"藍色", //對象里的一個字段,等同于一個變量saycolor:function(){ //對象里的一個方法,也就是匿名函數alert(this.color); //此時的this指向的是box對象本身, } }; box.saycolor(); //執行對象里面的saycolor()方法?
this在函數與對象里面的區別
window.color = '紅色的'; //或者var color = '紅色的';也行var box = { //創建一個對象color : '藍色的' //定義一個字段 };function sayColor() { //創建一個普通函數alert(this.color); //打印this下面的color } sayColor(); //此時執行函數,函數里的this指向的window,所以打印的window.color //返回紅色的 box.sayColor = sayColor; //將sayColor()函數,追加到box對象里,此時sayColor()函數里的this就在對象里了,this在對象里指向的就是對象本身 box.sayColor(); //此時執行box對象里的sayColor()函數,打印的就是對象里面的color //返回藍色的?
四.函數屬性和方法
ECMAScript中的函數是對象,因此函數也有屬性和方法。每個函數都包含兩個屬性:length和prototype。其中,length屬性表示函數希望接收的命名參數的個數。
length屬性表示函數希望接收的命名參數的個數。
function box(name,age){alert(name + age); } box(5,6); //執行函數 alert(box.length); //查看函數希望接收的命名參數的個數 //返回2?
prototype屬性
?
PS:對于prototype屬性,它是保存所有實例方法的真正所在,也就是原型。這個屬性,我們將在面向對象一章詳細介紹。而prototype下有兩個方法:apply()和call(),每個函數都包含這兩個非繼承而來的方法。這兩個方法的用途都在特定的作用域中調用函數,實際上等于設置函數體內this對象的值。簡單一句話理解就是apply()和call()方法可以冒充一個函數執行
?apply()方法冒充另外一個函數,第一個參數是要冒充的函數的作用域,第二個參數是數組類型的形式參數,用于接收函數的形式參數
冒充一個函數,實際上就是將要冒充的函數指向指定的作用域去執行
function box(num1,num2){ //原函數return num1 + num2; } alert(box(1,2)); //執行打印返回數據function saybox(num1,num2){ //冒充box函數執行,實際就是調用了box函數return box.apply(this,[num1,num2]); //用apply方法冒充另外一個函數,第一個參數是要冒充的函數的作用域,此時this就是box函數的作用域,this就是window//第二個參數是數組類型的形式參數,用于接收函數的形式參數 } alert(saybox(3,4)); //執行冒充函數 第二個參也可以用arguments屬性類接收實際參數function box(num1,num2){ //原函數return num1 + num2; } alert(box(1,2)); //執行打印返回數據function saybox(num1,num2){ //冒充box函數執行,實際就是調用了box函數return box.apply(this,arguments); //用apply方法冒充另外一個函數,第一個參數是要冒充的函數的作用域,此時this就是box函數的作用域,this就是window//第二個參也可以用arguments屬性類接收實際參數 } alert(saybox(3,4)); //執行冒充函數
?
call()方法于apply()方法相同,他們的區別僅僅在于接收參數的方式不同。對于call()方法而言,第一個參數是作用域,沒有變化,變化只是其余的參數都是直接傳遞給函數的。
冒充一個函數,實際上就是將要冒充的函數指向指定的作用域去執行
和apply區別在于后面的傳參
function box(num1,num2){ //原函數return num1 + num2; } alert(box(1,2)); //執行打印返回數據function saybox(num1,num2){ //冒充box函數執行,實際就是調用了box函數return box.call(this,num1,num2); //用call方法冒充另外一個函數,第一個參數是要冒充的函數的作用域,此時this就是box函數的作用域,this就是window//作用域后面的參數是形式參數,原函數有多少個形式參數,就需要寫多少個形式參數 } alert(saybox(3,4)); //執行冒充函數事實上,傳遞參數并不是apply()和call()方法真正的用武之地;它們經常使用的地方是能夠擴展函數賴以運行的作用域。
var color = '紅色的'; //或者window.color = '紅色的';也行var box = {color : '藍色的' };function sayColor() {alert(this.color); } sayColor(); //執行sayColor()函數,此時函數里的this作用域是window,所以打印的是紅色 sayColor.call(this); //這句話的意思是冒充this下的sayColor函數執行,作用域在window sayColor.call(window); //這句話的意思是冒充window下的sayColor函數執行,作用域在window sayColor.call(box); //這句話的意思是冒充box對象下的sayColor函數執行,作用域在box,冒充一個函數,實際上就是將要冒充的函數指向指定的作用域去執行
這個例子是之前作用域理解的例子修改而成,我們可以發現當我們使用call(box)方法的時候,sayColor()方法的運行環境已經變成了box對象里了。
使用call()或者apply()來擴充作用域的最大好處,就是對象不需要與方法發生任何耦合關系(耦合,就是互相關聯的意思,擴展和維護會發生連鎖反應)。也就是說,box對象和sayColor()方法之間不會有多余的關聯操作,比如 box.sayColor = sayColor;也就是不需要將方法追加到對象里
?轉載于:https://www.cnblogs.com/adc8868/p/6019809.html
總結
以上是生活随笔為你收集整理的第一百零二节,JavaScript函数的全部內容,希望文章能夠幫你解決所遇到的問題。