函数概述、参数、返回值、函数名函数体和函数加载问题、函数声明、变量和作用域、隐式全局变量、变量声明提升。
1。函数的定义和使用
函数 ,具有一定功能的代码块 可以重复执行的代码块
函数不调用不执行 执行方法 fn()
函数定义 function fn(){}
预解析 function 和变量
函数调用可以在函数定义之前
<!DOCTYPE html> <html> <head> <title>函数的定义和使用</title> </head> <body> <script type="text/javascript"> fn_name(); function fn_name(){ alert(1); } // 定义函数 function getSum(){ var sum = 0; for (var i=1;i<=100;i++){ sum+=i; } alert(sum); } fn1(); // 会输出1 function fn1(){ alert(1+1); } function fn1(){ alert(1); } // a,b占位置用的,形参,形式上参与运算的值 function fn2(a,b){ alert(a+b); } fn2(4,4); // 4,4实参,实际上参与运算的值 fn2(1,2); fn3(); function fn3(a,b){ alert(a+b); // NaN alert(a); alert(b); // undefined,未定义,未赋值 document.getElementById(a).title='1'; // 未赋值,又进行强制操作,报错 } </script> </body> </html>
2.参数
参数 返回值 函数两大组成部分
函数的组成部分1:参数2返回值3功能
参数
需求1 1+1=? Alert(1+1)
需求2 2+2=? Alert(2+2)
需求3 4+4=? Alert(4+4)
需求随时会改变,
可能修改运算的值而不是功能,可以设置参数,解决问题。
形参 形式上参与运算的值,占位置
实参 实际上参与运算的值
实参想参与运算必须要有形参占位置。
参数:增加函数功能性 如1+1 -》 a+b 功能强大
程序员交互性
参数可拓展性
// a,b占位置用的,形参,形式上参与运算的值
function fn2(a,b){
alert(a+b);
}
fn2(4,4);
// 4,4实参,实际上参与运算的值
函数名相同,后面的函数会覆盖前面的函数。函数名不能相同
3参数个数问题
如果形参个数与实参个数不匹配
一般情况下,不会让形参和实参不匹配
- 形参=实参 正常执行
- 实参》形参 正常执行,多余的实参无意义,函数不使用
- 实参《形参 看程序具体内容是否报错 NaN,undefined,报错
未给定实参,undefined
本身没有赋值,又对其进行强制操作,报错
fn3();
function fn3(a,b){
alert(a+b);
// NaN
alert(a);
alert(b);
// undefined,未定义,未赋值
document.getElementById(a).title='1';
// 未赋值,又进行强制操作,报错
}
Js中没有方法重载,函数名相同(无关形参个数),后面的会覆盖前面的函数。
比如fn(a,b)
fn(a,b,c)
4.
- 返回值
什么是返回值:执行完毕函数以后,我们能给其他变量赋值。
把函数的值赋值给外面,使用return,否则返回值是undefined
返回值的作用:一般来说,函数通过运算出来的数都是一个半成品,需要二次加工,所有不能直接结束,需要在函数外部二次加工。
<!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8"> <title></title> </head> <body> <script> //函数的组成分为: 1.参数。 2.返回值。 3.功能。 //什么是返回值:执行完毕函数以后,我们能给其他变量赋值。 //返回值干什么用的呢?一般来讲,函数通过运算出来的数都是一个半成品,需要二次加工。 // 系统自带的函数,confirm等的返回值 var bool1 = confirm("我们结婚吧?"); console.log(bool1); // false,返回值是布尔值 var bool2 = alert("我们结婚吧?"); console.log(bool2); // undefined,返回值是undefined var bool3 = prompt("请输入:"); console.log(bool3); // 返回值输入什么就是什么 var aaa = fn(); console.log(aaa); function fn(){ var bbb = 111; //如果我们想把函数内部的值赋值为外部,必须使用return; //如果没有return或者只有return没有值,那么返回值都是undefined。 return bbb; } </script> </body> </html>
练习1:返回值必须执行函数才能得到,return可以退出函数
<!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8"> <title></title> </head> <body> <script> //函数的返回值必须要执行函数才能得到。 //求和: var num = getSum()+1+1+1; alert(num); function getSum(){ var sum = 0; for(var i=1;i<=100;i++){ sum+=i; } return sum; } //需求:1+1=2;拓展这个算式 var aaa = fn(1,1); alert(aaa); // 或者 alert(fn(2,2)); function fn(a,b){ //规则中有几个变化的值,我们就定义几个变量。 var sum = a+b; //外部要用哪个值,我们就返回哪个值。 return sum; } demo(); function demo(){ console.log(1); console.log(2); // return可以切断函数。 后面的所有代码不再执行 // break跳出这个循环。 continue跳出本次循环进入下一循环。 return; console.log(3); console.log(4); } </script> </body> </html>
练习二:
<!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8"> <title></title> </head> <body> <script> //(参数和返回值) //求圆的周长(long=2*pi*r) var long1 = getLong(0.5); console.log(long1); console.log(getLong(1)); function getLong(r){ // 通俗版 var pi = 3.141592653; var l = 2*pi*r; return l; } //求圆的和面积(area = pi*r*r) var area1 = getArea(1); console.log(area1); function getArea(r){ //通俗版 // var pi = 3.14; // var a = pi*r*r; // return a; //精简版 // var pi = Math.PI; // var a = pi*Math.pow(r,2); // return a; //最终版 return Math.PI*Math.pow(r,2); } //求2个数中的最大值 console.log(getMax(1,2)); function getMax(num1,num2){ // if(num1>num2){ // return num1; // }else{ // return num2; // } //return是可以切断函数的。 // if(num1>num2){ // return num1; // } // return num2; //三元运算 return num1>num2?num1:num2; } //求3个数中的最大值 console.log(getMaxThree(-1,0,3)); function getMaxThree(a,b,c){ // var d = a>b?a:b; // return d>c?d:c; //精简版 return (a>b?a:b)>c?(a>b?a:b):c; //判断a和b // if(a>b){ // //如果a大判断a和c // if(a>c){ // return a; // }else{ // return c; // } // }else{ // //如果b打,判断b和c // if(b>c){ // return b; // }else{ // return c; // } // } } //求一组数中的最大值 var arr = [-3,-2,-1,0,1,2,3]; var maxValue = getArrMax(arr); console.log(maxValue); console.log(getArrMax(arr)); function getArrMax(array){ //用的必须是形参的数组中的第一项。 var max = array[0]; for(var i=1;i<array.length;i++){ if(array[i]>max){ max = array[i]; } } return max; } //求一组数中的最小值 var arr = [-3,-2,-1,0,1,2,3]; var minValue = getArrMin(arr); console.log(minValue); console.log(getArrMin(arr)); function getArrMin(aaa){ //把数组中的第一位默认为,最小值。 var min = aaa[0]; for(var i=1;i<aaa.length;i++){ //判断数组中的每一项,如果下雨min,那么把他赋值给min if(aaa[i]<min){ min=aaa[i]; } } //书写位置要注意,一定是这个for循环执行完毕之后再返回 return min; } //翻转数组,返回一个新数组 //用两种方法做,第一种创建心数组。第二种直接修改原数组。 var arr1 = [1,2,3]; var arr2 = reverse1(arr1); console.log(arr2); console.log(reverse1(arr1)); //定义一个新数组,把老数组中的元素反向添加到新数组中 function reverse1(array){ var newArr = []; for(var i=array.length-1;i>=0;i--){ newArr[newArr.length] = array[i]; } return newArr; } var arr = [1,2,3]; console.log(arr); // console.log(reverse2(arr)); reverse2(arr); console.log(arr); //修改或者说翻转原数组,此方法没有返回值,所以只能打印原数组。 function reverse2(array){ for(var i=0;i<array.length/2;i++){ var temp = array[i]; array[i] = array[array.length-1-i]; array[array.length-1-i] = temp; } return array; //Array对象中的方法返回了一个数组。 } //对数组排序,从小到大 // var arr = [2,1,3,4]; var arr = [4,3,2,1]; console.log(bubble(arr)); function bubble(array){ //外循环控制轮数(元素-1) for(var i=0;i<array.length-1;i++){ //开闭原则(标志,标识,旗帜) var flag = true; //内循环控制次数(元素-1) for(var j=0;j<array.length-1-i;j++){ //判断符合标准就交换位置 if(array[j]>array[j+1]){ var temp = array[j]; array[j] = array[j+1]; array[j+1] = temp; flag = false; } } if(flag){ //此情况在数组是极限从大到小排列下,会出现问题。每一轮flag都是false,最终无返回值。 // return array; break; } } //有了return执行完毕方法后,就可以用变量接收返回值! return array; } </script> </body> </html>
练习3:
<!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8"> <title></title> </head> <body> <script> // 求阶乘 console.log(getJC(10)); function getJC(num){ var sumJC = 1; for(var i=1;i<=num;i++){ sumJC *= i; } return sumJC; } // 求1!+2!+3!+....+n!(函数嵌套) //求阶乘的和 console.log(getSumJC(4)); function getSumJC(number){ var sum = 0; for(var i=1;i<=number;i++){ sum += getJC(i);//求阶乘 } return sum; } // 判断一个数是否是素数(质数) //思路:除了自身和1以外,不能被其他数整除。 //注意点: //1.必须用for循环实现 //2.判断是否是素数,所以她的返回值应该是true或者false。 //3.如果num%i===0了,那么一定不是素数。只有出了1和自身以外所有的数都不能整除,那么才能说她是素数。 console.log(isPrime(3)); // function isPrime(num){ // //除了自身和1以外,不能被其他数整除。 // for(var i=2;i<num;i++){ // if(num%i===0){ // return false; // } // } // return true; // } //拓展1(了解) // function isPrime(num){ // //开闭原则 // var bool = true; // //除了自身和1以外,不能被其他数整除。 // for(var i=2;i<num;i++){ // if(num%i===0){ // bool = false; // } // } // return bool; // } //拓展2 function isPrime(num){ //除了自身和1以外,不能被其他数整除。 for(var i=2;i<=num/2;i++){ if(num%i===0){ return false; } } return true; } //拓展3 // function isPrime(num){ // //除了自身和1以外,不能被其他数整除。 // //判断一个数是不是指数,只需要判断到他的平方根,超过平方根在判断,无意义。 // //因为一个数是由两个数相称得到的,一个变大,另外一个必然变小,那么判断到这个数的平方根就已经是极限了,不必超过平方根 // for(var i=2;i<=Math.sqrt(num);i++){ // if(num%i===0){ // return false; // } // } // return true; // } </script> </body> </html>
5.函数名、函数体、函数加载
函数名,就等于整个函数。执行函数,就等于函数的功能+返回值。 js加载的时候只加载函数名,不加载函数体
<!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8"> <title></title> </head> <body> <script> //函数名,就等于整个函数。 //执行函数,就等于函数的功能+返回值; // js加载的时候只加载函数名,不加载函数体 //打印函数名,就等于打印整个函数。 console.log(fn); //打印执行函数,就等于打印函数的返回值。 console.log(fn()); //函数中包函数,先执行里面,后执行外面。 function fn(){ var arr = [1,3,3]; } </script> </body> </html>
6.函数的定义
三种定义方法
<!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8"> <title></title> </head> <body> <script> // //第一种定义方法最强大,定义完毕后,在哪里使用都可以,无位置限制。 // fn1(); // //后两种定义方法是有局限性的。(使用函数必须在定义函数之后) // fn2(); // fn3(); //第一种 function fn1(){ console.log("我是第一种定义方法!"); } //第二种(匿名函数),函数不会被提前,使用必须在定义之后 var fn2 = function (){ console.log("我是第二种定义方法!"); } //第三种 var fn3 = new Function("console.log('我是第三种定义方法!')"); // fn1(); // fn2(); // fn3(); </script> </body> </html>
7.变量和作用域
局部变量:只有局部能够访问到的变量
全局变量:在哪里都能访问的变量
隐式全局变量
<!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8"> <title></title> </head> <body> <script> //变量问题:根据作用范围,变量可以分为局部变量和全局变量。 //局部变量:只有局部能够访问的变量。存在的时间比较短,执行完函数之后会被回收。 //函数内部用var定义的变量。 //全局变量:在哪里都能访问到的变量。 //函数外部或者进入javascript之后立即定义的变量和函数内部不带有var的变量。 var num3 = 333; //全局变量 // //函数加载的时候,只加载函数名,不加载函数体。 function fn(){ //局部变量, var num1 = 111; //全局变量(成员变量) num2 = 222; console.log(num3); } // fn(); // console.log(num1); 访问不到,因为num1是局部变量 console.log(num2); // 执行fn()之后num2才能访问到,因为函数加载时候只加载函数名,不加载函数体 console.log(num3); // //块级作用域,js中没有。 // { // var aaa = 1; // } // 作用域指的是作用范围 //隐式全局变量 function fn(){ //b和c都是隐式全局变量 var a = b = c = 1; //e和f都是隐式全局变量(分号相当于换行) var d = 1;e =2;f=3; //g和i都不是隐式全局变量 ,g,h,i全是局部变量 // ,相当于共用一个var var g = 1,h= 2,i=3; } fn(); console.log(b); console.log(c); console.log(e); console.log(f); // console.log(a); // console.log(h); // console.log(i); </script> </body> </html>
8.变量声明提升和预解析
预解析:js的解析器在页面加载的时候,首先检查页面上的语法错误。把变量声明提升起来。
变量值提升变量名,不提升变量值。而用function直接定义的方法是整体提升。
1.查看语法错误。
2.变量声明提升和函数整体提升(变量声明提升的时候,只提升变量名,不提升变量值)
3.函数范围内,照样适用。
函数就近原则
<!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8"> <title></title> </head> <body> <script> // console.log(aaa);报错 // console.log(aaa); // var aaa; undefined 预解析 // console.log(aaa); // var aaa=111; undefined 预解析,但是变量值提升变量名,不提升变量值 var aaa; console.log(aaa); aaa = 111; fn(); // 形参bbb相当于局部变量 function fn(bbb){ // //函数的就近原则。局部变量能解决的不会使用全局变量。 // console.log(a); 报错 // var a; // console.log(a); undefined var aaa; //函数的就近原则。局部变量能解决的不会使用全局变量。这里的aaa是函数内部定义的局部变量 console.log(aaa); // undefined 变量声明提升在函数内部照样实用。 aaa = 222; } function fn2(bbb){ //两个函数中的局部变量不会相互影响。 console.log(bbb); } </script> </body> </html>
例子
<!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8"> <title></title> </head> <body> <script> // 1、----------------------------------- var num = 10; fun(); function fun(){ //变量声明提升 只提升变量名,不提升变量值。var num; console.log(num); // undefined var num = 20; } //// 2、----------------------------------- var a = 18; f1(); function f1(){ var b=9; console.log(a); // undefined,就近原则,函数内部有a的定义,此时a是局部变量;根据变量声明提升,只提升变量名,不提升变量值。 console.log(b); // 9 var a = '123'; } //// 3、----------------------------------- f2(); console.log(cc); // 9 输出顺序4 cc是全局变量,故有值 console.log(bb); console.log(aa); // 报错,aa是局部变量,函数执行结束变量已经销毁,没有定义过 function f2(){ var aa = bb = cc = 9; // bb、cc隐式全局变量 console.log(aa); // 9 输出顺序1 console.log(bb); // 9 输出顺序2 console.log(cc); // 9 输出顺序3 } </script> </body> </html>