面向对象的原型与继承

1. 为什么需要原型
构造器创建对象的时候, 实际上会有成员重复
如果使用 构造器 this.方法名 = function .... 方式创建对象. 那么每一个对象
对应的方法就会重复.

解决办法就是让这个方法( 函数 )共享
-> 将函数写到外面, 那么 Person 在初始化对象的时候就不会再创建一个函数了.
只需要将 外面的函数引用 交给对象即可.

缺点: 一个对象可能有 n 多方法. 如果将所有的东西 都放到外面, 与其他库
冲突的几率就会变大. 所以不宜采取该方法.
-> 将所有的方法( 函数 )都绑定到一个对象中.

-> js 原生就支持解决该问题的办法
每一个函数都有 一个属性 prototype
该属性指向一对象. 每一个函数的该对象都是存在.
(重点) 每一个由该函数作为构造器创建的对象, 都会默认连接到该对象上.
如果访问对象的方法, 而对象中没有定义, 就会在这个 构造函数.prototype
表示的对象中去找.

-> prototype 就是原型之意

2. 针对构造函数而言, 原型就是 构造函数的 prototype 属性, 常常将其称为 原型属性.
针对实例对象而言, 原型就是 实例对象的 原型对象.

例:
function Person () {} // 有了构造函数, 和 原型
var p = new Person(); // 有了实例

3. 一般如何使用原型对象
-> 简单的说就是将共享的方法放到原型中, 而独有数据与行为放在当前对象里
-> 例:
Person( name, age, gender, sayHello, eat, run )
-> 直接给原型对象添加成员
-> 直接替换原型对象( 注意: 手动的添加 constructor 属性, 表示对应的构造函数 )

4. __proto__
和 prototype 是否存在关系

早期浏览器是不支持 __proto__
火狐率先使用该属性, 但是是非标准
基本现在的新浏览器都支持该属性

-> 访问
使用构造函数, 就使用 prototype 属性访问原型
使用实例对象, 就使用 非标准的 __proto__ 属性访问原型

5. 继承
-> 什么是继承
自己没有, 别人有, 拿过来自己用, 就好像自己的一样.
-> 原型与实例对象
在 js 中, 方法定义在原型对象中, 而属性定义在实例对象中
调用方法的时候, 实例对象本身是没有该成员的, 但是依旧可以调用
该方法, 好像这个方法就是该实例对象的一样. 因此, 我们称该实例对象
继承自 原型对象
-> 任何一个实例, 都是继承自其原型对象的. 即原型式继承.

6. 为什么需要继承
-> 编程的发展
复用( 重复使用 )

div 标签对象 nodeName, nodeType, nodeName, ...
appendChild, insertBefore, getElementsByTagName, ...

a 标签对象

baseElement

-> js 运行效率
共享特性
复用

7. 传统的编程语言的面向对象操作
-> 对象: 是具有方法和属性的逻辑单元
在 js 函数是一个特殊的数据类型( 函数在 js 是一等公民 )
js 对象就是键值对, 值如果是数据, 那么键值就构成属性
如果值是函数, 那么就构成方法.

-> 创建方式
类 -> 实例化 -> 对象( 实例 )

class Person {
public string name;
public int age;
public string gender;

public void sayHello () {
// ...
}
}
// 类, 用来描述对象的结构, 它就是一个模板

Person p = new Person(); // 利用模板创建对象

// 访问属性
p.name
// 调用方法
p.sayHello();

传统的面向对象编程语言, 重点需要一个"模板", 即 类( class )

-> 传统的继承
传统的继承是模板的继承.

class Student : Person {
}

Student s = new Student();
// 注意此时 s 就可以调用 sayHello 方法
// 可以使用 name, age, 和 gender 属性了

8. 相关概念
类 class 模板 构造函数, 类名就是构造函数名
子类 subclass 派生的模板 原型设置为指定对象的构造函数
实例 instance 某个类的对象 ...
实例成员(实例方法, 实例属性)
静态成员
静态方法 ... 直接绑定在函数上的方法
静态属性 ... 直接绑定在函数上的属性

// js 代码
function Person () {
this.name = ‘黄帝‘;
this.age = 0;
this.gender = ‘男‘;
}

// 不叫子类, 只是一个 Student 类
function Student() {
}

// 继承派生 成为子类
Student.prototype = new Person();

// 即完成派生
var s = new Student();
s.name // OK

9. 属性访问原则( 重点 )
1) 对象在调用方法或访问属性的时候, 首先在当前对象中查询. 如果有该成员使用并停止查找.
2) 如果没有该成员就在其原型对象中查找. 如果有该成员即使用, 并停止查找.
3) 如果还没有就到 该对象的 原型对象 的 原型对象中查找.
...
4) 最后会查到 Object.prototype 上. 如果还没有即 返回 undefined.

10. 如果修改原型对象中的属性值会怎样
给当前对象的原型提供的属性赋值, 实际上是给当前对象添加了该属性的新成员
并不会修改运行对象中的成员.

11. 混入( mix )

var o1 = { name: ‘张三‘ };
var o2 = { age: 19 };
-----------
o2.name = o1.name
利用这个简单的赋值, 就可以将一个对象中的成员加到另一个对象中

混入使得 o2 具有了 age 和 o1 中的 name. 即将 o1 混入到 o2 中

混入也是一种继承的方式

12. 如何使用代码实现混入

// 考虑需要执行, 写函数即可
// 由于将 一个 对象混入到 另一个对象. 所以有两个参数
function __mix__ ( obj, obj1 ) {
// 如何获得 obj1 中的所有成员?
for ( var k in obj1 ) {
obj[ k ] = obj1[ k ];
}
}

13. 原型式继承
-> 写一个构造函数, 如果需要将其实例继承自某个特定的对象 o. 那么
只需要设置该构造函数的 prototype 属性为 o 即可

function Person {}

var o = { ... }

Person.prototype = o; // 继承

14. 混合式继承
-> 混合就是将多个对象的各个功能混合到一起, 加到构造函数的原型对象上.
那么该构造函数创建的实例 就继承自多个对象了.

15. 对象 -> 父对象 -> 父对象的父对象 -> ... -> 原对象 -> ....
链式结构( 原型链 )

由于链越深, 属性搜索越需要性能. 所以一般少用深层次的链式结构继承
一般使用时, 链结构只有 3 级. 一般都是使用混入, 在原型上加成员

16. ES5 中 的 Object.create
继承的最经典结构
function Animal() {}

function Person() {}

Person.prototype = new Animal();

语法:
新对象 Object.create( 原对象 );

时间: 2024-12-14 18:48:52

面向对象的原型与继承的相关文章

JS面向对象,原型,继承

ECMAScript有两种开发模式:1.函数式(过程化),2.面向对象(OOP).面向对象的语言有一个标志,那就是类的概念,而通过类可以创建任意多个具有相同属性和方法的对象.但是,ECMAScript没有类的概念,因此它的对象也与基于类的语言中的对象有所不同.var box = new Object();box.name = 'Lee';box.age = 100;box.run = function(){ return this.name + this.age + '运行中...'; //th

js面向对象编程/原型链/继承 —— javascript

目录 js面向对象编程 js原型链 共享方法 原型继承 js面向对象编程 js面向对象编程不同于 java 的类和对象 JavaScript 不区分类和实例的概念,而是通过原型(prototype)来实现面向对象编程. js声明的构造函数,类似于普通函数的声明,但又不同, 实例对象时,如果不写new,就是一个普通函数,它返回 undefined. 但是,如果写了new,它就变成了一个构造函数,它绑定的 this 指向新创建的对象, 并默认返回 this,也就是说,不需要在最后写return th

JavaScript 随笔2 面向对象 原型链 继承

第六章 面向对象的程序设计 1.创建对象的几种方式 A)工厂模式 function CreatObj(name,sex,age){ this.name=name; this.sex=sex; this.age=age; } 缺点:虽然可以批量创建对象,却不能知道对象的类型 只知道他是Object类型: B)构造函数 function Person(name,sex){ this.name=name; this.sex=sex; this.sayName=function(){ alert(thi

面向对象之笔记二——————原型与继承

原型与继承 原型 为什么需要原型? 构造器创建对象的时候, 实际上会有成员重复 如果使用 构造器 this.方法名 = function .... 方式创建对象. 那么每一个对象对应的方法就会重复 function Person( name ) { this.name = name; this.sayHello = function() { console.log( '你好,我是 ' + this.name ); }; } var p1 = new Person( 'Hello' ); var

一步步学习javascript基础篇(5):面向对象设计之对象继承(原型链继承)

上一篇介绍了对象创建的几种基本方式,今天我们看分析下对象的继承. 一.原型链继承 1.通过设置prototype指向“父类”的实例来实现继承. function Obj1() { this.name1 = "张三"; } function Obj2() { } Obj2.prototype = new Obj1(); var t2 = new Obj2(); alert(t2.name1); 这里有个明显的缺点就是:(如果父类的属性是引用类型,那么我们在对象实例修改属性的时候会把原型中

JS面向对象与原型

面向对象与原型一.创建对象 1.基本方法 1 var box = new Object(); //创建对象 2 box.name = 'Lee'; //添加属性 3 box.age = 100; 4 box.run = function(){ //添加方法 5 return this.name + this.age + '运行中...'; //this表示当前作用于下的对象 6 }; 7 8 alert(box.run()); 9 10 alert(this.anme); //这里的this代表

js面向对象及原型(javaScript高级程序设计第3版)

一.创建对象 创建一个对象,然后给这个对象新建属性和方法. var box = new Object(); //创建一个Object对象 box.name = 'Lee'; //创建一个name属性并赋值 box.age = 100; //创建一个age属性并赋值 box.run = function () { //创建一个run()方法并返回值 return this.name + this.age + '运行中...'; }; alert(box.run()); //输出属性和方法的值 上面

JavaScript之基础-16 JavaScript 原型与继承

一.JavaScript 原型 原型的概念 - 在JavaScript中,函数本身也是一个包含了方法和属性的对象 - 每个函数中都有一个prototype属性,该属性引用的就是原型对象 - 原型对象是保存共享属性值和共享方法的对象 为对象扩展属性 - 扩展单个对象的成员 - 扩展共享的属性值 - 内存图描述 删除属性 - 可以使用delete关键字删除对象的属性 自由属性与原型属性 - 自有属性:通过对象的引用添加的属性;其它对象可能无此属性;即使有,也是彼此独立的属性 emp1.job = '

面向对象与原型5---继承

1.用原型链实现继承 最普通 但是没有办法传参,没有办法共享方法 继承是面向对象中一个比较核心的概念.其他正统面向对象语言都会用两种方式实现继承:一个是接口实现,一个是继承.而 ECMAScript 只支持继承,不支持接口实现,而实现继承的方式依靠原型链完成. 原型链是由原型加对象构造之间的关系结构形成的像一个链条一样 在 JavaScript 里,被继承的函数称为超类型(父类,基类也行,其他语言叫法),继承的函数称为子类型(子类,派生类). //继承,通过原型链实现 function Box(