1. proto
以前要访问原型,必须使用构造函数来实现,无法直接使用实例对象来访问原型 火狐最早引入属性__proto__
,表示使用实例对象引用原型. 但是早期是非标准的。 通过该属性可以允许使用实例对象直接访问原型
function Person() {}
// 神秘对象就是 Person.prototype
// 那么只有使用 构造函数 才可以访问它
var o = new Person();
// 以前不能直接使用 o 来访问神秘对象
// 现在有了 __proto__ 后
// o.__proto__ 也可以直接访问神秘对象
// 那么 o.__proto__ === Person.prototype
- 神秘对象中默认都有一个属性“constructor”,翻译为构造器,表示该原型是与神秘构造函数联系起来的
__proto__
有什么用?- 可以访问原型
- 由于在开发中除非特殊要求,不要使用实例去修改原型的成员,因此属性开发时使用较少
- 但是在调试过程中非常方便,可以轻易的访问原型进行查看成员
- 如果在早期的浏览器中使用实例需要访问原型如何处理?
- 可以使用实例对象访问构造器,然后使用构造器访问原型
var o = new Student(); o.constructor.prototype
- 可以使用实例对象访问构造器,然后使用构造器访问原型
- 如果给实例继承自原型的属性赋值
function Foo() {} Foo.prototype.name = 'test'; var o1 = new Foo(); var o2 = new Foo(); o1.name = '张三'; // 不是修改原型中的 name 而是自己增加了一个 name 属性 console.log( o1.name + ', ' + [o2.name );
2. 继承
- 最简单的继承就是 将别的对象的属性强加到 我的 身上, 那么我就有这个成员了.
- 利用原型也可以实现继承, 不需要在我的身上添加任何成员, 只要原型有了, 我就有了.
结论: 将属性, 方法等成员利用 混入的办法, 加到构造函数的原型上, 那么构造函数的实例就都具有该方法了.
2.1. 混合式继承复杂描述
- new DivTag() 用来 创建 div 对象
- appendTo 加到某元素上
- 扩展
- img
- p
- span
- a
- ...
- 无论方法怎么写, 方法是谁调用的, this 就是谁
2.2. 细节
使用点语法给原型添加成员与使用直接替换修改原型对象有什么区别?
- 原型指向发生了变化
- 构造函数所创建的对象所继承的原型不同
- 新增的对象的默认是没有constructor属性
注意:在使用替换的方式修改原型的时候,一般都会添加constructor属性
function Person() {}
Person.prototype = {
constructor: Person
};
// 拆解
function Person() {}
var o = {};
o.costructor = Person; // 属性中就存储着函数的地址
Person.prototype = o;
Person = 123;
2.3. 静态成员与实例成员的概念
这里提一下静态成员与实例成员的概念,也是从面相对象的编程语言中引入的,很多前端人员并不知道或者理解,我也就简单的提一下
- 静态成员表示的是静态方法和静态属性的概念,所谓的静态,就是由构造函数所提供的。
- 实例成员表示的是实例方法和实例属性,所谓的实例就是由构造函数所创建的对象所提供的。
一般工具型方法都由静态成员提供,一般与实例对象有关的方法由实例成员表示。
2.4. 属性搜索原则
- 属性搜索原则
- 所谓的属性搜索原则, 就是对象在访问属性与方法的时候, 首先在当前对象中查找
- 如果当前对象中存储在属性或方法, 停止查找, 直接使用该属性与方法
- 如果对象没有改成员, 那么再其原型对象中查找
- 如果原型对象含有该成员, 那么停止查找, 直接使用
- 如果原型还没有, 就到原型的原型中查找
- 如此往复, 直到直到 Object.prototype 还没有, 那么就返回 undefied.
- 如果是调用方法就包错, 该 xxxx 不是一个函数
**************************************************************************************************
原文转载自:http://www.zhimengzhe.com/Javascriptjiaocheng/94833.html