一、JavaScript 原型


原型的概念

  - 在JavaScript中,函数本身也是一个包含了方法和属性的对象

  - 每个函数中都有一个prototype属性,该属性引用的就是原型对象

  - 原型对象是保存共享属性值和共享方法的对象

wKioL1b5CI6jhMRxAADB-RWnjTM183.png


为对象扩展属性

  - 扩展单个对象的成员

wKiom1b5CDbxlBepAAFGv696ELk044.png

  - 扩展共享的属性值

wKioL1b5CPjjBRnzAAFTF0zqqvI566.png

  - 内存图描述

wKiom1b5CHzy_etdAADXv9VeM5M955.png


删除属性

  - 可以使用delete关键字删除对象的属性

wKioL1b5CVbjBMBcAAHNEJxHuIU887.png


自由属性与原型属性

  - 自有属性:通过对象的引用添加的属性;其它对象可能无此属性;即使有,也是彼此独立的属性

    emp1.job = 'Coder';

  - 原型属性:从原型对象中继承来的属性,一旦原型对象中属性值改变,所有继承自该原型的对象属性均改变

    Emp.prototype.dept = '研发部';

wKioL1b5CfyQYVAJAADY8iQsabY055.png

  - 自有属性重写原型属性

wKioL1b5CiSwG_D3AAFQAS2_PHQ031.png

  - 使用hasOwnProperty()检测对象是否具备指定自有属性:

wKiom1b5CdzxQVKZAACnh9DX-Yk323.png  - 使用in检测对象及其原型链中是否具备指定属性:

wKiom1b5CgmjoR-BAABiBWtLYa8929.png


对象的prototype属性

  - 自定义对象的prototype属性

      - new 创建的对象使用构造函数的 prototype 作为原型

      - 对象直接量的原型为 Object.prototype

  - 内置对象的prototype属性

      - Array 对象

      - Boolean 对象

      - Date 对象

      - Number 对象

      - String 对象


获取原型

  - 可通过两种方式获得对象的原型,进而设置共享属性

      - 使用构造函数的prototype属性

        比如: Emp.prototype

      - 使用专门的getPrototypeOf方法

        比如: Object.getPrototypeOf(obj)

  - 例如:为两个Emp对象指定相同的部门属性值

wKiom1b5CySxwJhRAAGNun8D_7E586.png


原型链

  - 其实,JavaScript中,原型对象本身也有原型

  - 构造函数的原型对象中也有一个__proto__属性

  - 原型对象中的__proto__属性,默认指向Object类型的原型对象----Object.prototype

  - Object.prototype是所有对象的原型。其中包含了所有对象所共有的属性和方法。比如:toString方法

  - 事实上,所有对象通过__proto__属性的引用关系,都可以直接或间接的引用到Object.prototype对象

  - 我们将使用对象的__proto__属性,形成的逐级引用的关系,称为原型链

  - 内存图描述

wKiom1b5DD3RpIsQAAD92a4HoSQ144.png


二、JavaScript 继承


继承的几种实现方式

  - JavaScript中主要通过原型实现继承

  - 通过原型实现继承主要有以下两种方式:

      - 修改构造函数的原型,为该构造函数创建的对象指定统一的父级对象

        语法: 构造函数.prototype = 父级对象;

     - 单独修改一个对象的原型,而不影响其他对象的原型

        语法: Object.setPrototypeOf(子类,父级对象);


如何实现继承

  - 修改构造函数的原型,为该构造函数创建的对象指定统一的父级对象

  - 注意:

      - 凡修改原型后,用此构造函数创建的新对象,均引用新原型

      - 修改原型之前,用此构造函数创建的对象,将无法使用新的原型,而依然使用旧的原型。因此被孤立

wKiom1b5DjixmKR_AAEa8rzRph4500.png

  - 也可以修改单个对象的原型,而不影响其他对象的原型

  - 仅影响当前对象的继承关系。不影响其它对象

wKioL1b5D0CyRV4DAAE5eqq9KCk807.png


检查对象的原型isPrototypeOf()

  - isPrototypeOf()方法用于判定一个prototype对象是否存在于另一个对象的原型链中。如果是,返回true,否则返回false

wKiom1b5DwvTTbuKAAFJVj8PPik621.png


只继承于原型

  - 出于效率考虑,尽可能地将可重用的属性和方法添加到原型中去。

      - 不要单独为继承关系创建新对象

      - 尽量减少运行时方法搜素,例如toString()方法

wKiom1b5D5PQjilpAAEt8Q4TbIs152.png


继承于扩展

  - JavaScript 是面向对象的语言,但与Java、C#等面向对象的语言不通,ECMAScript5中没有定义类(class)的语法,也不会通过类来创建对象

  - JavaScript中的继承基于prototype,而不是是基于类


 总结:本章内容主要介绍了 JavaScript 原型与继承