【发布时间】:2014-11-16 07:51:07
【问题描述】:
JavaScript 使用原型系统,它与类系统根本不同。这是我第一次认真接触这门语言。之前我也玩过,但这是我第一次用正确的面向对象、继承、多态等构建系统。
根据我的阅读,似乎有一些常用的方法可以在 Javascript 中进行成员函数继承。假设你有一个父 foo 如下
foo = function(){ this.one = 1; }
foo.prototype.func1 = function(){return this.one;}
MDN Introduction to JavaScript Inheritance 建议在子上下文中调用父方法的幼稚方法,如下所示。
bar = function(){ foo.call(this); }
bar.prototype = Object.create(foo.prototype);
bar.prototype.func1 = function(){ return this.one + foo.prototype.func1();}
这具有易于理解的优点,但如this Salsify Blog post 中所指出的那样会变得很麻烦。该博客文章概述了一种替代方法,其中在子原型中定义了 super 属性,并且每个成员函数的名称作为属性附加到该方法。但是,此方法依赖于方法的 caller 属性,文章指出该方法将很快被弃用。与其重复整个帖子,我相信总结的要点是这些
Object.defineProperty(bar.prototype, "super", {
get: function get() {
...
// methodName is set as a property on each method in an omitted code segment
methodName = get.caller.methodName;
...
Object.getPrototypeOf(this.prototype)[methodName]
}
}
也就是说你在你的原型的原型中找到了同名的方法。我想知道这是否可以以更简单的方式完成,而无需将方法名称作为参数附加,也无需 Function.caller。
foo.prototype.super = function(method) {
superMethod = Object.getPrototypeOf(this.constructor.prototype)[method];
return superMethod.call(this, Array.prototype.slice.call(arguments, 1));
}
bar.prototype.func1 = function(){ return this.one + super('func1'); }
我在上面做了一些假设,我想验证一些假设。
- new bar().constructor.prototype === Object.getPrototypeOf(new bar())
- 如果上述情况总是正确的,那么一个比另一个更可取吗?
- Parent 的成员函数将始终存在于子原型的原型中(假设在对象创建后两个原型都没有发生变化)
- Object.getPrototypeOf() 并不是博客所说的在 ES6 中添加的“访问超级方法的语言支持”
- 如果 Object.getPrototypeOf() 不是那种语言支持,那是什么?
在看到使用 this 的错误后,它在整个执行过程中不会改变并且总是引用子类的实例,我重新审视并认为我需要这样的东西
Grandfather = function(){};
Grandfather.prototype.function1 = function(){console.log("I am the Grandfather");};
Father = function(){Grandfather.apply(this);};
Father.prototype = Object.create(Grandfather.prototype);
Father.prototype.function1 = function f(){ f.super(); console.log("I am the Father");};
Father.prototype.function1.super = Grandfather.prototype.function1;
Child = function(){Father.apply(this);}
Child.prototype = Object.create(Father.prototype);
Child.prototype.function1 = function f(){ f.super(); console.log("I am the Child");};
Child.prototype.function1.super = Father.prototype.function1;
c = new Child();
c.function1();
// I am the Grandfather
// I am the Father
// I am the Child
那么问题就变成了,如何以某种自动方式为每个函数设置super 属性?
一种这样的方法如下所示,它的好处是在对象实例化后添加到原型的函数仍然可以调用superFunc,而设置super属性的方法如果稍后将函数添加到原型中,则在类扩展时不会设置此类属性。
这种方法的缺点是它只能在单线程环境中工作,并且它需要从公共基类继承的功能。它不是线程安全的,因为某些状态保存在实际上是函数的静态变量中。这对我的目的来说很好,因为浏览器仍然有单线程 JavaScript。所有类都继承自包含此方法的某个基类的要求并不是一个巨大的障碍(尤其是如果您做了“坏事”并将其插入到 Object 的原型中)。
Grandfather.prototype.superFunc = function f(funcName){
currentPrototype = Object.getPrototypeOf(f.startingPrototype || Object.getPrototypeOf(this));
f.startingPrototype = currentPrototype;
return currentPrototype[funcName]();
}
Child.prototype.function2 = function(){this.superFunc('function2'); console.log("Still in the Child");};
Father.prototype.function2 = function(){this.superFunc('function2'); console.log("Still in the Father");};
GrandFather.prototype.function2 = function(){console.log("Still in the Grandfather");};
c = new Child();
c.function2();
// Still in the Grandfather
// Still in the Father
// Still in the Child
【问题讨论】:
-
我猜你的意思是
bar.prototype.func1 = function () { ... }? ;)
标签: javascript inheritance polymorphism prototype