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. 让子类型原型对象继承父类型原型对象