午后・时光

【黑师音画帖小白教程】第二十二讲:学一点点JS(二)函数

位置: 首页 > 马黑教程[ 发布时间: 2024.8.11  作者: 马黑黑  阅读: 113 ]

第二十二讲:学一点点JS(二)函数

函数是JS重要的组件,被视为一等公民,可见其重要。函数有JS内置的,有自定义的,我们主要讨论的是自定义函数。函数无非就是特定功能的封装,或是方法的整合——将一个或多个处理事情的方法整合在一个函数里。函数的作用主要是为了方便调用、复用,一次写好可以反复使用或处理一系列相同性质的问题,不必每一次处理类似的事情都要重新写一遍处理事情的代码。比如求两个数之和,只要函数调用者调用函数时传入合法的数值,函数就能做计算然后返回计算结果。试看:

//JS函数 :函数名 add,函数参数 a、b,函数目的 求 a + b

function add(a,b) {
	return a + b;
}

var c = add(12,36);

以上是JS函数的传统写法,使用JS内置的 function 关键字来声明函数,空格之后是自定义的函数名称 add,函数名称后面要有小括号,小括号内可以有内容,如果有则是函数需要的参数,参数可以是一个或多个,多个参数时用小角逗号将参数隔开;参数也可以没有,此时小括号里面没有内容,小括号连在一起写()。参数相当于未知数,所以用代数方法表示,可以是单个字母,也可以是一个单词或拼音,参数的命名一般建议尽量语义化以便易于阅读和理解。函数要处理的事情可能是一个语句,也可能是一系列的语句,不论如何,都写在函数体内,即花括号 { ... } 之内,一般分行写每一条语句,语句结束通常要用小角分号 ; 收尾,但也有特殊规定不要分号的。上例,函数只有一个语句,return a + b;,return 是JS内置的方法,返回之意,这里表示返回 a + b 这个算式的运算结果。

函数之外,我们声明了一个变量 c,并调用函数 add 给变量 c 赋值,调用时传入对应于 a,b 两个参数的数值,函数 add() 会对传递过去的参数数值进行运算并返回运算结果给 c 变量。

JS的函数可以写成箭头函数。箭头函数主要可以简化函数,上例的 add 函数的写法换成箭头函数可以这么写:

add = (a,b) => a + b;
//也可以在函数名前面加一个声明关键字
//var add = (a, b) => a + b;

结构上,箭头组合符号 = (...) => 替代了 function 关键字但又不是简单的替代,其结构为函数名之后是一个等号,接着是小括号带参数,最后是连体符号 =>,这个两个连体符号 = 和 >之间不能有空格。函数体单行语句时不要花括号也不要 return 返回关键字,很简约。但是,如果函数体不止一个语句,花括号和return关键字不能省略。试看函数体多个语句的函数:

//JS函数 :函数名 divide,参数 a、b,目的 求 a/b

//传统函数
function divide(a,b) {
	if(b === 0) return '无穷大';
	return a/b;
}

//箭头函数
divide = (a,b) => {
	if(b === 0) return '无穷大';
	return a/b;
};

以上这种情况,由于函数体里面的语句不止一句,箭头函数写法上就不可以缺少花括号,如果有返回值 return 关键字也不能缺省,实际上,函数体内,箭头函数写法和传统函数写法完全一样。函数写完,习惯上,传统函数一般不在 } 之后写上分号但理论上应该写,箭头符号函数则习惯写上分号但道理上也可以不写。上述函数,先检测参数 b 传来的数值是否等于0, === 表示绝对等于,意思是参数的变量类型和参数值绝对和 0 所表明的数值型变量和值相同;如果(if)b 等于 0,那么,函数返回的值是无穷大,这是任何数除以0得到的结果,然后函数体的后面语句就不再执行;反之,如果 b 不等于 0 则执行后续的语句,返回 a/b 的值。

做音画帖,我们会经常设计没有参数的函数,例如:

//JS函数 :函数名 mState,参数 无,目的 根据音频的 paused 属性控制其他交互
//这里假设HTML结构中,帖子 id="mydiv"、音频标签 id="aud"、视频标签 id="vid"、
//CSS动画控制播放暂停变量 --state

//传统函数
function mState() {
	if(aud.paused) { //如果音频暂停中则
		mydiv.style.setProperty('--state', 'paused'); //CSS动画暂停
		vid.pause(); //视频暂停
	}else{ //否则,如果音频播放中则
		mydiv.style.setProperty('--state', 'running'); //帖子CSS动画播放
		vid.play(); //视频播放
	}
}

//箭头函数
mState = () => {
	if(aud.paused) { //如果音频暂停中则
		mydiv.style.setProperty('--state', 'paused'); //CSS动画暂停
		vid.pause(); //视频暂停
	}else{ //否则,如果音频播放中则
		mydiv.style.setProperty('--state', 'running'); //帖子CSS动画播放
		vid.play(); //视频播放
	}
};

上述函数举例,为了明晰,我们在函数体里面使用了经典的 if else 语句,它先提出一种可能,音频是否暂停中,若是,则用一组花括号将要处理事情的代码语句写在里面,若不是,则再使用一组花括号将处理问题的语句写在里面。if 或 if else 语句结束不用分号做标识。这个 mState 函数没有使用参数,它要处理问题的对象无需通过参数传入,全都存在于HTML代码结构里,比如帖子容器 mydiv、音频控件 aud、视频控件 vid,或在CSS代码模块中,比如CSS变量 --state,就是说,函数直接操作的对象是页面中存在的可视或不可视的对象。

提示:函数不一定要有返回值,上例 mState 函数只执行一系列工作,不提供返回值,所以代码中没有 return 语句出现。

后面的函数举例,我们不再使用传统的写法,全部采用箭头函数。现在我们来看看一个可交互演示的小函数,它将生成JS随机数:

<p><output id="msg1">随机数尚未生成</output></p>
<p><button id="button1" type="button">戳我生成 random() 随机数</button></p>

<script>
var rndNum = () => Math.random();
button1.onclick = () => msg1.value = rndNum();
</script>

JS代码中我们设计了一个函数 rndNum,没有参数,它返回JS内置 Math.random() 方法的结果。Math 是JS的数学方法,该方法内容丰富,其中,random() 是返回 0 ~ 0.999... 的浮点数,包含 0 但概率非常低。然后,我们通过按钮 button1 的点击事件(onclick)调用 rndNum 函数,每一次点击在 output 标签中都会输出不同的浮点数。按钮的点击事件所做的事情其实也封装在一个函数里,这个函数调用 rndNum 函数并赋值给 id="msg1" 的 output 标签的 value 属性,output标签一般用来显示相关消息,value 属性是它要显示的文本内容。

上述示例我们完全可以去掉函数 rndNum,直接用 Math.random() 放在 button1 的点击事件那里,我们之所以要设计一个函数,是为了方便扩展,比如我们想取得 0~10 的随机整数:

<p><output id="msg2">随机整数待生成</output></p>
<p><button id="button2" type="button">戳我生成 0~10 随机数</button></p>

<script>
var rndInt = () => Math.ceil(Math.random() * 10);
button2.onclick = () => msg2.value = rndInt();
</script>

函数 rndInt 拆解:Math.random() * 10 是一个整体,随机浮点数乘以10,所得值再用 Math.ceil() 方法处理,向上取整。这还是一个较为简单的函数体语句,也可以直接写在 button2.onclick 语句中,但若再复杂一点,代码不止一行了或太长了,那就不方便直接写在按钮的点击事件中,此外,函数有可能不止一处调用,所以还是封装成函数为好。

提示:生成 0~10 的随机整数,上一次和下一次之间重复的可能性事实存在,毕竟随机数并不保证没有重复。一般来说,随机数的区间越大,两次连续生成重复数的可能性越低。另外,上例演示,得到 0 的概率非常之低,这是前面解释过的。

随机数大有用处,下面的实例,利用JS随机数函数机制生成随机的 hsl 颜色,并驱动元素文本颜色即前景色的变化:

<p><output id="msg3">随机 hsl 颜色待生成</output></p>
<p><button id="button3" type="button">戳我生成 hsl 随机颜色</button></p>

<script>
var rndHue = () => `hsl(${Math.round(Math.random() * 360)}, 100%, 50%)`;
button3.onclick = () => msg3.value = msg3.style.color = rndHue();
</script>

函数 rndHue 的核心是生成随机色相值,色相值的范围在 0~360 之间,所以 Math.random() 乘以 360 然后向下或向上取整都行,这里我们用了四舍五入 round。最后是拼凑 hsl 颜色的字符表达法,饱和度、亮度使用正常值。拼凑字符方法我们在下一个示例统一讲解。

使用随机数生成 rgb 颜色也简单,下面的例子,我们设计了两个函数:一个生成指定限制数的随机整数,另一个生成rgb颜色,程序运行时随机给元素一个rgb背景色,然后每次点击元素都会更换背景色:

<style>
#mybox {
	width: 400px;
	height: 200px;
	border: 1px solid gray;
	padding: 12px;
	color: yellow;
	text-shadow: 1px 1px 2px #111;
}
</style>

<div id="mybox" title="戳我改变背景颜色"></div>

<script>
rndNum = (limit) => Math.floor(Math.random() * limit); //生成指定数以内的随机整数(不包含limit)
rndRgb = () => `rgb(${rndNum(256)}, ${rndNum(256)}, ${rndNum(256)})`; //生成rgb随机颜色
//元素单击事件 :改变背景色并给出当前rgb颜色
mybox.onclick = () => mybox.textContent = mybox.style.background = rndRgb(); 
mybox.onclick(); //程序运行时自动单击元素
</script>

上例,rndNum 函数需要一个 limit 参数,限定随机数最大值不超过它。函数内,Math.random() * limit 是一个整体,它被 Math.floor() 所包裹,floor 方法向下取整,因此所得结果不会包含 limit 本体。函数 rndRgb 生成rgb随机颜色,r(红)、g(绿)、b(蓝)的参与成分值都是调用 rndNum(256) 生成,值范围在 0~255之间,含头尾数;注意所返回的语句我们使用了反引号,这样更方便组织字符拼凑:rgb颜色的常规字符按顺序照写下来,碰上JS语句时,用 ${...} 包裹JS语句。然后是 id="mybox" 的div的点击事件,它被点击时,令 mybox 的文本内容和背景颜色等于 rndRgb 函数的返回值。最后一个语句,自动运行一次 mybox 的点击事件——前面说过,元素的点击事件其实也是一个函数,可以直接运行它。

小结:本讲主要学习JS自定义函数。函数定义特定功能,这些功能可以细化成简短的函数,也可以集合在一个体量较大的函数里。函数可以有参数,参数是调用函数时传递过来的数据;也可以根据情况不需要参数。函数可以有返回值,也可以根据需要只做事不返回任何值。函数可以使用传统的写法,要有 function 关键字,也可以使用箭头函数;主张尽量使用箭头函数,不过箭头函数也有缺陷,例如适用性方面,有些特定场合不能使用——不过做帖子一般不会涉及到这些。

作业:参考最后的两个示例,制作一个自设大小的元素,并在JS代码模块中做到:① 编写两个函数,其中一个函数需要名为 max 的参数,生成小于 max 的随机整数,另一个函数生成 hsl 颜色,调用前一个函数来生成随机的色相值和随机的饱和度值,亮度值固定为50%;② 单击元素,元素会改变背景色并在元素上显示该 hsl 颜色值;③ 程序运行时自动单击一次元素。

返回目录

前一篇: 【黑师音画帖小白教程】第二十一讲:学一点点JS(一)变量
下一篇: 【黑师音画帖小白教程】第二十三讲:学一点点JS(三)元素的JS相关事件

发表评论:

       

评论列表 [0条]

Copyright © 2014 All Right Reserved 马黑PHP文章管理整站系统v1.8
联系我们: gxblk@163.com