知识内容:
1.JavaScript函数
2.JavaScript作用域
参考资料:《JavaScript高级程序设计》
一、JavaScript中的函数
1.函数的定义
学完python后,对函数的定义一定不再陌生了,函数对于任何一个语言来说都是核心的概念。通过函数我们可以封装任意多条语句,而且可以在任何地方任何时候调用执行。JavaScript中的函数使用function来声明定义,函数的基本语法如下:
1 function functionName (arg0, arg1, ..., argN){ 2 statements 3 } 4 5 // 以下是一个函数示例: 6 function sayHi(name, message){ // 定义函数 7 alert("Hello " + name + ", " + message); 8 } 9 sayHi("wyb", "Good morning!"); // 调用函数
或者以下面的这种方式定义函数:
1 sayHi = function() { 2 console.log("Hello, world!"); 3 } 4 5 sayHi();
2.函数的参数与返回值
(1)函数的参数
像上面的例子中出现的参数都叫命名参数,类似python中的普通参数,在这里不做详细解释
JavaScript中函数的参数在内部是用一个数组表示,函数接受的始终是这个数组,而不关心数组中包含哪些参数。实际上函数可以通过arguments对象来访问这个参数数组,从而获取传递给函数的每一个参数
arguments对象:
- 访问参数 - arguments[index]
- 获取参数个数 - length属性
1 function sayHi(){ 2 console.log("Hello " + arguments[0] + "," + arguments[1]); 3 console.log(arguments.length); // 输出传入的参数个数 4 } 5 6 sayHi("wyb", "good morning!"); 7 8 // console.log() -> 在浏览器中的命令行输出
根据arguments对象实现让函数接受任意个参数并分别实现适当的功能:
1 function add(){ 2 if (arguments.length == 1){ 3 alert(arguments[0]); 4 } 5 else if (arguments.length == 2){ 6 alert(arguments[0] + arguments[1]); 7 } 8 } 9 10 add(10); // 10 11 add(10, 20); // 30
另外arguments对象可以和传统的命名参数一起结合使用:
1 function add(num1, num2){ 2 if (arguments.length == 1){ 3 alert(num1); 4 } 5 else if (arguments.length == 2){ 6 alert(num1 + arguments[1]); 7 } 8 } 9 10 add(10); // 10 11 add(10, 20); // 30
在上面这个程序中num1就相当于arguments[0],num2就相当于arguments[1],另外arguments的值始终和对应命名参数的值保持一致
注:没有传值的命名参数就被自动赋予undefined值类似变量定义时没有初始化一样;JavaScript中所有参数传递的都是值,不可能通过引用传递参数
(2)返回值
- JavaScript中函数可以有也可以没有返回值,使用return来返回返回值
- 函数会在return之后停止执行并立即退出,退出之后位于return之后的语句将不会执行;
- 函数中可以多个return
- return也可以不带任何返回值
1 // 带返回值的函数 2 function sum(num1, num2){ 3 return num1 + num2; 4 } 5 6 // return之后的语句不会执行 7 function sum(num1, num2){ 8 return num1 + num2; 9 alert("return之后的语句不会执行"); // 不会执行 10 } 11 12 // 包含多个return 13 function diff(num1, num2){ 14 if (num1 < num2) { 15 return num2 - num1; 16 } 17 else { 18 return num1 - num2; 19 } 20 } 21 22 // 不带任何返回值的return 23 function sayHi(name, message){ 24 alert("Hello " + name + ", " + message); 25 return; 26 } 27 sayHi("wyb", "Good morning!");
3.JavaScript函数注意事项
(1)JavaScript函数无重载
传统的重载:
Java和C++中的重载是可以为一个函数编写两个定义,只要这两个函数接受参数的类型和数量不同即可
JavaScript中不存在上述传统意义上的重载,但是JavaScript可以提过检查传入函数中的参数的类型和数量从而做出不同的反应,可以模拟重载,例如下面这一段:
1 function add(){ 2 if (arguments.length == 1){ 3 alert(arguments[0]); 4 } 5 else if (arguments.length == 2){ 6 alert(arguments[0] + arguments[1]); 7 } 8 } 9 10 add(10); // 10 11 add(10, 20); // 30
4.JavaScript3种基本函数
(1)普通函数
上面所有的函数均是普通函数
1 function func(arg){ 2 return true; 3 }
(2)匿名函数
没有名字的函数
1 var func = function(arg){ 2 return "tony"; 3 } 4 5 setInterval(function(){ 6 console.log(123); 7 }, 5000)
(3)自执行函数
程序从上到下解释执行,创建函数并且自动执行
1 (function(arg){ 2 console.log(arg); 3 })(‘123‘)
二、JavaScript作用域
1.JavaScript执行环境
执行环境:定义变量及函数有权访问的数据,决定它们各自的行为。每个执行环境都有一个与之关联的变量对象,环境中定义的所有变量和函数都保存在这个对象中
某个执行环境中的所有代码执行完毕后,该环境被销毁,保存在其中的所有变量和函数定义也随之销毁(全局执行环境直到应用程序退出-例如关闭网页或浏览器时才会被销毁)
函数与执行环境:每个函数都有自己的执行环境,当执行流进入一个函数时,函数的环境就会被推入一个环境栈中,而在函数执行之后,栈将其环境弹出,把控制权返回给之前的执行环境
2.作用域
什么是作用域:一段程序代码中所用到的名字并不总是有效/可用的,而限定这个名字的可用性的代码范围就是这个名字的作用域
- C/C++/C#/Java等语言以代码块为作用域 -> 代码块以{}区分
- python/JavaScript以函数为作用域
关于JavaScript的作用域:JavaScript中每个函数都有自己的作用域,当出现函数嵌套时,就出现了作用域链。当内层函数使用变量时,会根据作用域链从内到外一层层的循环,如果不存在,则异常
1 public void Func(){ 2 if(1==1) 3 { 4 string name = "java"; 5 console.writeline(name); // 正常运行 6 } 7 console.writeline(name); // 报错 8 } 9 10 Func()
1 def func(): 2 if 1==1: 3 name = "python" 4 print(name) // 正常运行 5 print(name) // 正常运行 6 7 func() 8 print(name) // 报错
function func(){ if(1==1){ var name = "javascript"; console.log(name); // 正常运行 } console.log(name); // 正常运行 } func(); console.log(name); // 报错
3.作用域链
当代码在一个环境中执行时,会创建变量对象的一个作用域链
作用域链的作用:保证对执行环境有权访问的所有变量和函数的有序访问
关于作用域和作用域链:
- 函数的作用域在函数未被调用之前就已经创建
- 函数的作用域存在作用域链,作用域链也是在函数被调用之前创建的
1 // 函数的作用域在函数未被调用之前确定 2 name = "wyb" 3 function func(){ 4 var name = "xxx"; 5 function inner(){ 6 var name = "ooo"; 7 console.log(name); // 输出: ooo 8 } 9 10 inner() 11 } 12 13 func(); 14 15 16 name = "wyb" 17 function func(){ 18 var name = "xxx"; 19 function inner(){ 20 // var name = "ooo"; 21 console.log(name); // 输出: xxx 22 } 23 24 inner() 25 } 26 27 func() 28 29 30 name = "wyb" 31 function func(){ 32 // var name = "xxx"; 33 function inner(){ 34 // var name = "ooo"; 35 console.log(name); // 输出: wyb 36 } 37 38 inner() 39 } 40 41 func() 42 43 44 // 函数的作用域存在作用域链 作用域链也是在函数被调用之前创建的 45 name = "wyb" 46 function func(){ 47 var name = "xxx"; 48 function inner(){ 49 var name = "ooo"; 50 console.log(name); // 输出: ooo 51 } 52 53 return inner; 54 } 55 56 var ret = func() 57 ret() 58 59 60 name = "wyb" 61 function func(){ 62 var name = "xxx"; 63 function inner(){ 64 // var name = "ooo"; 65 console.log(name); // 输出: xxx 66 } 67 68 return inner; 69 } 70 71 var ret = func() 72 ret() 73 74 75 name = "wyb" 76 function func(){ 77 // var name = "xxx"; 78 function inner(){ 79 // var name = "ooo"; 80 console.log(name); // 输出: wyb 81 } 82 83 return inner; 84 } 85 86 var ret = func() 87 ret()
注意以下问题:
1 name = "wyb" 2 function func(){ 3 var name = "xxx"; 4 function inner(){ 5 // var name = "ooo"; 6 console.log(name); // 输出: tony 7 } 8 var name = "tony"; 9 10 return inner; 11 } 12 13 var ret = func() 14 ret()
输出tony的原因是:
4.函数内局部变量会提前声明
1 // 函数内部局部变量会提前声明 2 // 当解释程序时,在函数提前生成作用域链的同时找到内部所有的局部变量 3 // 然后提前声明变量 var xxoo; // 此时输出xxoo的值为undefined 4 5 function func(){ 6 console.log(xxoo); 7 } 8 9 func() // 程序直接报错 10 11 12 function func(){ 13 console.log(xxoo); 14 var xxoo = "666"; 15 } 16 17 func() // undefined
原文地址:https://www.cnblogs.com/wyb666/p/9326768.html