面向对象精要——继承

    xiaoxiao2022-07-14  148

    一、原型对象链和 Object.prototype

    JS 内建的继承方法被称为原型对象链(对象继承其原型对象,而原型对象继承它的原型对象,以此类推),又可称为对象继承。 当访问一个对象的属性时,JS引擎会执行一个搜索过程,如果在对象实例上发现该属性(自有属性),该属性值就会被使用,否则会搜索 [[Prototype]],如果仍然没有发现,则搜索该原型对象上的 [[Prototype]] 直到继承链末端。

    上几章博客中用到的多个方法都是定义在 Object.prototype 上,因此可以被其他对象继承:

    hasOwnProperty() 检查是否存在一个给定名字的自有属性;propertyIsEnumerable() 检查一个自有属性是否可枚举;isPrototypeOf() 检查一个对象是否是另一个对象的原型对象valueOf() 返回一个对象的值表达toString() 返回一个对象的字符串表达 最好不要修改 Object.prototype !!!(在 Object.prototype 上添加的方法和属性会出现在所有对象上!并且以 Object.prototype.property = anything 方式添加的属性是可枚举的,即会出现在每一个对象的 for-in 循环中)。

    二、对象继承

    对象继承是最简单的继承类型。唯一需要做的就是制定哪个对象时新对象的 [[Prototype]] 。 对象字面形式会隐式制定 Object.prototype 为其 [[Prototype]] ,也可以用 Object.create() 方法显式制定。 Object.create() 方法接受两个参数,1.需要被设置为新对象的 [[Prototype]] 的对象(可以为 null,即没有原型对象链),第二个可选参数是一个属性描述对象,格式和 Object.defineProperties() 中使用的一样。

    var book = { title: "This is a book" }; // 等同于下面代码 var book = Object.create(Object.Prototype, { title: { value: "This is a book", configurable: true, enumerable: true, writable: true } })

    三、构造函数继承

    构造函数也是对象。当新建一个函数的时候,该函数的 prototype 属性被自动设置为一个新的继承自 Object.prototype 的泛用对象,该对象有一个自有属性 constructor。事实上,JavaScript 引擎做了下面的事情:

    // 你定义一个函数 funcction Person(){ //do something } // JS 在引擎中: Person.prototype = Object.create(Object.prototype, { constructor: { value: Perosn, //指向自身 configurable: true, enumerable: true, writable: true } })

    四、构造函数窃取

    构造函数窃取的关键是 call() 和 apply() 方法。只需要在子类的构造函数中用 call() 或者 apply() 调用父类的构造函数,并将新创建的对象传进去即可。实际上,就是用自己的对象窃取父类的构造函数。

    function Rectangle(length, width) { this.length = length; this.width = width; } Rectangle.prototype.getArea = function() { returen this.length * this.width; } function Square(size) { //从 Rectangle 继承 Rectangle.call(this, size, size); // 添加新的属性或覆盖原有属性 } Square.prototype = Object.create(Rectangle.prototype, { constructor: { value: Square, //指向自身 configurable: true, enumerable: true, writable: true } }) Square.prototype.getArea = function() { //覆盖原有方法}; Square.prototype.toString = function() { //添加新方法};

    这种分两步走的过程在需要完成自定义类型之间的继承时比较有用。 一般来说,需要修改 prototype 来继承方法并用构造函数窃取来设置属性。由于这种做法模仿了那些基于类的语言的类继承,通常被称作伪类继承。

    五、访问父类方法

    可以通过直接访问父类原型对象的方式访问父类的方法,当这么做时,必须以 call() 或 apply() 执行父类方法并传入一个子类的对象。

    最新回复(0)