【JS学习笔记】9.JavaScript函数基础(内置函数、函数基本用法、作用域、回调函数、匿名函数)

内置函数、函数基本用法

内置函数

特定计算eval();

计算表达式的结果,支持简单表达式,带变量表达式,条分支表达式以及用于解析JSON格式字符串

例:

		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();

在我的第5篇笔记JavaScript数据类型转换有详细的描述.

判断函数

1.isNaN():

作用:检查其参数是否非数字(注意是检查是否为非数字,非数字,非数字)。
如果是非数字就返回true(意思就是如果这个参数不是数字类型的就返回true),
如果不是非数字就返回false(意思就是如果这个参数是数字,就返回false)。

2.isFinite():

判断是否是有限数字(或者可以转换有限数字),如果是则返回true,如果是NaN、或者是正负无穷大数则返回false。

编解码函数

其意思为:对特殊字符串进行编码以及对编码过的字符串进行解码。

encodeURI,decodeURI

使用ISO8859-1的encodeURI,decodeURI:

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的声明方法,让这个代码执行的时候有一个特殊的情况。输出为:9、9、报错找不到a、9、9、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

注:此为个人学习笔记,如有补充可以选择在评论区留言或者无视。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值