案例:斐波那契数列
<script>
//求斐波那契数列,12---144
//1 1 2 3 5 8 13 21 34 55 89 144
function getFib(num) {
var num1=1;
var num2=1;
var sum=0;
for(var i=3;i<=num;i++){
sum=num1+num2;
num1=num2;
num2=sum;
}
return sum;
}
console.log(getFib(12));
</script>
arguments的使用:定义一个函数,如果不确定用户是否传入了参数,或者说不知道用户传了几个参数
function f1() {
//arguments----->数组使用------伪数组---
var sum=0;
for(var i=0;i<arguments.length;i++){
sum+=arguments[i];
}
return sum;
}
console.log(f1(10,20,30));
命名函数:函数如果有名字,就是命名函数
* 把一个函数给一个变量,此时形成了函数表达式
* 例子:
* var f1=function (){
*
* };
* 如果是函数表达式,那么此时前面的变量中存储的就是一个函数,而这个变量就相当于是一个函数,就可以直接加小括号调用了
* f1();
*
* 注意:
* 函数表达式后面,赋值结束后,要加分号
匿名函数:函数如果没有名字,就是匿名函数
函数的自调用,没有名字,调用---声明的同时,直接调用
//一次性的--------
// (function(){console.log("阿姆斯特朗回旋加速");})(); 自动调用并进行打印
// //函数表达式
// var f2 = function () {
// console.log("哈哈,真的好帅哦");
// };
// //匿名函数不能直接调用(这里指的是没有进行var f2=这样的操作)
// f2();
function 类型
<script>
function f1() {
console.log("我是函数");
}
//如何获取某个变量的类型? typeof
console.log(typeof f1);
//函数是有数据类型,数据类型:是function 类型的
</script>
回调函数
//函数可以作为参数使用,如果一个函数作为参数,那么我们说这个参数(函数)可以叫回调函数
//只要是看到一个函数作为参数使用了,那就是回调函数
<script>
function sayHi(fn) {
console.log("您好啊");
fn();//fn此时应该是一个函数
}
function suSay() {
console.log("我猥琐,我邪恶,我龌龊,小苏说");
}
sayHi(suSay);
</script>
函数是可以作为返回值使用的
<script>
//结论:函数是可以作为返回值使用的:
function f1() {
console.log("f1函数调用了");
return function () {
console.log("这是一个函数");
};
}
var ff=f1();//调用
//ff就是一个函数了
ff();
</script>
作用域:使用范围
* 全局变量:声明的变量是使用var声明的,那么这个变量就是全局变量,全局变量可以在页面的任何位置使用
* 除了函数以外,其他的任何位置定义的变量都是全局变量
* 局部变量:在函数内部定义的变量,是局部变量,外面不能使用,局部变量使用匿名全局变量修饰(num=10),函数调用后外部可以进行访问,下边第二个代码段说明该点。
* 全局变量,如果页面不关闭,那么就不会释放,就会占空间,消耗内存
<script>
function f(){
var n=5;
}
console.info(n); //无法访问到n变量,javaScript中只有在函数中有块的概念
</script>
*
* 全局作用域:全局变量的使用范围
* 局部作用域:局部变量的使用范围
*
* 块级作用域:一对大括号就可以看成是一块,在这块区域中定义的变量,只能在这个区域中使用,但是在js中在这个块级作用域中定义的变量,外面也能使用;
{
var num=10;
console.log(num);//10
}
console.log(num);//10
* 说明:js没有块级作用域,只有函数除外
*
* 隐式全局变量:声明的变量没有var,就叫隐式全局变量
<script>
function f(){
n=5;
}
f();
console.info(n);//5
</script>
* 全局变量是不能被删除的,隐式全局变量是可以被删除的
* 定义变量使用var是不会被删除的,没有var是可以删除的
作用域链:想链条一样连接,被包含函数中无法调用包含函数中定义的变量
<script>
var num=10;
function f1() {
var num=20;
function f2() {
console.info(num);//undefined
var num=30;
function f3() {
var num=50;
console.log(num);//50
}
f3();
}
f2();
}
f1();
</script>
预解析
* 把变量的声明提前了----提前到当前所在的作用域的最上面
* 函数的声明也会被提前---提前到当前所在的作用域的最上面
注意:
//预解析中,变量的提升,只会在当前的作用域中提升,提前到当前的作用域的最上面
//函数中的变量只会提前到函数的作用域中的最前面,不会出去
//预解析会分段(多对的script标签中函数重名,预解析的时候不会冲突),一个script中允许出现同名函数,但是预解析会存在覆盖,最好避免同名函数的使用。
//与java语言不同,函数的调用只根据函数名来进行区分,与参数无关,同名参数存在覆盖
//匿名函数不存在预解析,必须声明然后再进行调用,否则会直接报错。
<script>
console.log(num);//①没有声明,直接报错的
//分割线-----------------------------------
console.log(num);//②显示undefined,因为预解析,将变量的声明提升,但是未进行赋值即:var num;
var num=10;
//分割线-----------------------------------
f1();//函数调用的时候,把会函数的声明提升到作用域的上面
function f1(){
console.info("函数调用的时候,把会函数的声明提升到作用域的上面");
}
//分割线-----------------------------------
function f1() {
console.log("小苏好猥琐");
}
f1();
function f1() {
console.log("小苏没有助教猥琐");
}
f1();//执行结果是输出了两次"小苏没有助教猥琐":第一IC调用的使用预解析,将下边的f1提前了,所以两次调用都使用的第二个f1函数。
//分割线-----------------------------------
f1();
//var num=20; 如果这里加一个声明,输出结果还是undefined,变量的使用还是有就近原则的,这里使用了为进过初始化的num.
function f1(){
console.info(num);//undefined:说明预解析提前了声明但是未赋值
var num=10;
}
//分割线-----------------------------------
f1();
var num=20; 输出结果还是undefined,方法调用在声明之前,预解析方法声明提前,此时num还未初始化。
function f1(){
console.info(num);//undefined:预解析提前
}
</script>