Luk*_*uke 12 javascript oop inheritance prototype
必须有一些我不了解JS对象模型的东西.
从这些资源:
我已经收集了我认为或者认为是对象模型的准确心理表示的东西.这里是:
所有对象都有一个属性,文档称之为[[Prototype]].[[Prototype]]可以被认为是对象父级的引用.更精确地:
对[parent's]原型对象的引用将复制到
[[Prototype]]新实例的内部属性中.(来源1)
您可以访问[[Prototype]]子项的属性.Object.getPrototypeOf(child)此处返回的值将是父项原型的引用(不是其内部[[Prototype]]属性,而是其实际原型)
obj.prototype与对象的内部[[Prototype]]属性不同.它的作用类似于用于创建此精确对象的实例的蓝图,而其[[Prototype]]属性指向用于生成其父实例的蓝图.
Parent.prototype === Object.getPrototypeOf(child); //true详细说明:
如果向child.prototype函数添加函数,则可以使用该函数child及其任何子函数.
如果你添加一个函数parent.prototype,相当于添加一个函数Object.getPrototypeOf(child),那么该函数将可用于parent它的所有子函数,包括它的child所有子函数siblings.
您可以使用Object.create()任何[[Protoype]]属性创建新对象.因此,您可以将其用作实现继承的方法.有关示例,请参见源2.
考虑到这一点,我希望得到一个自己的实例.我的计划是创建一个父类'class',然后创建一个继承自它的子类'class'.
我希望子类实现一个方法,该方法从父方法重载方法.需要注意的是,我希望孩子的方法版本调用父方法的版本,然后做一些额外的事情.
以下是我提出的问题,请参阅下面的相关问题:
var Parent = function() {};
Parent.prototype.myF = function() {
console.log('derp');
};
function Child() {
Parent.call(this);
};
//make [[prototype]] of Child be a ref to Parent.prototype
Child.prototype = Object.create(Parent.prototype);
//need to explicitly set the constructor
Child.prototype.constructor = Child;
Child.prototype.myF = function() {
Object.getPrototypeOf(this).myF();
console.log("did I derp??");
};
childInstance = new Child();
childInstance.myF();Run Code Online (Sandbox Code Playgroud)
似乎是当我尝试重载时Parent.myF(),当我重载它时,我实际上是在同时修改原始函数.这似乎是这种情况,因为记录的结果是:
'derp'
'did I derp??'
'did I derp??'
Run Code Online (Sandbox Code Playgroud)
据推测,第一次出现'did I derp??'是来自父母的功能的修改版本,我不是故意要做的,那么第二个版本来自孩子的功能.
任何人都可以详细说明为什么会这样吗?
很好的问题,需要进行一些测试和研究才能找到它.
我稍微改变了你的代码,以找出在下列时调用的函数:
var Parent = function() {};
Parent.prototype.myF = function() {
console.log('derp');
};
function Child() {
Parent.call(this);
this.name = 'Test'; // this is a new test property
};
//make [[prototype]] of Child be a ref to Parent.prototype
Child.prototype = Object.create(Parent.prototype);
//need to explicitly set the constructor
Child.prototype.constructor = Child;
Child.prototype.myF = function() {
console.log(this); // here I want to find out the context, because you use it in the next line
Object.getPrototypeOf(this).myF();
console.log("did I derp??");
};
childInstance = new Child();
childInstance.myF();
Run Code Online (Sandbox Code Playgroud)
您可以查看JSFiddle并亲自尝试:http://jsfiddle.net/Lpxq78bs/
代码中的关键行是:
Child.prototype.myF = function() {
Object.getPrototypeOf(this).myF(); // this one
console.log("did I derp??");
};
Run Code Online (Sandbox Code Playgroud)
在做了一个console.log(this);找出this引用的内容之后,我看到它在第一个和第二个输出之间发生了变化did I derp??.
我得到以下输出:
Object { name: "Test" }
Object { constructor: Child(), myF: window.onload/Child.prototype.myF() }
"derp"
"did I derp??"
"did I derp??"
Run Code Online (Sandbox Code Playgroud)
因为我在Child构造函数中添加了一个'name'属性,所以只有当我查看一个实例而Child不是它的实例时它才会出现.prototype.
所以输出的第一行意味着当前的this上下文确实是childInstance.但第二个既不是childInstance,也不是Parent.prototype:
myFof childInstance):this指的是childInstance.Object.getPrototypeOf(this).myF();然后寻找[[Prototype]]的childInstance,这是Child.prototype,而不是Parent.prototype.输出:'我有没有解释?'Call (myFof Child.prototype):this指的Child.prototype是childInstances[[Prototype]]属性.所以第二次调用Object.getPrototypeOf(this).myF();最终返回Parent.prototype(有点).输出:'我有没有解释?'
调用(myF由Parent.prototype实例创建Object.create):最后,myF调用父元素.输出:'derp'
由于您console.log("did I derp??")在myF函数调用之后,输出的顺序相反.下图说明了如何遍历代码:

因此,您对Object.getPrototypeOf(this).myF();所指的内容的假设是错误的.
通过@LukeP:https://jsfiddle.net/Lpxq78bs/28/
为了避免这种混淆,并且由于您正在使用经典的继承模式,您可以查看ES6类.以下是您要做的事情的一个粗略示例:
class Parent {
constructor() {
}
myF() {
console.log('derp');
}
}
class Child extends Parent {
constructor() {
super();
}
myF() {
super.myF();
console.log("did I derp??");
}
}
var childInstance = new Child();
childInstance.myF();
Run Code Online (Sandbox Code Playgroud)
我希望这有助于理解会发生什么.
您的代码按预期工作,您获得的输出是因为Object.getPrototypeOf并且可以解释
第1步:当你调用childInstance.myF();它然后它转到下面的代码,其中this引用childInstance本身
Child.prototype.myF = function() {
Object.getPrototypeOf(this).myF();
console.log("did I derp??");
};
Run Code Online (Sandbox Code Playgroud)
然后Object.getPrototypeOf返回childInstance.[[Prototype]]哪个是Child.prototype再次调用myF方法(在执行方法后留下第二行打印)但下次this将引用childInstance.[[Prototype]].
第2步:在此调用this指向childInstance.[[Prototype]](或Child.prototype对象本身)
Child.prototype.myF = function() {
Object.getPrototypeOf(this).myF();
console.log("did I derp??");
};
Run Code Online (Sandbox Code Playgroud)
现在Object.getPrototypeOf返回childInstance.[[Prototype]].[[Prototype]](这是Child.prototype.[[Prototype]]),它Parent.prototype再次调用myF方法,但这次myF方法将打印derp,因为Parent.prototype正在调用myF方法.在那之后,第二行将打印我derp.
步骤3:然后该功能返回到步骤1以执行第二行,再次打印我的derp
| 归档时间: |
|
| 查看次数: |
5219 次 |
| 最近记录: |