javascript
java
原型模式架构
function Person (name, age) { this.name = name; this.age = age; } Person.prototype.sayName = function () { return this.name; } Person.prototype.sayAge = function () { return this.age; } function Student (name, age, school) { this.name = name; this.age = age; this.school = school; } Student.prototype = new Person(); Student.prototype.saySchool = function () { return this.school; } let stu = new Student('zhang', 18, 'zust'); console.log(stu.getName()); // 'zhang'
以上的继承方式是比较好理解的,当访问Student实例的sayName()方法时,先遍历实例方法(无匹配),再搜索函数
原型对象Person实例(无匹配), 最后搜索Person.prototype对象上,获得sayName()方法。优化
借用构造函数this
function Person(name, age){ this.name = name; this.age = age; } Person.prototype.sayName = function () { return this.name; } Person.prototype.sayAge = function () { return this.age; } function Student(name, age, school){ Person.call(this, name, age); this.school = school; }
所谓的借用构造函数是借用父类的构造函数来设置本身的属性,进一步避免了代码的重复。spa
以上是单纯使用了借用构造函数实现的继承,能够看到在子类中经过重用父类的构造方法为子类设置属性,可是仅仅使用借用构造函数,子类将没法继承父类构造函数原型中的方法。prototype
组合式继承(原型模式与借用构造函数的组合)设计
function Person(name, age){ this.name = name; this.age = age; } Person.prototype.sayName = function () { return this.name; } Person.prototype.sayAge = function () { return this.age; } function Student(name, age, school) { Person.call(this, name, age); this.school = school; } Student.prototype = new Person();
以上的继承方式是原型模式和借用构造函数模式的组合方式,经过原型链的方式继承父类构造函数原型对象上的方法,使用借用构造函数重用父类构造函数中的代码。至关因而对于原型链继承模式的优化,将父类构造函数中的代码加以重用。对象
原型式继承
let sup = {name: 'zhang', age: 18}; let extend = function (obj) { function F () {}; F.prototype = obj; return new F(); } let sub = extend(sup); console.log(sub.name);
就以上的继承方式而言,我的感受与如下实现方式并无太大区别
let sup = {name: 'zhang', age: 18}; let sub = {}; Object.setPrototypeOf(sub, sup); console.log(sub.name);
在子类对象建立的过程当中,全部的父类变量将会被子类共享,尤为是引用类型的变量
const sup = {name: 'zhang', age: 18, arr: ['a', 'b', 'c']} const extend = function (obj) { function F(){}; F.prototype = obj; return new F(); } const a = extend(sup); const b = extend(sup); console.log(a.arr); // ['a', 'b', 'c'] b.arr.push('d'); console.log(a.arr); // ['a', 'b', 'c', 'd']
在原型上定义了一个引用类型的属性arr,而后经过继承建立两个对象,经过对象b访问arr属性时,因为对象b上并无arr属性,所以,会访问b的原型对象,也就是sup对象中的arr属性,这是全部子类对象共享父类对象中的属性的实质。
ES5中经过Object.create()方法实现原型式继承的标准API
寄生式继承
function createPerson (obj) { var clone = Object.create(obj); clone.getName = function () { return this.name; } return clone; } var person = {name: 'zhang', age: 18}; var p = createPerson(person); console.log(person.name); // 'zhang'
寄生式继承是将原型式继承以及增长实例方法这两个步骤封装成一个工厂函数,而后将生成的对象返回
代码仍是比较简单的,可是具体是干吗用的,emmmmmm...因此,再也不赘述
寄生组合式继承
function Person (name, age) { this.name = name; this.age = age; } Person.prototype.getName = function () { return this.name; } Person.prototype.getAge = function () { return this.age; } function Student (name, age, school) { Person.call(name, age); this.school = school; } Student.prototype = Object.create(Person.prototype); Student.prototype.getSchool = function () { return this.school; }