1

我创建了 3 个类如下

  1. Ext.mine.TextParent - 从 Textfield 继承
  2. Ext.mine.child.TextChildA - 从 Ext.mine.TextParent 继承
  3. Ext.mine.child.TextChildB - 从 Ext.mine.TextParent 继承

这样,Child A 和 Child B 类是兄弟姐妹,因为它们都继承自 Parent 类。

我已经向父类添加了一个新的配置属性作为 testConfig,默认值为{}.

initComponentChild A 类中,我为此 testConfig 分配了一个新键:值 -me.testConfig.childAKey='Child A Value';

现在,有一个表单使用了所有三个文本字段,并且在 textChildB 类型的 afterrender 中,我正在打印它的 testConfig 的值。

由于在 Child B 中未修改 testConfig 的值,因此,预计这应该打印空白对象(因为此 testConfig 的 parent 中的默认值是空白对象)。

但它实际上打印了 Child A 的值。

Child A 和 Child B 是兄弟姐妹,那么 Child A 的值怎么会传给 Child B?

有人可以指导一下这背后的原因吗?

下面是测试用例:

<html>
    <head>
        <title>Inheritance Test</title>
        <link rel='stylesheet' href='resources/extjs/resources/css/ext-all.css' />
        <script type='text/javascript' src='resources/extjs/ext-all-dev.js'></script>

        <script type='text/javascript'>

            //Defining the Parent below
            Ext.define('Ext.mine.TextParent', {
                extend: 'Ext.form.field.Text',
                alias: 'widget.textParent',
                testConfig:{}
            });

            //Defining the Child A below
            Ext.define('Ext.mine.child.TextChildA', {
                extend: 'Ext.mine.TextParent',
                alias: 'widget.textChildA',
                initComponent:function(){
                    var me  =   this;
                    me.testConfig.childAKey     =       'Child A Value';//Adding the key value to Child A
                    me.callParent();
                }
            });

            //Defining the Child B below
            Ext.define('Ext.mine.child.TextChildB', {
                extend: 'Ext.mine.TextParent',
                alias: 'widget.textChildB'
            });
        </script>

        <script type='text/javascript'>

            Ext.onReady(function(){
                Ext.create('Ext.form.Panel', {
                    title: 'Basic Form',
                    renderTo: Ext.getBody(),
                    width: 350,
                    url: 'save-form.php',
                    items: [{
                        xtype: 'textParent',//Creating field for Parent
                        fieldLabel: 'Text Parent',
                        flex:1
                    },{
                        xtype: 'textChildA',//Creating field for Child A
                        fieldLabel: 'Text Child A',
                        flex:1
                    },{
                        xtype: 'textChildB',//Creating field for Child B
                        fieldLabel: 'Text Child B',
                        flex:1,
                        listeners:{
                            afterrender:function(){
                                /*
                                    **Printing to console the value of testConfig for Child B
                                    **Instead of giving a blank object, it is giving the values of Child A - childKey:Child A Value
                                    **How the value from a sibling got associated with another one?
                                */
                                console.log(this.testConfig);
                            }
                        }
                    }]
                });
            });
        </script>

    </head>
    <body>
    </body>
</html>
4

2 回答 2

2

这里的问题是您试图继承一个对象(通过引用传递),它的工作方式与 Extjs 中的数字和字符串等值类型传递完全不同。如果您将示例更改为:

<script type='text/javascript'>

            //Defining the Parent below
            Ext.define('Ext.mine.TextParent', {
                extend: 'Ext.form.field.Text',
                alias: 'widget.textParent',
                testConfig:"cheese"
            });

            //Defining the Child A below
            Ext.define('Ext.mine.child.TextChildA', {
                extend: 'Ext.mine.TextParent',
                alias: 'widget.textChildA',
                constructor:function(){
                    var me  =   this;
                    me.testConfig     =       'Child A Value';//Adding the key value to Child A
                    me.callParent();
                }
            });

            //Defining the Child B below
            Ext.define('Ext.mine.child.TextChildB', {
                extend: 'Ext.mine.TextParent',
                alias: 'widget.textChildB'
            });
        </script>

它将正常工作,因为 testConfig 现在是按值传递的字符串类型。这背后的原因是因为 Extjs 不是为了在子类中创建新的对象实例而设计的,因为 javascript 中对象的深层副本非常复杂,甚至对于许多对象来说都是不可能的。这是因为一些深拷贝甚至可能没有逻辑意义(想想拷贝一个有循环引用的对象,拷贝函数怎么知道什么时候停止?)。由于某些深拷贝在对象上没有逻辑意义,因此没有通用的解决方案来进行深拷贝,因此如果您在继承树的最高级别创建一个对象,该对象实际上将是相同的实例每个子类的那个对象。

如果您注意到 extjs 核心代码,几乎 100% 的时间,所有配置选项都是按值类型传递的,这就是您应该遵循的模型。在您提供的示例中,当您可以将所有这些配置选项放在类级别时,创建配置选项对象在逻辑上没有必要,这在逻辑上意味着相同的事情。

我想如果您真的想简化我在这里要说的内容,可以归结为按引用传递与按值传递。如果您希望继承按应有的方式工作,则只能对配置选项使用按值传递。

于 2012-07-06T14:40:26.570 回答
2

在不创建 textChildA 自己的 testConfig“实例”的情况下,this.testConfig 正在更改父级的值,尝试在 textParent xtype 字段上添加相同的侦听器,您将看到该值包含 childAKey 和值。

Ext.define('Ext.mine.child.TextChildA', {
            extend: 'Ext.mine.TextParent',
            alias: 'widget.textChildA',
            initComponent:function(){
             Ext.apply(this,{
        testConfig:{'childAKey':"valuea"}
        });
        this.callParent(arguments); 
            }
        });
于 2012-07-06T08:21:34.193 回答