函数(方法)
被调用时执行的可重复使用的代码块。
函数定义
<script type = "text/javascript">
//函数的定义方式,命名方式要遵循小驼峰形式。
function funcName(){
var a = 1;
document.write(a);
}
document.write(funcName.name);
var getFirstName = function theFirstName(){
var a = 1;
document.write(a);
}
document.write(getFirstName.name);
var getName = function(){
var a = 1;
document.write(a);
}
document.write(getName.name,"<br/>");
//定义带参数的函数,定义函数时声明的参数叫形式参数(形参)。
var getSum = function(a,b){
//每个函数都有一个内部数组,存储调用时传入的实参副本的列表。
//传入实参的值变化,对应的 arguments 也跟着变化。
document.write("传入的实参个数:" + arguments.length,"<br/>");
return a + b;//终止函数执行,并返回结果。
}
//调用自定义函数,调用函数时传入的参数叫实际参数(实参)。
var aa = getSum(10,30);
var bb = getSum(32,68);
var cc = getSum(435,6345,123,456);
document.write("函数形参个数:" + getSum.length,"<br/>");
document.write("调用函数返回:" + aa,"<br/>");
document.write("调用函数返回:" + bb,"<br/>");
document.write("调用函数返回:" + cc,"<br/>");
</script>
变量的作用域(上下文)
<script type = "text/javascript">
//函数的作用域
var a = 123;//全局变量,变量可以被所有对象调用。
function funcName(){
var b = 234;//局部变量,变量只可以被本函数内部对象调用。
function demo(){
var c = 456;//局部变量,变量只可以被本函数内部对象调用。
}
//这个获取不到 c 的值,只能获取 a b 的值。
}
//这里获取不到 b c 的值,只能获取 a 的值。
</script>
imply global暗示全局变量:如果变量未声明就赋值,此变量默认声明为全局变量。
一切声明的全局变量,全是window对象的属性。(即通过window对象的属性可访问变量,访问window对象的属性,可直接写属性名进行访问)。
相当于我们写的代码都是在 window 内部。
window{
//这里是我们编写的代码
var a = 123;
function funcName(){};
}
<script type = "text/javascript">
var a = 10;//定义全局变量
b = 20;//未声明就赋值,默认为全局变量
document.write(a,"<br/>");//全局变量为 window 的属性。直接写属性名就访问
document.write(window.a,"<br/>");//全局变量为 window 的属性。通过windows的属性访问
document.write(b,"<br/>");
document.write(window.b,"<br/>");
</script>
<script type = "text/javascript">
function demo(){
//赋值运算符执行顺序从右至左,下面代码相当于 b = 123;var a = b;所以 b 是全局变量, a 为局部变量
var a = b = 123;
}
demo()
document.write(b,"<br/>");
</script>
递归
函数内部调用函数本身
递归实现阶乘
求阶乘到 n 的结果
<script type = "text/javascript">
var n = 9;
function fn(n){
if(n < 2){
return 1;
}
// 获取调用者(被函数调用时)信息
console.log(arguments.callee.caller.name);
// arguments.callee 这个属性指向本函数(指针、句柄),作用是防止函数被改名后出现错误。
return n * arguments.callee(n - 1);
}
var b = fn;
function fnn(n){
return b(n);
}
var a = fnn(n);
document.write(a);
</script>
递归实现斐波那契数列
前两项之和等于第三位。1,1,2,3,5,8,13,21,34,55...............求第 n 位是多少?
<script type = "text/javascript">
var n = 9;
function fn(n){
if(n <= 2){
return 1;
}
return fn(n - 1) + fn(n - 2);
}
var b = fn(n);
document.write(b);
</script>
函数预编译
js执行分三步:1、语法分析,2、预编译,3、解释执行。
函数的预编译发生在函数执行前一刻,预编译时函数声明整体提升,变量声明提升。
练习分析执行过程
<script type = "text/javascript">
//函数执行前,进行预编译。
//1、预编译时创建 AO 对象(执行期上下文)。
//2、找形参和变量声明,将变量和形参名作为AO对象的属性名,值为undefined。
//模拟预编译对象
var AO = {
a:undefined,//同名的形参和变量声明,只作为一个属性。
b:undefined,//变量声明作为一个属性。这里不做方法声明。
c:undefined //形参作为一个属性。
}
//3、将实参值和形参统一,也就是给AO对象的属性赋值。
AO.a = 123;
AO.c = 456;
//4、找函数声明,函数名作为属性名,值赋予函数体。
AO.a = function a(){};
AO.d = function d(){};
document.write("执行期上下文对象执行前状态" ,"<br/>");
document.write("a = " + AO.a,"<br/>");
document.write("b = " + AO.b,"<br/>");
document.write("c = " + AO.c,"<br/>");
document.write("d = " + AO.d,"<br/>");
document.write("开始执行函数" ,"<br/>");
//开始执行函数
fn(234,456);
function fn(a,c){
document.write("1、a = " + a,"<br/>");//输出执行期上下文的属性 a 的值,即预编译的值。
var a = 123; //更改执行期上下文的属性 a 的值。
document.write("2、a = " + a,"<br/>");//输出执行期上下文的属性 a 的值.
function a(){}; //函数定义在预编译时处理,给执行期上下文的属性 a 的赋值,
document.write("3、a = " + a,"<br/>");//输出执行期上下文的属性 a 的值.未变动.
var b = function(){}; //更改执行期上下文的属性 b 的赋值,
document.write("4、b = " + b,"<br/>");//输出执行期上下文的属性 b 的值.
function d(){}; //函数定义在预编译时处理,给执行期上下文的属性 d 的赋值,
document.write("5、d = " + d,"<br/>");//输出执行期上下文的属性 d 的值.
}
</script>
<script type = "text/javascript">
//函数执行前,进行预编译。
//1、预编译时创建 AO 对象(执行期上下文)。
//2、找形参和变量声明,将变量和形参名作为AO对象的属性名,值为undefined。
//模拟预编译对象
var AO = {
a:undefined,//形参作为一个属性。
b:undefined,//形参作为一个属性。
c:undefined //变量声明作为一个属性。
}
//3、将实参值和形参统一,也就是给AO对象的属性赋值。
AO.a = 1;
//4、找函数声明,函数名作为属性名,值赋予函数体。
AO.b = function b(){};
AO.d = function d(){};
document.write("执行期上下文对象执行前状态" ,"<br/>");
document.write("a = " + AO.a,"<br/>");
document.write("b = " + AO.b,"<br/>");
document.write("c = " + AO.c,"<br/>");
document.write("d = " + AO.d,"<br/>");
document.write("开始执行函数" ,"<br/>");
//开始执行函数
demo(1);
function demo(a,b){
document.write("a = " + a,"<br/>");//输出属性 a 的值:1
a = 3;
b = 2; //运行时给属性 b 赋值:b = 2
function b(){};
document.write("b = " + b,"<br/>");//输出属性 b 的值:2
c = 0; //运行时给属性 c 赋值:c = 0
var c;
document.write("c = " + c,"<br/>");//输出属性 c 的值:0
function d(){};
document.write("d = " + d,"<br/>");//输出属性 d 的值:function d(){}
}
</script>
<script type = "text/javascript">
//函数执行前,进行预编译。
//1、预编译时创建 AO 对象(执行期上下文)。
//2、找形参和变量声明,将变量和形参名作为AO对象的属性名,值为undefined。
//模拟预编译对象
var AO = {
a:undefined,//形参和变量声明同名,作为一个属性。
b:undefined,//形参和变量声明同名,形参作为一个属性。
}
//3、将实参值和形参统一,也就是给AO对象的属性赋值。
AO.a = 1;
//4、找函数声明,函数名作为属性名,值赋予函数体。
AO.a = function a(){};
document.write("执行期上下文对象执行前状态" ,"<br/>");
document.write("a = " + AO.a,"<br/>");
document.write("b = " + AO.b,"<br/>");
document.write("开始执行函数" ,"<br/>");
//开始执行函数
demo(1);
function demo(a,b){
document.write("a = " + a,"<br/>");//function a(){}
document.write("b = " + b,"<br/>");//undefined
var b = 234;
document.write("a = " + a,"<br/>");//function a(){}
document.write("b = " + b,"<br/>");//234
a = 123;
document.write("a = " + a,"<br/>");//123
document.write("b = " + b,"<br/>");//234
function a(){}
document.write("a = " + a,"<br/>");//123
document.write("b = " + b,"<br/>");//234
var a;
document.write("a = " + a,"<br/>");//123
document.write("b = " + b,"<br/>");//234
b = 456;
document.write("a = " + a,"<br/>");//123
document.write("b = " + b,"<br/>");//456
var b = function(){}
document.write("a = " + a,"<br/>");//123
document.write("b = " + b,"<br/>");//function(){}
}
</script>
全局预编译
跟函数预编译区别在于参数,全局执行期上下文对象就是 window 对象。
练习分析执行过程
<script type = "text/javascript">
//全局预编译。
//1、预编译时创建 GO 对象(执行期上下文)。
//2、找变量声明,将变量作为GO对象的属性名,值为undefined。
//3、找函数声明,函数名作为属性名,值赋予函数体。
document.write("执行期上下文对象执行前状态" ,"<br/>");
document.write("a = " + window.a,"<br/>");
document.write("b = " + window.b,"<br/>");
document.write("开始执行下面代码" ,"<br/>");
var b = 234;
document.write("b = " + b,"<br/>");//234
a = 123;
document.write("a = " + a,"<br/>");//123
function a(){}
document.write("a = " + a,"<br/>");//123
var a;
document.write("a = " + a,"<br/>");//123
b = 456;
document.write("b = " + b,"<br/>");//456
var b = function(){}
document.write("b = " + b,"<br/>");//function b(){}
</script>
练习分析全局预编译
<script type = "text/javascript">
//全局预编译。
//1、预编译时创建 GO 对象(执行期上下文)。
//2、找变量声明,将变量作为GO对象的属性名,值为undefined。
//3、找函数声明,函数名作为属性名,值赋予函数体。
document.write("执行期上下文对象执行前状态" ,"<br/>");
document.write("test = " + window.test,"<br/>");
document.write("开始执行下面代码" ,"<br/>");
document.write("test = ",test ,"<br/>");//function test(){...}
function test(test){
document.write("test = ",test ,"<br/>");//function test(){}
var test = 234;
document.write("test = ",test ,"<br/>");//234
function test(){}
}
test(1);
var test = 123;
</script>
练习分析全局预编译
<script type = "text/javascript">
//全局预编译。
//1、预编译时创建 GO 对象(执行期上下文)。
//2、找变量声明,将变量作为GO对象的属性名,值为undefined。
//3、找函数声明,函数名作为属性名,值赋予函数体。
document.write("执行期上下文对象执行前状态" ,"<br/>");
document.write("global = " + window.global,"<br/>");
document.write("fn = " + window.fn,"<br/>");
document.write("开始执行下面代码" ,"<br/>");
global = 100;
function fn(){
document.write("global = ",global ,"<br/>");//undefined
global = 200;
document.write("global = ",global ,"<br/>");//200
var global = 300;
}
fn();
var global;
</script>
练习分析全局预编译
<script type = "text/javascript">
//全局预编译。
//1、预编译时创建 GO 对象(执行期上下文)。
//2、找变量声明,将变量作为GO对象的属性名,值为undefined。
//3、找函数声明,函数名作为属性名,值赋予函数体。
document.write("执行期上下文对象执行前状态" ,"<br/>");
document.write("a = " + window.a,"<br/>");
document.write("c = " + window.c,"<br/>");
document.write("demo = " + window.demo,"<br/>");
document.write("开始执行下面代码" ,"<br/>");
function demo(){
document.write("b = " ,b ,"<br/>");//undefined
if(a){
var b = 100;
document.write("b = " ,b ,"<br/>");//undefined
}
c = 234;
document.write("c = " ,c ,"<br/>");//234
}
var a;
demo();
a = 10;
document.write("c = " ,c ,"<br/>");//234
</script>