Javascript Instaunction中出现意外结果
Unexpected Result in Javascript Instanciation
我正试图使用javascript原型继承创建一个网格,但有一个问题我无法理解。在代码的某些地方,"new"关键字似乎不起作用。
这很难解释,所以代码在下面,我在要点中添加了注释。
<head>
<!-- this is the "parent class" -->
<script type='text/javascript'>
// constructor
function Container(CSSClassName) {
this.CSSClassName = CSSClassName;
this.build = ContainerBuild;
this.components = new Object();
this.addComponent = ContainerAddComponent;
this.getComponent = ContainerGetComponent;
}
/*
* methods
*/
function ContainerAddComponent(id, component) {
this.components[id] = component;
}
function ContainerGetComponent(id) {
return this.components[id];
}
function ContainerBuild() {
this.element = document.createElement('div');
this.element.className = this.CSSClassName;
for (var i in this.components) {
this.element.appendChild(this.getComponent(i).build());
}
return this.element;
}
</script>
<!-- Below I'm using prototype inheritance -->
<script type='text/javascript'>
Grid.prototype = new Container('grd');
function Grid() {
this.addComponent('body', new GridPart());
this.addComponent('foot', new GridPart());
}
GridPart.prototype = new Container('grd-part');
function GridPart() {
this.addComponent('comp', new Container('comp')); // this new keywork seems not to work.
/* ***** I tried this code, but the result was the same.
var comp = new Container('comp');
this.addComponent('comp', Object.create(comp)); // same unexpected result.
*/
}
window.onload = function() {
var grd = new Grid();
document.getElementById('grd').appendChild(grd.build());
grd.getComponent('body').element.style.background = 'red'; // ok!
grd.getComponent('body').getComponent('comp').element.style.background = 'gold'; // unexpected behavior
// Testing the objects.
console.log(grd.getComponent('body') === grd.getComponent('foot')); // false, ok!
console.log(grd.getComponent('body').getComponent('comp') === grd.getComponent('foot').getComponent('comp')); // true?? should be false!
}
</script>
<style type='text/css'>
.grd { border: 1px solid black }
.grd-part {
height: 25px;
padding: 12px;
border-bottom: 1px solid black;
}
.grd-part:last-child { border:none }
.grd-part .comp {
background: black;
height: 25px;
}
</style>
</head>
<body>
<div id='grd'></div>
</body>
如果您将此代码复制并传递到html文档中,您将看到问题。黄色矩形应该在红色矩形的内部!
有人知道会发生什么吗?
仔细查看您的代码,我怀疑问题在于Grid
和GridPart
的每个实例共享同一个components
对象。您可以通过查看原型链或检查grd.getComponent('body').components === grd.getComponent('foot').components
的结果来验证这一点。
不要做类似的事情
Grid.prototype = new Container('grd');
它将实例特定的属性添加到原型中,因此所有实例共享相同的实例特定的属性(如components
)。相反,使用Object.create
来建立继承:
Grid.prototype = Object.create(
Container.prototype,
{constructor: {value: Grid, configurable: true, writable: true}}
);
并在子构造函数内部调用父构造函数:
function Grid() {
Container.call(this, 'grd');
this.addComponent('body', new GridPart());
this.addComponent('foot', new GridPart());
}
应该在构造函数中设置特定于实例的属性,应该在原型上设置共享的属性。所以在你的情况下,你应该做Container.prototype. ContainerAddComponent = ContainerAddComponent;
。
另请参阅使用`Object.create`进行继承的好处
如果您已经能够使用ES6,请使用新的class
语法:
class Grid extends Container {
constructor() {
super('grd');
this.addComponent('body', new GridPart());
this.addComponent('foot', new GridPart());
}
}
问题不在于new
关键字不再工作,而在于以下行:GridPart.prototype = new Container('grd-part');
它的作用是使所有GridPart
对象都具有相同的this.components
对象。
因此,当您在GridPart
构造函数内调用this.addComponent
时,您可以用新的Container
对象覆盖索引'comp'
处的相同this.components
对象
我找到了一种方法来实现你在这里寻找的遗产并将此解决方案集成到您的代码中。
这是一个工作代码笔
- Node.js使用Series函数(模式?)实现流控制时出现意外结果
- Javascript:函数返回意外结果
- 意外结果,在 ASP.Net 中解析 JSON 对象的数组
- 按位或意外结果
- 来自 JavaScript 循环的意外结果
- 从 JavaScript 中的图像中读取像素数据会返回半透明像素的意外结果
- 在 JS 中短路空数组会产生意外结果:“[] ||真 == []'
- NodeJS中的Parse Json文件在Node中显示意外结果
- 基于给出意外结果的提示输入的逻辑
- JavaScript Regexp.test返回意外结果
- 键控产生意外结果.HTML5游戏
- Javascript do/while循环显示意外结果
- 来自 CSS 和 jQuery 的意外结果
- MongoDB mapReduce方法意外结果
- 具有意外结果的 Javascript 函数参数
- 在 JavaScript 中解析日期字符串的意外结果
- 从内部HTML更改为表单时获得意外结果,输入类型文本字段
- 在计算链逻辑表达式 JavaScript 时出现意外结果
- 意外结果 - 谷歌自动完成针对约克郡
- JavaScript unshift 参数返回意外结果