其实你学完了变量赋值、分支循环,理论上你就学“完”编程了:任何功能,本质你都可以用分支循环直接实现。
接下来,其实我们要学的,是如何把代码写“好”。怎么才算好?
只要拿到驾照,其实大家的技术(油门/刹车/离合/方向盘)都一样的,但是:
@想一想@:他们的差距在哪里?
有一种很流行的说法:要懂“底层”,老司机车开得好,是因为他更懂发动机?
安全、性能、可维护性。
专讲可维护性(代码会一直用反复改,和“建筑工程”其实不同):
函数(function),又被称之为“子程序”,面向对象时称之为方法(method),几乎所有的高级语言中都有这个概念。
其本质就是将一段代码予以封装,以便于以后反复使用(重用)。
比如我们之前的“从数组中查找某个值”,这一功能就可以在项目中反复使用:在任意一个数组中查找任意一个值,这就可以被封装成一个函数。
@想一想@:不然怎么办?
记住:程序员讨厌复制粘贴!
演示:复制粘贴的三个问题:
所谓函数的声明(declare),就是函数的创建 (复习:变量的声明)
任何函数,一定包含:
最常规声明方式:
function find(numbers, target) { return -1; //或者其他值 }
语法点:
函数声明之后,不会自动运行。函数运行,需要开发人员调用(使用,call/invoke):
调用函数的代码被称之为函数表达式:
find([2, 5, 8, 1, 7, 12, 9], 8);
函数表达式执行完成之后就“代表”函数返回值,可以赋值给变量,也可以直接使用
let result = find([2, 5, 8, 1, 7, 12, 9], 8); alert(find([1, 9, 7, 3, 15, 5, 4, 6], 3))
通过调用:(F12断点演示)
示例,声明和调用:
function find() { return 986; //或者其他值 }
function find() { console.log("源栈欢迎你!"); }注意:console.log()控制台输入≠ return
function find(numbers, target) { for (let i = 0; i < numbers.length; i++ ){ if(numbers[i]==target){ //break; return i+1; console.log("找到了,在第"+ (i+1) + "位"); } else{ if(i == numbers.length-1){ console.log("没找到"); return -1; }//else nothing } } }
有些同学会好奇无返回值return;的意义,简单的说,它可以和if...else配合,在某些条件下终止函数的执行。
比较常见的情景包括:
function isPositive(number){ //函数的本义是检查一个数字是否为正数, //所以如果传入的number都不是数字的话 if(isNaN(number)){ console.log("无法判断一个非数字的值是否为正数"); return; } return number > 0; }
function doSomething(number){ //要根据用户角色进行各种不同的复杂的处理 //但是,如果用户根本就没登录…… if(role==null){ console.log("未登录用户请先登录/注册"); return; } //其他代码.... }这样剩下的问题也会逐渐变得简单。
无论是防御式,还是截断式,都能减少else的使用,从而减少分支的嵌套层级。
if 中直接返回了,不需要在额外加上else。
PS:不重要,愿意理解的就了解一下
最后,alert()和console.log()都是函数。
native code:非JavaScript实现,看不到内容
混淆“输出”和“返回”:console.log()不是返回不是返回不是返回!
当方法体中出现分支循环时,以为有“多个”返回
断点调试时:
function isPositive(number){ return number > 0; } function isOdd(number){ return number % 2 == 1; }
代码:
if(isPositive(-5) && isOdd(20)){
在方法体中还可以调用方法自己,这被称之为递归(调用)。
通常我们并不鼓励采用这种写法,因为它占用“栈”资源,导致运行效率低,甚至会造成堆栈溢出(Stack Overflow)。
但有时候,使用递归能够大幅精简代码书写,比如:二分查找,或者查找一个文件夹下所有的文件等,这里我们讲一个经典的:
0,1,1,2,3,5,8,13,21,34,55,89,144……依次类推下去。
你会发现,它后一个数等于前面两个数的和。在这个数列中的数字,就被称为斐波那契数。
思路:
function getFibonacci(a, b) { //终止条件 if (b > 1000) { return; } console.log(b); let sum = a + b; //递归的调用自己 getFibonacci(b, sum); }
一直重用一直爽!
同学们要更深刻的理解函数的价值:封装和重用。不仅仅是封装一段代码,函数和函数之间也可以形成封装和重用。
比如最初,我们有这么一个函数:
//返回数组中的第一个元素 function getFirst(numbers){ return numbers[0]; }
后来,我们又有了这么个函数:
//返回数组中的最后元素 function getLast(numbers){ return numbers[numbers.length-1]; }最后,我们进一步的拓展,有了这么一个函数:
//返回由参数指定位置/下标的数组中某元素 function getBy(numbers, index){ return numbers[index]; }
@想一想@:有啥不对劲的地方不?
getFirst()和getLast()是不是能够重用一下getBy()呀?
function getFirst(numbers){ return getBy(numbers, 0); }
这有没有价值?^_^
多快好省!前端后端,线上线下,名师精讲
更多了解 加: