1. *****OOP

   内置对象的原型对象

   共有属性和自有属性

   原型链

   原型相关API

*****自定义继承


1. 内置对象的原型对象: 

   所有内置对象都是一个构造函数(除Math外)

   每类内置对象都有自己的原型对象(prototype)

   所有内置对象的API都保存在类型.prototype对象中

   何时: 解决浏览器兼容问题: 2步:

      如果类型.prototype.方法===undefined

         类型.prototype.方法=function(...){

            this->自动获得将来调用该方法的当前对象

         }


2. 共有属性和自有属性: 

   自有属性: 直接保存在对象本地的属性

   共有属性: 保存在父级原型对象中的属性

   访问共有/自有属性:

      读取属性值: 即可用子对象读取,也可用原型对象读取

      修改属性值: 

          自有属性: 子对象.属性名=值

          共有属性: 原型对象.属性名=值 

   如何判断自有还是共有: 

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

          判断obj中是否包含自有属性"属性名"

      共有: 不是自有! 且 子对象可访问到!


3. ***原型链(prototype chain):

   什么是原型链: 多级父对象连续继承,形成的链式结构

      保存了: 对象的属性和方法

      控制了: 对象的成员的使用顺序

         优先使用自有成员

         自己没有才延原型链向父级查找,只要找到就不再向上

         如果整个原型链上都没有,才返回undefind

   vs 作用域链(scope chain)

      保存了: 全局/局部的变量

      控制了: 变量的使用顺序

         优先在当前函数调用的函数作用域对象(AO)中查找

         如果函数作用域对象(AO)中没有,才延作用域链向全局方向查找。只要找到,就不再继续

         如果整个作用域链上都没有,才报错


鄙视题: 判断一个对象是不是数组类型,有几种方式

   0. typeof只能区分基础类型和function

              无法进一步区分对象的类型

   1. 判断原型对象: 

     如果obj的原型是Array.prototype说明是数组

      obj.__proto__==Array.prototype 

      问题: __proto__是内部属性,本来浏览器是禁止使用的

      解决: Object.getPrototypeOf(obj)

               获得obj的原型对象 

1. *****OOP

   原型链

*****自定义继承


1. 原型链: 

  判断一个对象是不是数组类型,有几种方法: 4种

  0. typeof X

  1. 判断原型对象: 

     obj.__proto__==Array.prototype

         问题: __proto__是内部属性,可能不允许使用

         Object.getPrototypeOf(obj)==Array.prototype

              问题: 只能判断直接父对象是Array.prototype的情况

                       无法判断间接继承Array.prototype的情况

              解决: var bool=father.isPrototypeOf(child)

                  判断father是否是child的父级对象

                     不但检查直接父对象,且检查整个原型链!

   2. 判断构造函数: 

       每个原型对象都有一个constructor属性指回构造函数

       obj.constructor==Array 

       还可以用: obj instanceof Array

          instance: 实例-用一个构造函数创建出的一个具体对象

         比如: var lilei=new Student(...);

                 称lilei是Student类型的一个实例

                 实例化一个Student类型的对象lilei

          检查整个原型链


   要求不够严格: 只要有继承关系,就认为是数组

   要求严格: 只有用数组类型创建的对象,才是真正的数组。


   3. 检查对象的class属性

      什么是class: 对象的内部属性,专门保存创建对象时使用的类型名。

       只有一个办法获得class属性值: 

          调用Object.prototype.toString();->"[object Class]"

      问题: 所有内置对象都重写了Object中的toString

         重写(override): 如果子对象觉得,父对象的成员不好用,可在本地定义同名的自有成员,覆盖父对象中的。

         ——多态

      解决: 用call强行借用

        call: 强行借用一个本无法调用的方法

        何时:  想调用一个原本无法调用的方法

        如何: 想借用的函数.call(要替换的对象)

             比如: Object.prototype.toString.call(obj)

                         相当于: obj.toString()

                         返回: "[object Class]"


   4. Array.isArray(obj);

      问题: ES5   IE9+

      解决: 自定义isArray方法


鄙视题: 对象实例方法 vs 构造函数方法

     对象实例方法: 必须用一个对象实例才能调用的方法

                            仅当前类型的对象可用!

        对象实例方法一律保存在该类型的原型对象中,所有子对象共用。

        何时: 一个方法只希望当前类型的子对象才能使用时

     构造函数方法: 不需要任何对象实例,用构造函数即可直接调用的方法。

       构造函数方法一律保存在构造函数对象上

        何时: 一个方法的执行和对象的类型无关时


2. *****自定义继承关系:

    1. 修改单个对象的继承关系: 

       obj.__proto__=father; 

       问题: 内部属性: Object.setPrototypeOf(child,father);

                   设置child继承father

    2. 批量修改多个对象的继承关系: 

       直接修改构造函数的prototype引用新的父对象

       obj.prototype=father

       强调: 必须在创建第一个子对象之前就换

    3. 两种类型间的继承: 最像Java的继承

      何时: 只要两种类型间包含相同的属性结构定义或相同的方法。

      如何: 3步: 

         1. 抽象出一个父类型

             共同的属性定义,集中到父类型的构造函数中

             共同的方法,集中到父类型的原型对象中

         2. 在子类型构造函数中借用父类型构造函数

              不能直接调用: this->window

             应该用call,将this替换为当前正在创建的新对象

               父类型构造.call(this,参数...)

         3. 让子类型原型对象继承父类型原型对象