函数
作用:
1.简化代码
2.方便维护
3.提高开发效率
4.提高了代码的复用性,减少代码冗余
格式:
标准函数声明语句
function 函数名(参数...){
函数执行的代码
}
<script>
function str(){//定义了一个函数,名为str
alert("你好")//函数的执行语句
}
str() ;//调用这个函数
</script>
注意,如果使用函数声明语句这种方式声明函数,会具有函数名提升的效果
如
变量提升只在当前作用域(例如:开始加载页面的时候,只对全局作用域下的进行提升,因为此时函数中存储的都是字符串而已)
<script>
str();//你好
function str() { //定义了一个函数,名为str
alert("你好") //函数的执行语句
}
str(); //你好 调用这个函数
</script>
[注意]函数先定义后调用
分类:
1.内置函数(官方提供的函数,系统自身拥有函数)
弹出 alert();
document.write();
控制台 console.log();
整数 parseInt();
浮点数 parseFloat();
2.自定义函数
根据参数和返回值的不同,可将函数分为四种。
1.无参数无返回值
2.有参数无返回值
3.无参数有返回值
返回值:对函数执行完成的结果的返回。
return:结束当前函数,并将return后面的值(表达式/变量)作为函数的运行结果返回。
当我们需要对函数的运算结果进行不同的处理时,需要将函数的结果返回。
4.有参数有返回值
<script>
function say() {
alert("HELLO");
}
var func = say; //没有括号
say(); //有括号时,是使用了函数 say()的调用结果
func(); //没有括号时,是把 函数 say本身的执行过程
</script>
匿名函数
关键词function后没有函数,称为匿名函数(匿名函数不具有函数名提升效果,因此不能在匿名函数创建之前使用它)
<script>
var say = function() { //定义了一个变量say,把函数体当做表达式赋值给了变量say
alert("hello"); //这个函数的内容是弹出一个字符串hello
};
say(); //hello 将变量say弹出
</script>
这种写法是将一个匿名函数赋值给变量,这时,这个匿名函数又称函数表达式,
匿名函数不能有函数名提升会报错
<script>
say();//Uncaught TypeError: say is not a function
var say = function() {
alert("hello");
};
</script>
有参数函数
<script>
function show(a, b) {
alert(a + b);//输出 AnnHello
}
var a = "Ann";
show(a, "Hello"); // 这个时候a就已经变为了字符串Ann
alert(a); //输出 Ann
</script>
这两个是对比(注意下面的a是字符串)
<script>
function show(a, b) {//这个时候参数变为"a" "Hello"
alert(a + b);//输出 aHello
}
var a = "Ann";
show("a", "Hello"); // 这个时候字符串a就给了上面的参数a
</script>
若函数形参重名,使用时以最后一个形参为准
<script>
function str(a, a) {
console.log(a);//2
}
str(1, 2)
</script>
函数的传参 值传递与引用传递
参数为值传递,传递副本;
引用传递时传递地址,操作的是同一个对象
<script>
var n = 10;
function fn4(num) {
num = 20;
console.log(num); //20
}
fn4(n);
console.log(n); //10
</script>
引用传递(引用传递时传递地址,操作的是同一个对象)
<script>
var obj = {
uname: "张三",
age: 18
};
console.log(obj);// {uname: "张三", age: 18}
function fun5(a) {
a.uname = '李四';
}
fun5(obj);
console.log(obj); //{uname: "李四", age: 18}
</script>
封装函数
1.确定函数的执行代码:函数体。
2.找出变量(不确定值。),将其设置为形参
3.如果需要对返回结果进行不同的处理,则定义返回值。
var arr = ["苏轼", "辛弃疾", "李白"];
function joint(arr) {
var str = "";
for (var i = 0; i <= arr.length - 1; i++) {
str += arr[i];
if (i == arr.length - 1) continue;
str += "|";
}
return str;
}
alert(joint(arr));
调用函数
1.函数名(参数列表);
<script>
function str() {
console.log("常见的调用")//常见的调用
}
str();//调用
</script>
2.函数调用模式
<script>
function str(a, b) {
return a + b;
}
var sum = str(2, 3);
console.log(sum);//5
</script>
对象调用模式
<script>
var obj = {
name: "张三",
age: 18,
str: function() {
console.log("对象调用函数......")//对象调用函数......
}
}
obj.str();
</script>
回调函数
回调就是一个函数的调用过程。那么就从理解这个调用过程开始吧。函数a有一个参数,这个参数是个函数b,当函数a执行完以后执行函数b。那么这个过程就叫回调。
其实中文也很好理解:回调,回调,就是回头调用的意思。函数a的事先干完,回头再调用函数b
必须清楚一点:函数b是你以参数形式传给函数a的,那么函数b就叫回调函数。
function a(m, n, b) {
var d = m + n;
alert("一个从父函数a 产生的参数将要被传递给回调函数 ,这个参数是:" + d);//先执行
//这里才写你想调用的函数---参数要正确
b(d);
}
function b(data) {
alert("我是回调函数,我的名字叫:callback ,我接收到来自父函数的参数,参数是:" + data);//后执行
}
a(1, 2, b)
函数的返回值 return
1,如果函数有返回值,需要通过return返回;
<script>
function str(a, b) {
return a + b;
}
console.log(str(2, 3));//5
</script>
2,如果函数不需要返回数据时,则无返回值,或者说返回undefined;
3,如果函数不需要返回值时,使用return,则表示结束方法
作用:
1,返回结果给调用者,
2,结束语句
函数的属性
【length属性】
函数的length属性表示形参个数,
arguments对象的length属性表示实参的个数
【name属性】
可以访问到函数指定的名字
匿名函数的name属性为空
<script>
function fun(a, b, c) {
console.log("hello js"); //hello js
console.log(fun.arguments.length);//4 实参的个数
}
fun(1, 2, 3, 4)
console.log(fun.name); //fun
console.log(fun.length); //3
</script>
例子:定义一个函数,参数的数量不固定,
function joint() {
var str = arguments[0];
for (var i = 1; i < arguments.length; i++) {
str = Number( str + arguments[i]) ;
}
document.write(str);
}
joint(1, 2,6, 3,4)
作用域
变量存在的范围
全局变量
直接写在Script标签中的变量,在页面中的任意位置都可以访问到。
在页面打开创建,在页面关闭时销毁。
局部变量
局部变量是定义在函数内部的变量.这个变量只能在函数内使用.例外,函数中的
形参也是局部变量.
每一次调用时创建,调用结束会销毁。
【注意】
如果局部变量与全局变量重名,则使用局部变量。若函数内部没有找到该变量,则去全局变量中查找。
<script>
//这个例子就是重名典型案例
let userName = 'John';// 声明一个全局变量
function showMessage() {
let userName = "Bob"; // 声明一个局部变量
let message = 'Hello, ' + userName; // 为Bob,因为在函数内优先使用函数内变量
alert(message);因为下边调用了,所以可以弹出
}
showMessage(); // 调用这个函数
alert(userName); // 还是为John,未被更改,因为它输出的是全局定义的变量。
</script>
<script>
var user="join";//这是个全局变量
function show(){//定义一个函数取名为show
var message="hello,"+user;
alert(message);//弹出
}
show();//调用函数
</script>
在函数定义变量时,若没有加var关键字,使用后自动变为全局变量
<script>
function str() {
a = 100;
}
str();
console.log(a);//100
</script>
上述例子你如果加了var 就会报错为未定义
例子
<script>
let userName = 'John';
function showMessage() {
userName = "Bob"; // (1) 改变外部变量
let message = 'Hello, ' + userName;
alert(message);//弹出的是字符串
}
alert(userName); // John 在函数调用之前
showMessage();//调用这个函数
alert(userName); // Bob,值被函数修改了
</script>
下面这个例子是说标准的命名函数可以在没有这个函数时调用(命名函数有函数名提升),但是要注意赋值时,要在调用前就将值赋好
<!-- <script>
foo(); // undefined
var a = 2;
function foo() {
console.log(this.a);
}
</script> -->
<!-- <script>
var a = 2;
foo(); // 2
function foo() {
console.log(this.a);
}
</script> -->
<script>
var a = 2;
function foo() {
console.log(this.a);
}
foo(); // 2
</script>
作用域链就是寻找变量时找不到会一级一级往上寻找
变量的释放
<script>
var a = 1//全局变量
b = 2 //全局变量
delete a; //变量释放
delete b;
function str() {
var c = 3;//局部变量
d = 4 //全局变量
}
console.log(a);//1
console.log(b);//b is not defined
</script>
使用 var 创建的变量不能使用 delete 释放内存。
不使用 var 创建的变量可以使用 delete 释放内存。
递归
函数之间可以互相调用,如果函数内部调用了其自身,则我们称其为递归调用。
特点:
1.函数自己调用自己
2.一般情况下还有参数
3.一般情况下有返回值.
方法:
1.找这一次计算与上一次计算的关系。
2.调用自身
3。找到函数结束的条件。
<script>
// 求n的阶乘 递归法
//5*4*3*2*1
function fac(n) {
if (n == 1) {
return n;
}
return n * fac(n - 1);
}
alert(fac(5)); //120
</script>
for循环
function jc1(num) {
var s = 1;
for (var i = num; i > 0; i--) {
s = s * i;
}
console.log(s);
}
jc1(5);