首页 > 代码库 > JS 11

JS 11

1. *****作用域和作用域链

2. *****闭包

 

1. *****作用域和作用域链

   作用域scope:

     什么是: 一个变量的使用范围——使用

                 本质上作用域是一个对象——存储

                     作用域中的变量都是对象的成员

     程序/函数的执行过程:

        1. 开始执行程序前:

            创建ECS(执行环境栈):

                依次保存每个调用的函数的执行环境

            在ECS中压入第一个全局执行环境(全局EC)

            创建window对象,全局EC引用window对象

            window就是全局作用域对象

        2. 开始执行程序:

            所有全局变量都保存在全局作用域对象window中

        3. 定义函数时:

            在全局添加函数名变量

            创建函数对象封装函数定义

            函数名变量引用函数对象

            函数对象中有一个scope属性,引用回创建函数时的作用域对象。通常都是window。

        4. 调用函数时:

            在ECS中压入一个新的EC

            为本次函数调用创建专门的活动对象(AO)

            在AO中创建所有函数定义中规定的局部变量

            其实AO就是函数作用域对象

                 所有局部变量都是AO的成员

            新的EC引用活动对象AO

            AO的parent指向window

            变量的使用顺序:

               先用AO(函数作用域)中的局部变量

               如果AO中没有,才去window(全局作用域)中找

        5. 函数调用后:

            本次函数调用的EC出栈

                导致函数作用域对象AO释放

                       导致局部变量一同释放

   作用域链(scope chain): 由多个作用域对象连续引用形成的链式结构。

      顺序: 先函数作用域对象AO->全局作用域对象window

      所有的变量都保存在作用域链上的对象中

          局部变量都保存在函数作用域对象AO中

          全局变量都保存在全局作用域对象window中

      控制了: 变量的使用顺序

        先用AO(函数作用域)中的局部变量

               如果AO中没有,才去window(全局作用域)中找

 

   闭包:

     什么是: 即重用变量,又防止变量被污染的一种机制

     为什么: 全局变量: 优: 可重用     缺: 易被全局污染

                 局部变量: 优: 不会被污染    缺: 不可重用

     何时: 即重用变量,又防止变量被污染

     如何: 3步:

        1. 用外层函数包裹住受保护的变量和操作变量的内层函数

        2. 外层函数将内层函数返回到外部,被外部的变量保存

        3. 通过外部变量调用内层函数,访问受保护的变量

     缺: 1. 占用更多内存: 外层函数的AO

          2. 容易造成内存泄漏

     三特点: 1. 函数嵌套:

                  2. 外层函数包含一个受保护的局部变量

                 3. 外层函数将内层函数对象返回

 

 

 

 

1. *****面向对象OOP:

   什么是: 程序中都是先用对象来定义数据和功能,再按照逻辑的需要,访问对象中的数据和功能。

   为什么: 和现实中人的想法非常接近。

   什么是对象: 内存中同时存储多个数据和功能的存储空间

              描述现实中一个具体事物的属性和功能的程序结构

                     事物的属性,会成为对象中的属性

                     事物的功能,会成为对象中的方法

   何时: 今后开始写程序前,都要先用对象,描述好要操作的事物的属性和功能,再按需使用对象的功能,访问对象的属性

   如何: 面向对象三大特点: 封装,继承,多态

      封装: 将一个具体事物的属性和功能集中定义在一个对象中

      创建自定义对象: ——封装   3种:

         1. 使用对象直接量:

              var obj={

                  属性名: 属性值,

                         ... : ... ,

                  方法名: function(){... this.属性名 ...},

                         ... : ... ,

              }

          强调: 对象自己的方法,要访问自己的属性,必须用this.属性名.

           this->正在调用函数的当前对象自己

 

       2. 使用new: 2步: 

          var obj=new Object(); //创建一个空对象

          //向空对象中添加属性和方法

          obj.属性名=属性值;

          obj.方法名=function(){...this.属性名...};

         

     对象的本质: js中一切对象的底层都是关联数组

                        每个属性/方法都是关联数组中的元素

                        属性名/方法名是key,属性值/函数对象是value

 

      问题: 一次只能创建一个对象

       3. 解决: 用构造函数:

          什么是构造函数: 专门描述一类对象统一结构的函数

          何时: 今后只要反复创建多个相同结构的对象时,都要先定义构造函数

          为什么: 复用对象的结构代码

          如何: 2步:

            1. 定义构造函数

                function 类型名(属性参数列表){

                     this.属性名=属性参数值;

                               ...=...;

                     this.方法名=function(){ ... this.属性名 ...  }

                }

            2. 用new调用构造函数,创建并装修新对象

                var obj=new 类型名(属性值列表);

                     创建一个指定“类型”的对象

                     用new调用指定"类型"的构造函数来创建对象

              new: 4件事:

                1. 创建新的空对象

                2. 让新对象继承构造函数的原型对象

                3. 用新对象去调用构造函数

                      向新对象中添加构造函数规定的属性

                      将属性参数的值,保存到新对象的新属性中

                      向新对象中添加构造函数规定的方法

                4. 将新对象的地址保存在变量

 

      按需访问对象的属性,调用对象的方法: 

         访问对象的属性: obj.属性名   用法和普通的变量完全一样

                属性就是保存在对象中的一个变量

         调用对象的方法: obj.方法名() 用法和普通的函数完全一样

            强调: 方法中的this,默认指.前的对象

 

      构造函数的问题: 只能复用代码,不能节约内存

 

      继承: 父对象的成员,子对象不用重复创建,也可直接使用

      为什么: 即节约内存,又代码重用

      何时: 只要一类子对象,需要相同的属性或功能时,都要将相同的属性和功能仅在父对象中定义一次即可

      如何:

        原型对象: 集中存储同一类型的子对象所需的所有共有属性和方法的父对象

 

JS 11