面向对象、原型、闭包

**闭包:

    作用域:一个变量的可用范围

    作用域链:记录一个函数,可用作用域的*对象*!

    方法定义时:创建2个对象:

        1个对象:保存方法体的方法对象

        2个对象:当前方法的作用域链对象

                 作用域链对象中有一个元素指向全局对象

    方法调用过程中:创建1个对象,作用域链中多出一个新元素

        1个对象:创建该方法*本次调用*的*活动对象*

                 活动对象中保存了*本次调用*的局部变量

  如果方法定义中没有局部变量,活动对象中不会包含任何变量

        作用域链中新追加的元素,引用了活动对象

    方法调用结束后:作用域链中的新元素出栈

                    活动对象无人使用,自动回收释放

***闭包:

   为什么用闭包:全局变量可共享,但容易被污染

                 局部变量虽然私有,但不可重用/共享

   解决:3步:1. 用大的方法将变量和操作变量的方法封装起来

             2. 在外层方法结尾,将操作变量的方法对象返回

    3. 在全局,使用专门的方法名接住外层方法返回的函数对象

   何时使用闭包:保护可反复使用的局部变量

   判断闭包:3特点:

        1. 方法嵌套;

        2. 内层方法使用了外层方法的局部变量

        3. 内层方法被外层方法返回到外部,被反复调用。

1. 面向对象:

   1. 创建对象:3种方式

   2. 原型:

   3. 继承:

1. 创建自定义对象:

     对象:专门描述现实中一个东西的属性和功能的程序结构

         对象中封装了一个东西的属性以及对属性的操作方法

    如何创建:3种方式:

       1. 对象直接量的方式:

          var obj={属性名:属性值,

                   ... ...}

    ***js中对象的本质,其实是关联数组/Hash数组

      存入属性时,以hash算法,根据属性名计算存储位置

      读取属性时,以hash算法,快速算出存储位置,直接读取

    ***hash数组优点:极快的查找速度。与数据量无关。

       对象中的方法内,访问对象自己的属性:this.属性名

       this.读作“当前对象的”

       3. 使用对象模板/构造函数创建对象:

       何时使用:使用统一的数据结构,反复创建多个对象

        构造函数作用:2个:

           1. 接收要封装到对象中的属性值

            2. 用接收到的属性值,初始化对象的属性

        如何使用:2步:

            1. 先定义统一的对象结构/构造函数

        function 构造函数名(参数1,参数2,....){

            this.属性1=参数1;

            this.属性2=参数2;

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

        }

        其中,this表示当前正在创建的对象

            2. 使用new关键字,调用构造函数创建对象

        var obj=new 构造函数名(参数值1,参数值2,...);

                1. new 创建一个对象

                2. 按构造函数的规定,初始化对象中的属性

                3. ?

                4. 将新对象的地址,存入等号左边的变量中

. this:用在函数内,指代当前正在调用方法的对象。

     *this和定义时的对象无关。仅和调用时的对象有关*

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

       封装:对象内封装了描述一个事物的属性和方法

       多态:同一个对象,可以表现出不同的状态

       继承:子对象可以使用父对象中的属性和方法

2. 原型:集中存储多个对象共用的属性值和方法的父对象

     每个函数都有一个prototype属性指向自己的原型对象

     何时使用构造函数的原型?

         多个对象共用的属性值和方法,都要放在原型中。

         一次创建,反复使用。

     如何向原型中添加属性和方法:

         构造函数名.prototype.共享属性名=属性值

         构造函数名.prototype.共享方法名=function(){...}

     为对象扩展属性:

        1. 自有属性:通过对象的引用添加的属性;

                    其它对象无法访问。

        2. 原型属性:通过原型对象添加的属性;

                    所有继承自原型的子对象都可以访问

     获得对象的原型:2种

        1. 通过构造函数的prototype属性获得

        2. 通过Object.getPrototypeOf(obj)获得

      

     检测自有属性和原型属性:

        1. 检查在整个原型关系上是否存在某个属性:

           var bool="属性名" in 对象

           返回true:属性名包含在对象中或

                     也可能包含在原型对象中

           返回false:对象中和原型对象中一定都没有!

        2. 检查自有属性:

            var bool=obj.hasOwnProperty("属性名")

            返回true:对象中包含指定属性名

            返回false:仅说明对象中没有,

                       不能确定原型中是否包含

3. 面向对象:

    1. 多态:重写:子对象认为父对象中方法不好用!

                 可定义自有的同名方法,重写父对象中方法

    2. 继承:子对象可以直接使用父对象中的属性和功能

         为什么使用继承:代码重用

     如何实现继承:

            将要继承的父对象,设置为子对象的原型

          2种方式:

            1. 修改单个对象的原型:

               Object.setPrototypeOf(子对象,父对象)

             优:任何时候修改任何对象的父对象

             缺:每次仅能修改单个对象

            2. 批量修改多个对象的原型:

               修改构造函数的原型即可!

               构造函数.prototype=父对象

               创建对象之前!

             优:之后创建的所有子对象,自动继承父对象

缺:必须在创建对象之前修改!

2. prototype:存储多个对象共享的属性值或方法的父对象

    1. 所有方法都有prototype属性,指向自己的原型对象

    2. 所有对象都有__proto__属性,指向自己的父对象

         构造函数创建出的对象:

                __proto__指向构造函数的prototype对象

         使用直接量创建的单个对象:

                __proto__指向Object的prototype对象

3. 继承:子对象直接使用父对象的属性和功能。

     原型继承:将一个子对象的原型设置为另一个父对象

     如何实现继承:   

         1. 修改单个对象的__proto__属性

                Object.setPrototypeOf(子对象,父对象)

         2. 批量修改多个对象的原型:

              条件:在使用构造函数创建对象前

              构造函数.prototype=父对象

    var obj=new 构造函数(属性值1,属性值2,...);

            1. new 创建新对象

            2. 调用构造函数初始化对象中的属性和方法

            3. 将对象的__proto__设置为构造函数的原型

    4. 将新创建的对象的地址,存入全局变量obj中。

原文地址:https://www.cnblogs.com/baiyanfeng/p/5042814.html