这个问题的主要信息来源是James Shore在以下地址提供的教程:http://www.objectplayground.com/ ... ...多次重看视频后,我带走了足够的精力来整理一系列课程,但我仍然无法真正了解幕后情况。 James解释经典模型继承的方式(我认为是指使用类来组织数据,而不是使用较旧的处理方式)是这样的:
评估任何函数定义语句时,都会创建两个对象。创建的第一个对象是构造函数(出于这个问题的目的,我将其称为cStruct
),并且可以通过其称为原型的成员进行识别,据他所说,原型和许多其他来源都指向 Function对象原型或Function.prototype
。但是然后变得很奇怪,因为创建的第二个对象是原型(或proType
),而原型又可以由其自己的称为构造函数的成员(指向cStruct
)进行标识,并拥有自己的原型成员指向 Object Object Prototype ,或者仅指向Object.prototype
。好的,足够简单(哈!),但随后他(和其他消息来源)继续;当一个类扩展到另一个类时,我们放弃扩展的(较新/较窄的)类proType
,而将其替换为实际上指向扩展的(原始/较旧/较宽的)类proType
的一个新类。
好的,因此,根据此描述,我试图仅使用具有null
原型作为构建基块的对象来重新创建继承模型,以便我可以在控制台中检查结果而不必仔细检查所有内容。还不明白基本上,我正在寻找继承的烟枪;证明这不仅是魔术,。看起来应该有可能,但是一旦逻辑以代码形式建立,就不会令人惊讶地无法传递继承的属性。您会明白我的意思。
常规练习-三个课程
function ExampleClass_A ( ) { }
function ExampleClass_B ( ) { }
function ExampleClass_C ( ) { }
文学解释
注意 这些是字面模拟的类。他们证明了我理解编写班级时幕后发生的事情。请注意,在我们稍后开始扩展类之前,c
变量几乎可以被忽略
a = Object.create( null );
b = Object.create( null );
c = Object.create( null ); // this represents the Object Prototype
cStruct_A = a;
proType_A = b;
proType_A.prototype = c;
cStruct_A.prototype = b;
proType_A.constructor = a;
delete a; delete b;
a = Object.create( null );
b = Object.create( null );
cStruct_B = a;
proType_B = b;
proType_B.prototype = c;
cStruct_B.prototype = b;
proType_B.constructor = a;
delete a; delete b;
a = Object.create( null );
b = Object.create( null );
cStruct_C = a;
proType_C = b;
proType_C.prototype = c;
cStruct_C.prototype = b;
proType_C.constructor = a;
delete a; delete b; delete c;
常用练习-线性类扩展
编辑 @Vog,我不确定对象的组成是什么,但是如果我不得不猜测这是线性扩展的另一种类扩展/实例化模式我在这个问题中写过一篇文章,其中我必须假设某种形式的继承无论如何都在发生。当然,我当然不准备将一种模式接受到另一种模式,因为我只是想了解一开始使这些模式可行的机制是如何起作用的。
ExampleClass_B.prototype = Object.create( ExampleClass_A.prototype );
ExampleClass_C.prototype = Object.create( ExampleClass_B.prototype );
文学解释
注意 如果我正确理解这一点,则继承要工作于主类之后的所有子类的proType
或彼此必须指向proType
其父类。因此,这里我们取消了三个类proType
中的两个,而将它们替换为指向适当的“后续”位置的类。
a = Object.create( null );
a.prototype = proType_A;
a.constructor = cStruct_B;
alt_proType_B = a;
cStruct_B.prototype = alt_proType_B;
delete proType_B;
delete a;
a = Object.create( null );
a.prototype = alt_proType_B;
a.constructor = cStruct_C;
alt_proType_C = a;
cStruct_C.prototype = alt_proType_C;
delete proType_C;
delete a;
常用练习-实例化
var exampleInstance_W = new ExampleClass_A(); //
var exampleInstance_R = new ExampleClass_B(); // randomly chosen names
var exampleInstance_T = new ExampleClass_C(); //
文学解释
a = Object.create( null );
a.prototype = proType_A;
nstance_W = a;
delete a;
a = Object.create( null );
a.prototype = alt_proType_B;
nstance_R = a;
delete a;
a = Object.create( null );
a.prototype = alt_proType_C;
nstance_T = a;
delete a;
常用练习-作业
ExampleClass_A.prototype.prop_a = "test a,";
ExampleClass_B.prototype.prop_b = "test b,";
ExampleClass_C.prototype.prop_c = "test c";
文学解释
注意 在这里我开始看到可能有问题
cStruct_A.prototype.prop_a = "test a,";
cStruct_B.prototype.prop_b = "test b,";
cStruct_C.prototype.prop_c = "test c";
// proType_A.prop_a = "test a"; //
// proType_B.prop_b = "test b"; // Kind of cool that this works
// proType_C.prop_c = "test c"; //
测试 ---常规做法
console.log(
exampleInstance_T.prop_a, // successful log
exampleInstance_T.prop_b, // successful log
exampleInstance_T.prop_c, // successful log
);
测试-文字解释
注意 现在将所有努力推向高潮。这些日志产生不同的结果令人困惑...
console.log(
nstance_T.prototype.prop_a, // unsuccessful log
nstance_T.prototype.prop_b, // unsuccessful log
nstance_T.prototype.prop_c, // successful log
);
console.log(
nstance_R.prototype.prop_a, // unsuccessful log
nstance_R.prototype.prop_b, // successful log
nstance_R.prototype.prop_c, // unsuccessful log
);
console.log(
nstance_W.prototype.prop_a, // successful log
nstance_W.prototype.prop_b, // unsuccessful log
nstance_W.prototype.prop_c, // unsuccessful log
);
console.log( // Kind of lame that this does't work
nstance_W.prop_a, //
nstance_R.prop_b, // I mean it makes sense when you follow the
nstance_T.prop_c, // established logic, but at the same time
); // it means that I'm missing something.
换句话说,如果每个 文学解释 代码块都只是在模仿上面的 Common Practice 代码块它为何nstance_t
不能访问.prop_a
和.prop_b
?与我的配置有关吗?我错过了重点吗?帮帮我。预先感谢。
答案 0 :(得分:1)
nstance_t
为什么不能访问.prop_a
和.prop_b
?与我的配置有关吗?我错过了重点吗?
似乎您期望.prototype
建立一个对象的继承链。它不是,它只是一个普通属性,分配它不会带来任何神奇的作用。
对对象(或null
)的实际引用是内部的,通常表示为 [[prototype]] 。您需要调用Object.getPrototypeOf(…)
才能访问它。要进行设置,可以使用Object.create
,Object.setPrototypeOf
或new
。
我相信这是您正在寻找的代码:
常用练习-ES6
class A {}
class B extends B {}
const instance = new B
常规练习-ES5
function A() {}
function B() {}
B.prototype = Object.create(A.prototype)
B.prototype.constructor = B
const instance = new B
文字解释(关于对象关系,忽略构造函数调用)
A_prototype = Object.create(Object.prototype)
A_constructor = new Function(…)
A_prototype.constructor = A_constructor
A_constructor.prototype = A_prototype
B_prototype = Object.create(A_constructor.prototype)
B_constructor = new Function(…)
B_prototype.constructor = B_constructor
B_constructor.prototype = B_prototype
instance = Object.create(B_constructor.prototype)
您现在可以在A_prototype
/ A_constructor.prototype
和B_prototype
/ B_constructor.prototype
上分配属性,并在instance
上继承它们。
答案 1 :(得分:0)
尽管我赞扬您对构建这种东西的好奇心,但请注意继承是一种众所周知的反模式。 (经典)面向对象程序设计的其他方面在“今天”受到质疑(从某种意义上说:最近十年,如果不是更长的话)。但是,继承是几乎所有有经验的程序员都会建议的东西。
这里的口头禅是在可能的情况下始终使用对象组合而不是继承(我认为实际上总是这样)。
这与在JavaScript之上对适当的类型系统进行建模不同。或者,建模解构和结构模式匹配。这些玩具也可能永远不会在生产中使用,但是至少您会构建一些东西,以后再实际使用“真实”。
请注意,继承在任何语言中都没有实现其承诺,例如C ++,Python,Ruby,PHP,Smalltalk,Java等。即使在GoF书(https://en.wikipedia.org/wiki/Design_Patterns)中,您也可以找到早期的提示,这对大多数OO程序员来说都是一本圣经。在那里,尽管没有直接批评继承,但您可以将模式的整个小节总结为“如何用易于维护的对象组成结构替换难以维护的继承结构”。