渡一教育公开课web前端开发JavaScript精英课学习笔记(五)函数及预编译

函数(方法)

被调用时执行的可重复使用的代码块。

函数定义

<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>

 

  • 3
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值