1. JS函数的概念
函数就是把特定功能的代码抽取出来,使之成为程序中的一个独立实体。
2. 函数的作用
正如函数的概念, 我们可以根据需要, 将特定的功能用函数来包裹(封装)
3. 使用函数的好处
1, 函数可以在同一个程序或其他程序中多次重复使用(通过函数名调用)
2, 使程序变得更简短而清晰 , 提高可读性
3, 有利于程序维护
4.函数的分类
函数可以分为: 系统函数 内置函数 和 自定义函数
系统函数,内置函数:
是官方提供好的函数,可以直接使用
如: alert(), isNaN(), console.log() ,document.write(), Boolean(), Math.pow()等
自定义函数:
函数的简单定义
定义函数的语法格式:
function 函数名() {
代码块;
}
注意:
1, 必须使用function关键字, 且为小写, 函数名可以自己给定
2, 函数名的命名规则和变量名一致
3, 函数名后必须写圆括号()
示例: 定义一个函数printOut
function printOut(){
document.write(“Hello World!”);
}
函数的标准定义
定义函数的语法格式:
function 函数名(参数1,参数2,……)
{
执行语句;
return 返回值;
}
注意: 1, 函数名后圆括号()中的参数数量不定, 也可以没有; (根据功能需要)
2, return关键字的作用是将某个值返回, 如果没有返回值则默认返回undefined
5.函数的三种写法
//普通函数
function fn1(n,m) {
return n+m;
}
console.log(fn1(10,20));
//匿名函数(没有函数名称)
var fn2=function(n,m) {
return n+m;
}
console.log(fn2(10,20));
//构造函数,创建函数
var fn3= new Function("a","b","return a+b;")
console.log(fn3(50,40))
6.函数的形参和实参
形参:
形参就是在函数定义时,函数名后面的参数;
函数的形参跟变量是一样使用,且不能用var修饰
实参:
实参就是调用时,函数名后面的参数
如: 之前定义的函数sum中: one和two是形参, 2和8是实参
function sum(one, two){
var s = one + two;
return s;
}
sum(2, 8);
7.函数中的arguments数组:
JS中函数不介意传递进来多少个参数,也不在乎传进来参数是什么数据类型,在调用函数时也未必一定要传递指定数量的参数,原因是 ECMAScript 中的参数在内部是用一个数组(arguments)来表示的。函数接收到的始终都是这个数组,而不关心数组中包含哪些参数(如果有参数的话)。
arguments可以判断参数的个数,arguments是个数组。
我们可以使用arguments.length来获取参数的个数
可以使用arguments[i] 的方式来访问数组中的第i个参数(i为自己给定的整数下标)
<script>
// arguments
// 1.只能在函数内部出现
// 2.它是伪数组(本质是一个对象)
// 对象多一个length属性
// 它的作用:1动态接受实参
// 动态接受实参
function fn() {
var res=0;
for(var i=0;i<arguments.length;i++) {
res+=arguments[i];
}
return res;
}
var res1=fn(10,20,30);
console.log(res1);
var res2=fn(4,5,6,7);
console.log(res2);
// fn("大白兔","白又白")
//对象不会天生自带length
//数组会自带length
</script>
8.DOM的简单操作
<body>
<input type="text" id="txt">
<button id="btn">提交</button>
</body>
<script>
//想用js操作页面上元素
//通过id获取文档里的元素
var oBtn = document.getElementById("btn");
var oTxt = document.getElementById("txt");
//console.dir 查看对象的详细信息
//. 的
//console.log(oBtn);
//页面里面输入的内容都是字符串型
//1.拿到点击按钮,给按钮绑定点击事件
oBtn.onclick=function (){
//2.在点击事件里面,获取输入框的值
var res = oTxt.value;
console.log(res);
}
</script>
9.作用域
作用域:
就是起作用的范围。或者说有效范围; 这里涉及到另外两个概念
1.局部变量: 定义在函数内部的变量,这个变量只能在函数内部使用,即作用域范围只是函数内部,另外,形参也是局部变量.
2.全局变量: 全局变量就是定义在函数外部的变量,这个变量在任何函数中都有效,即作用域范围是当前文件的任何地方.
注意: 在定义变量时, 如果不写关键字var也是合法的, 且是全局变量, 但是这样写不安全,容易在其他地方被更改, 所以我们在函数中写变量要加上var
<script>
//全局变量和局部变量,同名并同时存在,局部变量优先
function fn(n) {
m=10;//全局变量
}
fn(20)
console.log(m);
//console.log(n);
var n=100;
function fn() {
console.log(n); //undefined 变量提升
var n=200;
console.log(n);//200
}
//变量提升是JavaScript 的一种执行机制,大致就是字面意思,将声明的变量提前,
// 但并不是指在编译时改变语句的顺序,而是将变量 提前 放入内存中,供后续操作
// 上面fn的执行顺序为fn{
// var n;
// console.log(n); //所以n会输出undefined
// n=200;
// }
fn();
function fn() {
var n=m=200; //var n;所以n是一个局部变量,而m前面没有var所以是全局变量
}
fn()
console.log(n);// n is not defined
console.log(m);//200
</script>
10.递归调用
递归调用: 函数可以自己调用自己,必须要有结束条件,称为函数的递归调用;
重要性:
递归的分量,递归属于函数中比较难理解的知识,在应用开发中,虽然使用不是很频繁,但是很体现你的功底,而且,从事IT行业开发,最好要会递归,如果说现在可以不要求灵活运用的话,以后到公司中一定要会,如果面试中有人问你递归,说明,他对你要求挺高
10.函数执行顺序(函数提升)(易错)
函数提升:
规则:
1.变量声明,函数声明都会被提升到作用域顶部;
2.当出现相同名称函数时,优先级:变量声明<函数声明<变量赋值
var foo = function(x,y) {
return x-y
}
var foo = function(x,y) {
return x+y
}
var num = foo(1,2)
javaScript编译器处理后执行顺序
//variable hositing 变量提升
var foo;//foo#1
var num;
//function declaration hoisting 函数声明提升
function foo(x,y){ //foo#2
return x + y;
}
//function expression NOT hoisted 函数表达式不会提升
function foo(x,y){ //foo#3
return x - y;
}
num = foo(1,2); 这里使用foo #3
———————————————————————————————————————————————
2021/10/27 更新
声明式函数 和 赋值型函数
声明函数与赋值函数的区别在于: 在 JS 的预编译期间,声明式函数会被先提取出来,然后才按照顺序执行 JS代码。
声明式函数:
a(); // 'a'
function a() {
console.log('a');
}
赋值型函数:
b(); // Uncaught TypeError: b is not a function
var b = function() {
console.log('b');
}
函数声明 提前于 赋值函数。
console.log(e); // undefined
var e;
console.log(f); //Uncaught ReferenceError: f is not defined
———————————————————————————————————————————————
递归调用的方式:
- 首先去找临界值,即无需计算,获得的值(一般是返回该值)。
- 找这一次和上一次的关系(一般从后往前找)
- 假设当前函数已经可以使用,调用自身计算上一次的运行结果,再写出这次的运行结果
var f = function (x) {
if (x < 2) {
return 1;//当x小于2时,函数会返回1;不再执行else
}
else {
return x * f(x - 1); //递归调用
}
}
console.log(f(5)); //得到5的阶乘是120
兔子问题
兔子繁殖问题,设有一只新生兔子,从第四个月开始他们每个月, 月初都生一只兔子,
// 新生的兔子从第四个月月初开始又每个月生一只兔子按此规律,并假定兔子没有死亡,
// n(n<=20)个月月末共有多少只兔子?
function f(n){
if(n == 1 || n == 2){ // 输入1和2时候,返回只有一对兔子
return 1;
}
return f(n-1)+f(n-2); //递归计算兔子数量
};
f(12); //12个月后一共有144对兔子