【JS學習筆記】9.JavaScript函數基礎(內置函數、函數基本用法、做用域、回調函數、匿名函數)

內置函數、函數基本用法

內置函數

特定計算eval();

計算表達式的結果,支持簡單表達式,帶變量表達式,條分支表達式以及用於解析JSON格式字符串javascript

例:前端

var str="5+5";
		console(eval(str));

		var exp=prompt('請輸入一個表達式:');
		var x=5,y=5;
		var result=eval(exp);
		console.log(result);

類型轉換函數

1.parseInt()
2.parseFloat();java

在個人第5篇筆記JavaScript數據類型轉換有詳細的描述.數組

判斷函數

1.isNaN():函數

做用:檢查其參數是否非數字(注意是檢查是否爲非數字,非數字,非數字)。
若是是非數字就返回true(意思就是若是這個參數不是數字類型的就返回true),
若是不是非數字就返回false(意思就是若是這個參數是數字,就返回false)。學習

2.isFinite():this

判斷是不是有限數字(或者能夠轉換有限數字),若是是則返回true,若是是NaN、或者是正負無窮大數則返回false。編碼

編解碼函數

其意思爲:對特殊字符串進行編碼以及對編碼過的字符串進行解碼。url

encodeURI,decodeURI

使用ISO8859-1的encodeURI,decodeURI:spa

ISO8859-1:每一個UTF-8的漢字編碼成3個16進制字節,如:%字節1,%字節2,%字節3

例:

var str="我是jackson";
		var s1=encodeURI(str); //編碼
		console.log(s1); //%E6%88%91%E6%98%AFjackson
		var s2=decodeURI(s1);//解碼
		console.log(s2);//'我是jackson'
escape、unescape

escape、unescape使用的是unicode

unicode:每一個UTF-8的漢字被編碼成一個雙字節16進制轉義字符,如:%u****,中文的範圍是%u4e00至%u9fa5

例:

var s3=escape(str); //編碼
		console.log(s3); //%u6211%u662Fjackson
		var s4=unescape(s3);//解碼
		console.log(s4);//'我是jackson'

二者區別:escape會對雙字節和符號";/;@&=+$,-_.~*’()"進行轉換,而encodeURI不會

函數基礎

建立、調用函數

建立方法

funchiton 函數名(參數1,參數2.....){
	函數體;
}

建立函數時的參數,稱爲形參。

調用方法:

函數名(參數1,參數2.....);

調用函數時的參數,稱爲實參

定義一無參個函數

function calcsum(){
			var sum=0;
			for(i=1;i<=100;i++){
				sum+=i;
			};
			console.log(sum);
		};
		// 調用函數
		calcsum();

定義單個形參的函數

function calcsum2(n){//n爲形參
			var sum=0;
			for(i=1;i<=n;i++){
				sum+=i;
			};
			console.log('從1到'+n+'之和爲:'+sum);			
		};
		// 調用函數
		calcsum2(1000);//1000爲實參

定義多個形參的函數

function calcsum3(m,n){//m,n爲形參
			var sum=0;
			for(i=m;i<=n;i++){
				sum+=i;
			};
			console.log('從'+m+'到'+n+'之和爲:'+sum);			
		};

		// 調用函數
		calcsum3(1000);

函數的用法

1.在JavaScript中,實參的個數能夠和形參個數不想等
能夠看一下案例

function show(name,age){
			console.log('我是的姓名是:' +name + ',年齡爲'+age);
		};
		
		show('jackson',26);//我是的姓名是:jackson,年齡爲26 
			
		show('jackson');//我是的姓名是:jackson,年齡爲undefined
		
		show();//我是的姓名是:undefined,年齡爲undefined
		
		show('jackson',26,'男');//我是的姓名是:jackson,年齡爲26 

2.JavaScript,中沒有重載的概念,若是函數同名後面的函數會把前面的函數覆蓋掉

注:在其餘語言中,會有重載的概念,即函數名相同,參數個數不一樣的多個同名函數

例:

function calc(num1,num2,num3){
			console.log(num1*num2*num3);
		};

		function calc(num1,num2){
					console.log(num1+num2);
		};

		calc(3,5);//8
		calc(2,2,3);//4
		calc(4);//NaN
		calc(4,4,4,3);//8

函數返回值

函數執行後能夠返回一個結果,稱爲函數的返回值
使用return關鍵字來返回函數執行後的結果值

function calcSum(num1,num2){
			// console.log(num1+num2);
			var sum=num1+num2;
			return sum;//使用return關鍵字返回函數執行後的結果
		};
		var result=calcSum(3,5);
		console.log(result*2);
		console.log(result/2);

若是return後面沒有返回值,或者沒有使用return關鍵字,則默認返回undefined

function calcSum2(num1,num2){
			console.log(num1-num2);
		};
		calcSum2(5,2);//3
		var result=calcSum2(5,2);
		console.log(result);//undefined

return關鍵字的做用:

1.回函數的執行結果
2.結束函數的執行

例:

function calcSum3(num1,num2){
			console.log(num1+num2);
			return;
			console.log('return後面的代碼!');//return後面的代碼都不會執行
		};

		calcSum3(7,2);

練習

1.計算從到1指定數字之和,最多統計到8的總和。

function calcSum4(num){
			var sum=0;
			for(var i = 1;i<=num;i++){
				if(i>8){//若是大於8,直接返回當前和,再也不執行。
					return sum;
				};
				sum+=i;
			};
			return sum;
		};

		console.log(calcSum4(7));//28
		console.log(calcSum4(8));//36
		console.log(calcSum4(9));//36

2.計算兩數之和,若是總和大於20,則直接中止,不然輸出總和

function calcSum5(num1,num2){
			var sum=num1+num2;
			if(sum>20){
				return;
			};
			console.log(sum);
		};

		calcSum5(3,16);//19
		calcSum5(4,18);//無輸出*/

		//練習1:求個數的最大值
		/*function max(num1,num2){ if(num1>num2){ return num1; }else if(num2>num1){ return num2; }else{ return '兩數相等'; }; } var x=prompt('請輸入第一個數'); var y=prompt('請輸入第二個數字'); var maxNumber=max(x,y); document.write('最大值爲:'+ maxNumber ); 

函數的參數

對函數的參數進行處理:

function calcSum(num1,num2){
			//若是參數爲undefined、null、NaN時,則默認設置爲0
			/*if(!num1){ num1=0; } if(!num2){ num2=0; } num1=num1||0; num2=num2||0; //若是參數爲非空字符串,則提示用戶將進行拼接 if(isNaN(num1)||isNaN(num2)){ console.log('將進行拼接操做:'); }; var sum=num1+num2; console.log(sum); }; calcSum(3,6);//9 calcSum(5);//undefined calcSum(5,null);//5 calcSum(5,"");//'5' calcSum(5,NaN);//NaN calcSum(5,'hello');//5hello 

變量的做用域

即變量能夠在上面位置使用
分類:局部變量、全局變量

局部變量:在函數內聲明的變量,只能在該函數內訪問,函數運行結束,變量自動銷燬。
全局變量:只要不是在函數內部聲明的變量,在任何位置均可以訪問,當全部頁面關閉時銷燬。

注:在函數內沒用使用var聲明的,而且直接賦值的變量,也是會提高爲全局變量的

全局變量
var name='jackson';//全局變量,在任何位置均可以訪問
		console.log(name);//jackson

		function show1(){
			console.log(name);
		};
		show1();//jackson
		function show2(){
			console.log(name);
		};
		show2();//jackson
局部變量
function show3(){
			var age=26; //局部變量,只有在該函數內纔可用,函數結束後就會銷燬
			console.log('name:'+name+' age:'+age)
		};
		show3();//
		function show4(){
			console.log('name:'+name+' age:'+age)
		};
		show4();//報錯:age is not defined,由於show4找不到age,age在show3使用完後,就自動銷燬了
function show5(){
			sex='male';
			//函數內建立的全局變量,即在函數內部未使用var聲明,直接賦值的變量,也是全局變量。 *通常不建議怎麼寫
			console.log('name:'+name+' sex:'+sex);
		}
		show5();//name:jackson sex:male 
		function show6(){
			console.log('name:'+name+' sex:'+sex);
		}
		show6();//name:jackson sex:male
就近原則

若是局部變量和全局變量同名,默認訪問的是局部變量,若是要訪問全局變量,必須使用window前綴在必定條件下,也可使用this前綴

var hobby='前端';
		function show(){
			var hobby='吃飯';
			console.log('局部變量:'+hobby);//局部變量:吃飯
			console.log('全局變量:'+window.hobby);//全局變量:前端
			console.log('全局變量:'+this.hobby);//全局變量:前端

		};
		show();
JavaScript中沒有塊級做用域的概念

JavaScript中沒有塊級做用域的概念 ,只要不是在函數中定義的變量,都是全局變量,在其餘語言中,一對花括號{}就是一個代碼塊,在代碼塊中定義的變量在代碼塊外是沒法訪問的。

在ES6中已經可使用let關鍵字進行定義變量,支持塊級的做用域。

function show(){
			for(var i=1;i<=10;i++){
				var name='Jakcson';//局部變量
				console.log(name+'轉圈圈+'+i)
			};
			console.log(name);//Jakcson,能夠輸出,JAVASCRIPT中沒有塊級做用域,只有全局和局部之分,其餘語言會以花括號分割代碼塊。
		};
		show();
		console.log(name);//沒有輸出
		*/
		//在ES6中可使用let定義塊級做用域的變量
		/*function show2(){ for(var i=1;i<=10;i++){ // var name='Jakcson';//局部變量 let name='CYA' console.log(name+'轉圈圈+'+i) }; console.log(name);//沒法輸出,let }; show2(); 

練習

1.求圓的面積

function circleArea(radii){
			pi=Math.PI;
			var area=pi*pi*radii*radii;
			return area;
		};
		var radius=Number(prompt('請輸入圓的半徑(單位:cm)'));
		var area=parseInt(circleArea(radius));
		document.write('該圓的半徑爲:'+radius+'釐米</br>'+'面積約爲:'+area+'平方釐米');

2.圓的周長

function circumference(radii){
			pi=Math.PI;
			var perimeter=2*(pi*radii);
			return perimeter;
		};
		var perimeter=parseInt(circumference(radius));
		document.write('</br>該圓的直徑爲:'+(2*radius)+'釐米</br>'+'周長約爲:'+perimeter+'釐米');

3.求2個數的最大值

function maxNum1(num1,num2){
			if(num1>num2){
				return num1;
			}else if(num2>num1){
				return num2;
			}else{
				return '兩數相等';
			};
			return num1>num2?num1:num2;
		}*/

		/*var x=prompt('請輸入第一個數'); var y=prompt('請輸入第二個數字'); var maxNumber=max(x,y); document.write('最大值爲:'+ maxNumber ); 

4.求3個數的最大值

function maxNum2(num1,num2,num3){
			return (num1>num2?num1:num2)>num3?(num1>num2?num1:num2):num3;
		};
		var x=Number(prompt('請輸入數字x'));
		var y=Number(prompt('請輸入數字y'));
		var z=Number(prompt('請輸入數字z'));
		var result=maxNum2(x,y,z);
		document.write('其中最大的數爲:'+result);

固然咱們也能夠利用練習3中的函數來進行函數嵌套

function maxNum2(num1,num2,num3){
			var temp=maxNum1(num1,num2);
			return maxNum1(temp,num3);
		};
		var x=Number(prompt('請輸入數字x'));
		var y=Number(prompt('請輸入數字y'));
		var z=Number(prompt('請輸入數字z'));
		var result=maxNum2(x,y,z);
		document.write('其中最大的數爲:'+result);

5.求數組中的最大值,函數接收一個數組

function maxNum3(array){
			var max=array[0];
			for(var i=0;i<array.length;i++){
				if(array[i]>max){
					max=array[i];
				};
			};
			return max;
		};
		var nums=[213,12,4,2,12,56,34,299];
		document.write('最大值爲:'+maxNum3(nums));

6.將數組反轉後,返回反轉後的數組

function reverse(array){
			var newArray=[];
			for(var i=array.length-1;i>=0;i--){
				newArray[newArray.length]=array[i];
			};
			return newArray;
		};
		var nums=[213,12,4,2,12,56,34,299];
		document.write('新數組爲'+reverse(nums));

變量提高

咱們首先來了解一下解析器在執行JavaScript代碼的過程:
1.首先進行預解析(全局做用域)
將變量的var和函數function的聲明提早到做用域的最上面,須要注意的是變量的賦值操做是不會提早的,這步也就是變量提高。
2.執行代碼
執行規則就是常規的從上至下,逐行執行代碼
當執行到函數時,就會進入函數內部進行內部的預解析(局部做用域)
3.局部的預解析
也就將聲明部分提高到函數的最上面先執行
而後從上往下,逐行執行代碼。
好比如下代碼:

var num=10;
		fun();
		function fun(){
			console.log(num);
			var num=20;
		};

按照正常的JS逐行執行順序來看,看上去輸出值不是提示報錯就是10,對吧?不對,輸出應該是undefined
咱們來看下拆解的執行步驟:

// 第一步:預解析(全局做用域)
		/*var num; function fun(){ //第三步:當執行函數的時,再次進行預解析(局部做用域) var num; // 第四部:一行一行執行代碼 console.log(num);//因此執行到這裏輸出的時候,輸出了一個函數內部聲明瞭可是未賦值的num num=20; }; //第二步:一步一步執行代碼 num=10; fun(); //完畢 

注意:正確的順序是跟着標籤的順序進行執行的。

例2:

var a=18;
		f1();
		function f1(){
			var b=9;
			console.log(a);//undefined
			console.log(b);//9
			var a='123';
		};

拆解步驟:

// 第一步:預解析(全局做用域)
		var a;
		function f1(){
			//第三步:函數內部預解析
			var b;
			var a;

			//第四步:執行函數內部
			b=9;//給b賦值
			console.log(a);//執行了函數內部聲明可是未賦值的a,因此是undefined
			console.log(b);//執行了輸出b,而且b被賦值了9,因此輸出9
			a='123';
		};

		// 第二步:執行代碼
		a=18f1();
		// 完畢*/

例3:

f1();
		console.log(c);
		console.log(b);
		console.log(a);
		function f1(){
			var a=b=c=9;
			console.log(a);
			console.log(b);
			console.log(c);
		};

這裏我本身踩了個坑,由於教學在這步驟的時候直說了同上,可是其中的var a=b=c=9的聲明方法,讓這個代碼執行的時候有一個特殊的狀況。輸出爲:九、九、報錯找不到a、九、九、9。
詳細的步驟:

// 第一步:預解析(全局做用域) 
		function f1(){
			// 第三步:函數內部預解析
			var a;
			//第四步:執行函數內部
			c=9;//提高
			b=c;//提高
			a=b; 這裏有個特殊狀況,由於在函數中var a=b=c的寫法,致使只有a被聲明瞭,b和c沒有在函數中被聲明,因此被自動解析爲全局變量了。
			console.log(a);
			console.log(b);
			console.log(c);
		};
		// 第二步:一步一步執行代碼
		f1();
		console.log(c);
		console.log(b);
		console.log(a);
		// 完畢!

一開始踩坑覺得開頭的輸出cba都是沒法被找到,由於在預解析中,是沒有全局變量的,並且運行的結果卻和我一開始想象的不太同樣,直到我翻閱了資料才瞭解到,當在var 後面使用=鏈接的時候,只會對第一個變量進行聲明,後面幾個變量只是普通的賦值操做而已,當他們被放進函數中,普通的賦值操做,就使他們變成了全局變量。
也就是說,當var a=b=c=9是不等於var a=9;var b=9;var c=9;
而應該是var a;c=9;b=c;a=b;
當這就很明顯了,在函數裏的時候c=9;b=c;至關於一個把變量提高到了全局,並且只有a是被var 聲明過了,致使在執行以後,c和b都能找到,可是a是在函數裏聲明的是局部變量,全局中沒有這個變量因此是a is not defined

定義函數的形式、回調函數

方式1:函數聲明

function sum(num1,num2){
			return num1+num2;
		}
		console.log(sum(3,7));

方式2:函數表達式

var sum=function(num1,num2){ //沒有名字的函數,稱爲匿名函數
			return num1+num2;
		};
		console.log(sum(4,8));

區別:

fn1();//能夠被執行,由於會預解析函數,也就是能夠先調用,再聲明
		function fn1(){
			console.log('this is fn1');
		}
		
		fn2();//沒法執行,會提示fn2不是函數
		function fn2(){
			console.log('this is fn2');
		};

回調函數

顧名思義,不當即執行的函數條用,知足必定條件時才執行佛者別的代碼條用執行
用法:條用時只寫函數名,沒有小括號()和參數
應用場景:事件綁定,函數參數

function show1(){
			document.write('這是第一個函數');
		}

		function show2(){
			document.write('這是第二個函數');
		}

		//當點擊頁面時執行函數show2
		// window.οnclick=show2();//頁面加載完就直接執行了,可是點窗體又不執行。
		window.onclick=show2;//這樣就能夠按預想的方式執行,稱爲回調函數:即回頭再調用此函數

函數也是一種數據類型

函數也是一種數據類型,其類型爲function類型

function fn(){
			console.log('這是一個函數');
		}

		console.log(typeof fn);//function

		var fn2=function(){
			console.log('這是一個函數2');
		};
		console.log(typeof fn2);//function

將函數做爲參數:

function show(a,fn){
			console.log(a);
			fn();//調用傳入的函數
		};

		show(8,fn);//8,這是一個函數

例2:

function sum(x,y){
			return x+y;
		}

		function sum2(a,b,fn){
			var result=fn(a,b);
			console.log(result);
		};

		sum2(1,2,sum);//3

匿名函數

用於回調

引用以前的回調函數:

function show(){
			console.log('點擊了頁面');
		}
		window.onclick=show;

可使用匿名函數來寫:

window.onclick=function(){//匿名函數,用於回調
			console.log('點擊了頁面2!')
		};

用於一次性執行的函數:

(function(){
			console.log('只用於一次執行1')
		})();

這種寫法其實就是一個調用,只是把調用的函數名直接匿名函數的方式完整的寫出來。
好比咱們用下以前的函數做爲數據類型的例子2:

function sum(x,y){
			return x+y;
		}

		function sum2(a,b,fn){
			var result=fn(a,b);
			console.log(result);
		};

		sum2(1,2,sum);//3

咱們把他sum
這步驟去掉,直接用匿名函數寫到實參裏。

function sum2(a,b,fn){
			var result=fn(a,b);
			console.log(result);
		};
		sum2(1,2,function(x,y){//將匿名函數做爲另外一個函數的參數
			retrun x+y;
		});//3

注:此爲我的學習筆記,若有補充能夠選擇在評論區留言或者無視。

相關文章
相關標籤/搜索