javascript函数以及作用域简介

Posted 尹正杰

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了javascript函数以及作用域简介相关的知识,希望对你有一定的参考价值。

                    javascript函数以及作用域简介

                                      作者:尹正杰

版权声明:原创作品,谢绝转载!否则将追究法律责任。

 

一.基本函数

  对于JavaScript中函数参数,实际参数的个数可能小于形式参数的个数,函数内的特殊值arguments中封装了所有实际参数。JavaScript中函数基本上可以分为以下三类:

 1 <!DOCTYPE html>
 2 <html lang="en">
 3 <head>
 4     <meta charset="UTF-8">
 5     <title>尹正杰的基本函数</title>
 6 </head>
 7 <body>
 8 
 9 <script>
10     //1.普通函数定义
11     function Get(name) {
12         console.log(name);      //打印变量
13     }
14     Get("yinzhengjie");
15 
16     //2.自动执行函数,
17     (function (age) {
18         alert(age);            //弹窗效果的变量
19     })("18");
20 
21     function func(arg) {
22         arg()
23     }
24     //3.匿名函数,可以当做一个参数传递。
25     var yzj = function () {alert("尹正杰")};
26     func(yzj)
27 
28 </script>
29 
30 </body>
31 </html>

 

二.作用域

1.什么是作用域

  JavaScript中每个函数都有自己的作用域,当出现函数嵌套时,就出现了作用域链。当内层函数使用变量时,会根据作用域链从内到外一层层的循环,如果不存在,则异常。变量的作用域是在声明时决定的而不是调用执行时决定。也就是说,所有的作用域在创建函数且未执行时候就已经存在。

 1 <!DOCTYPE html>
 2 <html lang="en">
 3 <head>
 4     <meta charset="UTF-8">
 5     <title>Title</title>
 6 </head>
 7 <body>
 8 <script type="text/javascript">        //如果不写类型的话,默认就是type="text/javascript",注释方法和golang类似。
 9 var a=100,b=200;    
10 window.a =100;
11 window.b = 200;
12 function A() {
13     var a=33,b=99;
14     function B() {
15         var a=11,b=22;
16         console.log(a+b);
17     }
18     return B()  
19 }
20 A()
21 </script>
22 </body>
23 </html>

2.词法分析

  我们浏览器是如果分析我们的html文件呢?其实浏览器内置了html,css,javascript引擎分别取解析不同的代码。浏览器的js引擎在遇到函数的时候,在函数执行前,会进行一个预编译,这个预编译的过程就是词法分析。会形成一个活动对象,即Active Object,简称AO。词法分析分大致分为以下三个步骤:

  a>.分析函数的参数:

          如果没有参数的话,AO对象没有任何属性,例如:AO.age = undefined。如果有的话就回接受参数的值。如AO.age = 100.

  b>.分析函数的变量声明:

    会一次性拿到函数内的所有的变量名称,我们称如果没有函数生命表达式就不处理,这些变量名称为活动对象,它会将所有的变量保存起来,并赋值为undefined,当调用该函数的时候,它才会进行赋值操作。

  c>.分析函数的函数声明表达式

    所谓的函数声明表达式就是关键字“function(){}”,如果存在函数名称和变量名称重复, 就会用这个变量名称将之前的变量进行覆盖哟!

技术分享图片
 1 <!DOCTYPE html>
 2 <html lang="en">
 3 <head>
 4     <meta charset="UTF-8">
 5     <title>Title</title>
 6 </head>
 7 <body>
 8 <script>
 9     var str = "locale";         //当然,也可以这样写:    window.str = "locale";
10 
11     function t() {
12         console.log(str);           //输出“undefined”
13         var str = "locale";
14         console.log(str);           //输出“locale”
15     }
16     t();
17 </script>
18 </body>
19 </html>
作用域案例1
技术分享图片
 1 <!DOCTYPE html>
 2 <html lang="en">
 3 <head>
 4     <meta charset="UTF-8">
 5     <title>Title</title>
 6 </head>
 7 <body>
 8 <script>
 9     function t(age) {
10         console.log(age);  //此时的age已经被下面的函数表达式覆盖了,因此它的值为:“function age() {}”,
11         var age =99;
12         console.log(age);   //它的值应该是99,因为我们在他的上一行已经定义了他的值。
13         function age() {
14         }
15         console.log(age);   //同理,其值还是99
16     }
17 t(5);
18 </script>
19 </body>
20 </html>
作用域案例2

  如果你对词法分析的知识掌握以及很透彻了,那么上面的2道企业的面试题,你是否一眼能看出真身呢?

 

三.闭包函数

1.什么是闭包函数

  官方”的解释是:闭包是一个拥有许多变量和绑定了这些变量的环境的表达式(通常是一个函数),因而这些变量也是该表达式的一部分。相信很少有人能直接看懂这句话,因为他描述的太学术。我对闭包函数的理解就是父函数可以取到子函数的变量的函数就叫闭包函数。相信学习了作用域,也都明白全局变量和局部变量的意思吧,我们可以知道在函数中,一个局部变量作用域可以很轻松的拿到全局变量的数值,但是在全局变量作用域中想要拿到局部作用域的变量就得利用闭包函数啦。

2.闭包的作用

  闭包可以用在许多地方。它的最大用处有两个,一个是前面提到的可以读取函数内部的变量,另一个就是让这些变量的值始终保持在内存中。我们可以看以下案例:

 1 <!DOCTYPE html>
 2 <html lang="en">
 3 <head>
 4     <meta charset="UTF-8">
 5     <title>尹正杰的闭包函数</title>
 6 </head>
 7 <body>
 8 <script>
 9     function A(){
10         var n= 999;
11     nAdd = function(){n+=1001};
12     function B(){
13       alert(n);
14     }
15     return B;
16   }
17   var result=A();
18   result();         //调用A函数,于是会生成n和nAdd这两个变量,与此同时还会返回B的执行结果.
19   nAdd();           //我们将匿名函数nAdd执行。
20   result();         //由于上面执行了nAdd匿名函数,也就是将n的数值增加1001,因此我们看到的结果应该是2000才对。
21 </script>
22 </body>
23 </html>

3.使用闭包的注意点

  a>.由于闭包会使得函数中的变量都被保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题,在IE中可能导致内存泄露。解决方法是,在退出函数之前,将不使用的局部变量全部删除。

  b>.闭包会在父函数外部,改变父函数内部变量的值。所以,如果你把父函数当作对象(object)使用,把闭包当作它的公用方法(Public Method),把内部变量当作它的私有属性(private value),这时一定要小心,不要随便改变父函数内部变量的值。

 

四.面向对象

  其实在javascript编程里面,并没有用关键字定义一个对象类,它不像python或是golang等其他语言,有类似关键字“class”,或是“type .... struct”来声明一个对象。我们定义javascript的对象时,其实还是用function关键字来定义,只不过我们定义函数时并么有要求首字母是否大写,而定义一个对象时,潜规则就是函数名的首字母需要大写。

 1 <!DOCTYPE html>
 2 <html lang="en">
 3 <head>
 4     <meta charset="UTF-8">
 5     <title>尹正杰的面向对象</title>
 6 </head>
 7 <body>
 8 <script>
 9     //定义一个javascript的类,并初始化内部数据。
10     function Foo(name,age) {
11         this.Name = name;
12         this.Age = age;
13     }
14 
15     //给我们定义j具体的方法.我们称之为利用原型实现方法重用.
16     Foo.prototype = {
17         "show":function () {
18             alert(this.Name);
19         },
20         "print":function () {
21             alert("尹正杰");
22         }
23     };
24 
25     //实例化我们定义的对象,生成obj.
26     obj = new Foo("尹正杰",18);
27     alert(obj.Name);
28     alert(obj.print);
29 
30 </script>
31 </body>
32 </html>

 


以上是关于javascript函数以及作用域简介的主要内容,如果未能解决你的问题,请参考以下文章

JavaScript 作用域 与 作用域链

JS 作用域及作用域链

JS 作用域及作用域链

《你不知道的JavaScript》 函数作用域和块级作用域

JavaScript中的作用域和闭包

JavaScript中的作用域以及this变量