函数就是封装了一段可以被重复调用的代码块,目的:就是让代码重复使用
1.函数的使用
//声明函数
function sayhi {
console.log('hi ~~');
}
//函数不调用自己不执行:函数调用
sayhi();
//!!一定要加小括号
2.函数的封装
函数的封装是把一个或者多个功能通过函数的方式封装起来,对外只提供一个简单的函数接口
3.函数的参数
//形参和实参的执行过程
function cook(aru) {//形参是aru
console.log(aru);
}
cook('酸辣土豆丝');//实参是酸辣土豆丝
//形参类似于一个变量,接收实参
//函数的参数可以有,也可以没有个数不限
3.1函数形参和实参个数不匹配的问题
// 函数形参实参个数匹配
function getSum(num1, num2) {
console.log(num1 + num2);
}
// 1. 如果实参的个数和形参的个数一致 则正常输出结果
getSum(1, 2);
// 2. 如果实参的个数多于形参的个数 会取到形参的个数
getSum(1, 2, 3);
// 3. 如果实参的个数小于形参的个数 多于的形参定义为undefined 最终的结果就是 NaN
// 形参可以看做是不用声明的变量 num2 是一个变量但是没有接受值 结果就是undefined
getSum(1); // NaN
// 建议 我们尽量让实参的个数和形参相匹配
3.2函数的返回值
- return后面的代码不会被执行
- 返回的结果是最后一个值return num1,num2;
- 返回多个数据可以返回数组
- 如果没有return,返回undefined
function getResult() {
return 666;
}
getResult(); // getResult() = 666
console.log(getResult());
function cook(aru) {
return aru;
}
console.log(cook('大肘子'));
//4. 求任意两个数的和
function getSum(num1, num2) {
return num1 + num2;
}
console.log(getSum(1, 2));
案例
//经典案例求两个数的最大值
// 利用函数 求两个数的最大值
function getMax(num1, num2) {
// if (num1 > num2) {
// return num1;
// } else {
// return num2;
// }
return num1 > num2 ? num1 : num2;
}
console.log(getMax(1, 3));
console.log(getMax(11, 3));
// 利用函数求数组 [5,2,99,101,67,77] 中的最大数值。
function getArrMax(arr) { // arr 接受一个数组 arr = [5,2,99,101,67,77]
var max = arr[0];
for (var i = 1; i <= arr.length; i++) {
if (arr[i] > max) {
max = arr[i];
}
}
return max;
}
// getArrMax([5, 2, 99, 101, 67, 77]); // 实参是一个数组送过去
// 在我们实际开发里面,我们经常用一个变量来接受 函数的返回结果 使用更简单
// var re = getArrMax([5, 2, 99, 101, 67, 77]);
var re = getArrMax([3, 77, 44, 99, 143]);
console.log(re);
4.arguments的使用
arguments实际上是当前函数的一个内置对象,所有函数都内置了一个arguments对象,arguments对象中存储了传递的所有实参。
function fn() {
// console.log(arguments); // 里面存储了所有传递过来的实参 arguments = [1,2,3]
// console.log(arguments.length);
// console.log(arguments[2]);
// 我们可以按照数组的方式遍历arguments
for (var i = 0; i < arguments.length; i++) {
console.log(arguments[i]);
}
}
fn(1, 2, 3);
fn(1, 2, 3, 4, 5);
// 伪数组 并不是真正意义上的数组
// 1. 具有数组的 length 属性
// 2. 按照索引的方式进行存储的
// 3. 它没有真正数组的一些方法 pop() push() 等等
// 利用函数求任意个数的最大值
function getMax() { // arguments = [1,2,3]
var max = arguments[0];
for (var i = 1; i < arguments.length; i++) {
if (arguments[i] > max) {
max = arguments[i];
}
}
return max;
}
console.log(getMax(1, 2, 3));
console.log(getMax(1, 2, 3, 4, 5));
console.log(getMax(11, 2, 34, 444, 5, 100));
5.函数可以调用另一个函数
// 用户输入年份,输出当前年份2月份的天数
function backDay() {
var year = prompt('请您输入年份:');
if (isRunYear(year)) { // 调用函数需要加小括号
alert('当前年份是闰年2月份有29天');
}
else {
alert('当前年份是平年2月份有28天');
}
}
backDay();
// 判断是否为闰年的函数
function isRunYear(year) {
// 如果是闰年我们返回 true 否则 返回 false
var flag = false;
if (year % 4 == 0 && year % 100 != 0 || year % 400 == 0) {
flag = true;
}
return flag;
}
6.函数的表达式声明函数(匿名函数)
var fun = function(){//这里的fun是变量名,不是函数名
console.log('我是函数');
}
fun();
7.作用域
- 7.1变量的作用域
- 7.2作用域链
什么是作用域?
作用域就是代码名字(变量)在某个范围内起作用和效果,目的是为了提高程序的可靠性,减少命名冲突。
全局作用域:整个script标签或者是一个单独的js文件。
局部作用域:在函数内部就是局部作用域。意思就是出了函数该变量就不起作用了。
7.1变量的作用域分类:
1.全局变量——在全局作用域下的变量。
2.局部变量——在局部作用域下的变量。
注意:函数的形参也可以看做是局部变量。
//全局变量只有浏览器关闭的时候才会销毁,比较占内存资源,在任何一个地方都可以使用;局部变量当我们程序执行完毕就会销毁,比较节约内存资源,只有在函数内部使用。
7.1.1JS没有块级作用域(在es6新增了块级作用域)
!!!块级作用域就是花括号里面的{} if{} for{}
//java里面
if(xx) {
int num = 10;
}
//外面是不能调用num
//JS里面
if(3 < 5) {
var num = 10;
}
console.log(num);//在花括号外面就可以调用num
7.2作用域链
内部函数可以访问外部函数,用链式查找决定查找哪些数据。类似css的就近原则。
例题解释:
//结果是几??
function f1() {
var num = 123;
function f2() {
console.log(num);//执行结果是123,执行链最近的是123;(站在目标出发一层一层往外找)
}
f2();
}
var num = 456;
f1();
小测验:
// 案例2 :结果是几?
var a = 1;
function fn1() {
var a = 2;
var b = '22';
fn2();
function fn2() {
var a = 3;
fn3();
function fn3() {
var a = 4;
console.log(a); //a的值 ?
console.log(b); //b的值 ?
}
}
}
fn1();
答案:4 22;