递归
function auto(){//无限执行,自己调用自己
auto();
}
auto();
会报错(调用栈溢出重复执行导致内存不够)
在函数内部 重复调用函数自身 这个情况叫做递归
1.求1-100之内的所有偶数和
2+4+6+8+10+...100//1-100之内的偶数
100+98+96+...+4+2
function sum(n){
if(n==0){//递归出口
return 0;
}
return n+sum(n-2);//定义了一个条件
}
var result = sum(100);
console.log(result);
n=100
sum(100)
100+sum(98)
98+sum(96)
96+sum(94)
94+sum(92)
...
...
4+sum(2)
2+sum(0)
n=4
4+sum(2) 4+2
n=2
2+sum(0) 2+0
n=0
0
使用递归做某事时:首先是函数内部必须是使用自己调用自己的函数,但是一定要找到递归出口(如果找不找出口就会一直执行下去)
2、 求n的阶乘
求n的阶乘
5! = 5*4*3*2*1
= 5*4!
4*3!
3*2!
2*1!
1
7! = 7*6*5*4*3*2*1
n! = n*(n-1)*(n-2)*(n-3)*...2*1
n=5
fn(5)
5*fn(4)
4*fn(3)
3*fn(2)
2*fn(1)
function fn(n){
if(n==1){//递归出口
return 1;
}
return n*fn(n-1) //定义了一个条件
当n=5时 这个return 必须等到5*fn(4)的结果算出来之后 才能结束函数
}
var result = fn(5);
console.log(result);
3、求1-100之内所有能被3并且被5整除的数字之和
/*
*
* 求1-100之内所有能被3并且被5整除的数字之和
*
*
* fn(100)
* fn(99)
* fn(98)
* ...
* fn(90)
* 90+fn(89)
* fn(88)
* fn(87)
* ...
* fn(75)
* 75+fn(74)
* fn(73)
* ...
* fn(60)
* 60+fn(59)
* ...
* fn(45)
* 45+fn(44)
* ...
* fn(30)
* 30+fn(29)
* ...
* fn(15)
* 15+fn(14)
* ...
* fn(2) 0
* fn(1) 0
* fn(0) 0
*
*
*
*
* */
function fn(n){
if(n==0){//递归出口
return 0
}
if(n%3==0&&n%5==0){ //能够被3 和 5整除的数字
return n+fn(n-1)//定义了一个条件
}
return fn(n-1)
}
var result = fn(100);
console.log(result)
作用域
在JS中 变量有两个存放的区域
- 全局作用域
- 函数作用域
在函数作用域中可以使用全局变量
在全局作用域中不能够使用函数中的变量
var a = 1;//全局作用域中的变量
function auto(){
var a = 2;//函数作用域中的变量
console.log(2);
}
auto();
全局作用域
全局变量会自动成为window
对象的属性
window
对象也可以叫做Global Object GO
对象
打开浏览器 自动生成window
对象
关闭浏览器 window
对象就自动销毁了
console.log(window);
打开浏览器,浏览器会自动把全局变量储存在 window
对象里也就是Global Object GO
对象
var b = 'heaven';
console.log(window);
把变量b
作为GO对象
的属性名字,值heaven
作为GO对象属性值
把他存起来
一旦关掉浏览器window
对象就不复存在
function auto(){-->auto是全局作用域中的变量储存在GO对象里
var a = 2;//函数作用域中的变量
console.log(2);
}
auto();
var heaven = function(){//函数表达式也可以在全局变量中
console.log('heaven');
}
无论是变量还是函数,他都被放在全局变量当中,只要你是身处在全局
GO {
b:'heaven',
auto:function(){},
heaven:function(){}
}
全局的预编译三步:
- 创建
GO
对象 ==>Global Object
(GO对象) - 找到变量,把变量作为
GO
对象的属性名,值是undefined
- 在全局中找到函数声明,把函数名作为
GO
对象的属性名,值是函数体
预编译之后才能执行JS代码
等到关闭浏览器的时候 GO
对象就会被销毁了
函数作用域
Js解释引擎执行js代码的步骤
语法分析
Js解释引擎会先扫描所有的js代码,查看代码有没有低级的语法错误,如果存在语法错误,则整个程序就不会执行,如果没有语法错误,则进入预编译阶段
报错信息:Uncaught SyntaxError:Invalid or unexpected token表示语法错误
函数的预编译四步:(当时函数没有执行)
- 创建AO对象 ==>
Activated Object
(活动对象)【激活状态】 - 找到形参和变量,把形参和变量作为AO对象的属性名,值是
undefined
- 实参把值赋给形参
- 在函数中找到函数声明,把函数名作为AO对象的属性名,值是函数体
预编译之后才能执行JS代码
等到函数执行完成后(return)
AO
对象就会被销毁了
function auto(a){
var b = 3; --->var b;--->b=3;
console.log(a,b);
}
auto(2);
/*
1,AO{
a:2,undefined -->3,a:2
b:2,b -->3,b:3
}预先编译的环节,然后就执行函数内部的代码了
函数的预编译四步结束了
不符合条件直接跳过预编译然后就执行js代码
*/
AO对象
就像一个小型的仓库,他可以储存函数作用域中的变量,可以查找函数中的变量
function outer(){
/*
* AO{
* b:3,
* inner:function(){}
* }
* */
function inner(){
/*
* AO{
* a:4
* }
* */
var a = 4;
c = 5; //一个变量 没有var关键词 直接赋值 则这个是全局的 叫做暗示全局变量
console.log(a); //4 inner的AO中找到变量a
console.log(b); //3 outer的AO中找到变量b
console.log(c); //5 GO中找到变量c
}
var b = 3;
inner();
}
var a = 2;
outer();
console.log(outer);
/*
* GO{
* a:2,
* outer:function(){},
* c:5
* }
*
* */
c = 5;
一个变量 没有var关键词
直接赋值 则这个是全局的 叫做暗示全局变量
GO
和AO
都是相互独立的,如果没有相对应的变量会往父级去找,如果有就不会去父级找了
作用域有两个规则
- 规则是用来定义变量到底储存在哪里的
- 如何查询