就是封装了一段可被重复调用执行的代码段,可以实现大量代码的重复使用
1、函数的声明及调用
//函数的声明(定义):
function 函数名(){
//要执行的代码块
}
//调用:调用函数时,会逐行执行 函数里的代码
函数名();
注意点:
1、函数不调用 自己不执行
2、调用函数时加();
3、一次声明可以对此调用多次
4、封装就类似于打包
//利用函数封装,计算1-100 之间的和
function getSum(){
var sum=0;
for (var i =1; i<= 100;i ++)
{
sum+=i;
}
console.log(sum);
}
getSum();
2、带参数的函数
function 函数名(形参1,形参2,...){// 可以定义任意多的参数,用 逗号 分隔
// 函数体
}
// 带参数的函数调用
函数名(实参1, 实参2);
如:
function cook(aru) {
//形参 形式上的参数 接收函数调用时传递过来的数据
console.log(aru);
}
// 实参 函数调用时传的参数 土豆丝 花菜就是实参
cook('土豆丝'); //土豆丝
cook('花菜'); //花菜
//利用函数 完成 根据传入的任意两个值的和\
function sum(num1,num2){
console.log(num1+num2);
}
sum(12,6); // 形参和实参匹配,结果正常输入18
sum(12); //只有一个实参,num2类似于声明变量未赋值,结果就是undefined,12+undefined最后结果就会NaN 任何数加unde救过都是NaN
sum(12,6,2) // 结果还是18
总结:
1、函数可以带参数也可以不带参数
2、声明函数的时候,函数名括号里面的是 形参 类似一个变量 接受数据的
3、调用函数的时候,函数名括号里面的是 实参。
4、多个参数中间用 逗号分隔。
5、形参的个数可以和实参个数不匹配,但是结果不可预计,我们尽量要匹配。
函数形参和实参 数量不匹配
function getSum(x, y, z) {
return x + y + z;
}
console.log(getSum(1, 2, 3)); // 6
console.log(getSum(1, 2, 3, 4)); // 6 若形参少于实参 多的实参不输出
console.log(getSum(1, 2)); // NaN 若形参多于实参,多的形参输出undefined 任何数字与undefined相加都为 NaN
3、带返回值的函数
- 返回值概念:函数执行完后,可以把执行的结果 通过 return 语法 返回给 调用者
- 返回值本质 就是 调用函数 并将需要 值返回给 调用者
函数外部想使用函数内部的值的时候 可以使用return
语法:
function 函数名(){
return 需要返回的值;
}
函数调用
函数名() // 此时 调用 函数就可以得到 函数体内return 后面的值
function num(){
return 666;
}
console.log(num()); //666
执行思路:
1、因为函数里有return 所以function num(){return 666} == 666
2、调用函数的时候 就执行地2步操作 类似于num() = 666 赋值
返回值注意事项
1、retrun 后的代码不被执行
return除了返回值之外 还有终止函数的操作
function getSum(a, b) {
return a + b;
alert(8); //return后面的代码不执行
}
console.log(getSum(2, 5));//
2、return只能返回一个值
function getSum(a, b) {
return a+b ,a-b;
}
console.log(getSum(2, 5)); //-3
3、使用一个变量来接收返回的结果
function getSum(a, b) {
return a + b;
}
var num = getSum(2, 5);
console.log(num); //7
4、没有return 返回的值是 undefined
function fn() {
}
console.log(fn()); // undefined
案例:对数组排序,从小到大** -- 冒泡排序
function sort(array) {
for (var i = 0; i < array.length - 1; i++{
for (var j = 0; j < array.length - i -1; j++) {
if (arr[j] > arr[j + 1]) {
var temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
return array;
}
var arr = [2, 8, 1, 4, 9];
var arr1 = [2, 4, 8];
console.log(sort(arr));
console.log(sort(arr1));
1,1,2,3,5,8,13,21 求第9个数字是多少(可选) 斐波那契数列
// 根据数列的规律1,1,2,3,5,8,13,21 求第9个数字是多少(可选)
var num1 = 1;
var num2 = 1;
var num3 = 0;
for (var i = 3; i <= 7; i++) {
num3 = num1 + num2;
num1 = num2;
num2 = num3;
}
console.log(num3);
封装函数
function getFib(num) {
var n1 = 1;
var n2 = 1;
var n3;
for (var i = 3; i <= num; i++) {
n3 = n1 + n2;
n1 = n2;
n2 = n3;
}
return n3;
}
console.log(getFib(7));
4、arguments的使用
JavaScript中,arguments对象是比较特别的一个对象,实际上是当前函数的一个内置属性。也就是说所有函数都内置了一个arguments对象,arguments对象中存储了传递的所有的实参。arguments是一个伪数组,因此及可以进行遍历
当我们不确定有多少个参数传递的时候,可以用arguments 来帮助我们确定用户输入了多少个实参
arguments是用来存储用户传递过来的实参的
注意点:
1、有了arguments就不用写形参了
2、arguments按照一种维数组的方式存储
案例::求任意个数的最大值
function maxValue() {
var max = arguments[0];
for (var i = 0; i < arguments.length; i++) {
if (max < arguments[i]) {
max = arguments[i];
}
}
return max;
}
console.log(maxValue(2, 4, 5, 9));
console.log(maxValue(12, 4, 9));
5、函数的两种定义方式:
函数声明方式
// 命名函数 有函数名 为 fn
function fn() { ....}
// 调用 那个地方调用都可以
fn()
函数表达式方式
// 跟声明变量的写法一致
var fn = function () { .... };
// 调用 函数调用必须写到声明下面
fn();
1、函数没有名字,我们称为匿名函数
2.这个fn 里面存储的是一个函数 其实fn是一个变量
3、这个执行的原理 跟我们 学的 变量使用一致的
var num = 10;
console.log(num);
num = 20;
console.log(num);
有些函数没必要一定给名字, 比如我们 点击某个按钮,就执行一个代码
// 点击按钮 就执行一段代码, 没必要给这个函数再命名了。直接跟一个匿名函数就好了
btn.onclick = function() { ...};
6、自执行函数
名函数除了作为参数传递外,也可以作为启动函数,定义后立即自执行
自执行函数的由来:
function fn(){}
fn();
//fn===function() {} 数学的代入法
//fn(); === function() {} ()即 (function(){})()
(function(){
console.log('我是自执行函数');
})()
自执行函数的写法
(function () {
})();
7、函数也是一种数据类型(不严谨)
函数可以接受任何类型的数据作为参数, 数值 字符 甚至是函数类型
//函数表达式
var fn=function (){}
console.log(typeof(fn)); //function
function fun(){
}
console.log(typeof(fun)); //function
8、函数也可以作为参数传递(了解):
function fun(ff){
//ff==function(){console.log('函数作为参数');}
console.log(ff);
}
fun(1); //1
fun('andy'); //andy
fun(function(){
console.log('函数作为参数');
}); // (){console.log('函数作为参数');}
function fun(ff){
//ff==function(){console.log('函数作为参数');}
// 跟 var fn=function(){}; fn()差不多
ff(); //调用 形参+()
}
fun(function(){
console.log('函数作为参数');
}); // 函数作为参数
function fun(ff){
ff(); //调用 形参+()
}
fun(hi);
//函数名里面存的是整个函数 hi=function hi(){console.log('你好吗?');}
function hi(){
console.log('你好吗?');
}
var a = 10;
function fun1(b){
// b = 20;
console.log(b);
}
fun1(a);
alert(a);//10
var c = [1,2,3,4];
function fun2(d){
d[4] = 5;
}
fun2(c);
alert(c);//[1,2,3,4,5]
var e=function(){
e=10;
}
function fun3(f){
f();
}
fun3(e);
console.log(e);
9、函数的返回值:
function back(){
return 666;
}
var result=back();
console.log(result); //666
函数是可以作为返回值使用的
function backFn(){
return function (){
console.log('我是作为返回值使用滴');
}
}
var fn=backFn();
fn(); //我是作为返回值使用滴
10、作用域:
就是变量可以起作用的区域
全局作用域和局部作用域
全局作用域:提供了代码的运行环境,比如说一个script标签或者一个独立js文件
局部作用域(函数作用域) : 当声明一个函数时,就创建了一个局部作用域
严格来说分为 函数作用域和块级作用域(es6版本添加了)
根据作用域的不同分为两种不同的变量:
全局变量和局部变量
全局变量:
在全局作用域里面的就是全局变量(在最外层函数外部的变量就是全局变量)
//只要在script中都可以使用
var num=20; //全局变量
console.log(num);
function fn(){
console.log(num);
}
fn();
局部变量
在局部作用域内的就是局部变量 (在函数内部申明的变量就是局部变量)
//局部变量只限于当前函数内部有效 外面的不可以使用
function fn1(){
var num1=10; //局部变量 只限函数内部
console.log(num1);
}
fn1(); //10
console.log(num1); //num1 is not defined
//局部变量只限于当前函数内部有效 外面的不可以使用
两种变量注意点:
1、在函数内部 变量未声明直接使用的 也算是全局变量(不太提倡使用)
function fn2(){
num1=10; //在函数内部未声明的变量当做全局变量
console.log(num1);
}
fn2(); //10
console.log(num1); //10
2、形参 属于局部变量
function fn3(x,y){
console.log(x);
}
fn3(1,2);
console.log(x); //x is not defined
3、局部变量 写在函数内部 当我们函数执行完毕后,里面的局部变量就自动销毁。 释放内存空间,比较节约资源 我们更喜欢局部变量
4、全局变量 只有浏览器关闭的时候才会销毁。 比较浪费资源,我们不太提倡使用。
注意:自执行函数的作用域需要特别注意
(function (){
var num=10; //对fn来说是全局变量 但是仍在函数里 所以还是局部变量
unction fn(){};
fn();
})()
作用域链
按照链式方式去查找,最终决定变量使用哪个值的过程(就近原则)
案例:
function f1() {
var num = 123;
function f2() {
console.log(num);
}
f2();
}
var num = 456;
f1();