详解Javascript继承的实现(4)

通过代理的方式,就解决了在在实例方法内部通过this.base调用父类原型同名方法的问题。可是在实际情况中,每个实例方法都有可能需要调用父类的实例,那么每个实例方法都要添加同样的代码,显然这会增加很多麻烦,好在这部分的逻辑也是同样的,我们可以把它抽象一下,最后都放到模块化的内部去,这样就能简化代理的工作。

5)未考虑静态属性和静态方法。尽管静态成员是不需要继承的,但在有些场景下,我们还是需要静态成员,所以得考虑静态成员应该添加在哪里。

解决方式:由于js原生并不支持静态成员,所以只能借助一些公共的位置来处理。最佳的位置是添加到构造函数上:

- Hide code var copy = function (source) { var target = {}; for (var i in source) { if (source.hasOwnProperty(i)) { target[i] = source[i]; } } return target; }; function Employee() { this.init.apply(this, arguments); } //添加一个静态属性 Employee.idCounter = 1; //添加一个静态方法 Employee.getId = function () { return Employee.idCounter++; }; Employee.prototype = { constructor: Employee, init: function (name, salary) { this.name = name; this.salary = salary; //调用静态方法 this.id = Employee.getId(); }, getName: function () { return this.name; }, getSalary: function () { return this.salary; }, toString: function () { return this.name + '\'s salary is ' + this.getSalary() + '.'; } }; function Manager() { this.baseProto = Employee.prototype; this.init.apply(this, arguments); } Manager.prototype = copy(Employee.prototype); Manager.prototype.constructor = Manager; Manager.prototype.init = (function (name, func) { return function () { var old = this.base; this.base = this.baseProto[name]; var ret = func.apply(this, arguments); this.base = old; return ret; } })('init', function (name, salary, percentage) { this.base(name, salary); this.percentage = percentage; }); Manager.prototype.getSalary = function () { return this.salary + this.salary * this.percentage; }; var e = new Employee('jason', 5000); var m = new Manager('tom', 8000, 0.15); console.log(e.toString()); //jason's salary is 5000. console.log(m.toString()); //tom's salary is 9200. console.log(m instanceof Manager); //true console.log(m instanceof Employee); //false console.log(e instanceof Employee); //true console.log(e instanceof Manager); //false console.log(m.id); //2 console.log(e.id); //1

最后的两行输出了正确的实例id,而这个id是通过Employee类的静态方法生成的。在java的面向对象编程中,子类跟父类都可以定义静态成员,在调用的时候还存在覆盖的问题,在js里面,因为受语言的限制,自定义的静态成员不可能实现全面的面向对象功能,就像上面这种,能够给类提供一些公共的属性和公共方法,就已经足够了。

2. 期望的调用方式

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wgydxg.html