为什么在使用ExtJS配置功能时定义setName()时getName()返回undefined?

时间:2016-03-01 08:21:30

标签: javascript extjs

请参阅以下使用ExtJS配置功能的HTML + JS + ExtJS代码。

<!DOCTYPE html>
<html>
<head>
<title>Ext-JS config missing setAge() problem</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/extjs/6.0.0/ext-all.js"></script>
<script>
Ext.define('Student', {
    config: {
        name: 'anonymous',
        age: 0
    },

    constructor: function (config) {
        this.initConfig(config);
    },

    putName: function (name) {
        this.config.name = name
    }

});

var studentObj = Ext.create('Student', {name: 'Alice', age: 12})
console.log('before putName: methods:  ' + studentObj.getName() + ', ' + studentObj.getAge());
console.log('before putName: internal: ' + studentObj._name + ', ' + studentObj._age);
console.log('before putName: config:   ' + studentObj.config.name + ', ' + studentObj.config.age);
studentObj.putName('Bob');
console.log('after putName:  methods:  ' + studentObj.getName() + ', ' + studentObj.getAge());
console.log('after putName:  internal: ' + studentObj._name + ', ' + studentObj._age);
console.log('after putName:  config:   ' + studentObj.config.name + ', ' + studentObj.config.age);
</script>
</head>
<body>
</body>
</html>

这提供了预期的输出。

"before putName: methods:  Alice, 12"
"before putName: internal: Alice, 12"
"before putName: config:   Alice, 12"
"after putName:  methods:  Alice, 12"
"after putName:  internal: Alice, 12"
"after putName:  config:   Bob, 12"

但如果我在上面的代码中将putName替换为setName,那么我会得到 以下输出。

"before setName: methods:  undefined, 12"
"before setName: internal: undefined, 12"
"before setName: config:   Alice, 12"
"after setName:  methods:  undefined, 12"
"after setName:  internal: undefined, 12"
"after setName:  config:   Bob, 12"

在这种情况下,为什么内部_name变量设置为undefined?为什么getName()来电回复undefined

我知道我不应该定义我的setName()方法 而是定义applyName()方法。但我想了解 这是怎么回事。

在我看来,当我定义setName()方法时,它会变得混乱 关于如何在ExtJS中维护配置的内部变量。

您能否准确描述在这种情况下内部_name变量未定义的原因?

2 个答案:

答案 0 :(得分:1)

config成员自动生成的getter和setter实现实际上是从父类继承的 - 如果覆盖未在API中标记为模板函数的方法,则需要调用“超级“方法,如果您希望保留原始行为 - 您可以使用callParent来实现此目的,例如:

Ext.define('MyClass', {

    config: {
        foo: 'bar'
    },

    constructor: function(config){
        this.initConfig(config);
    },

    setFoo: function(value){
        // custom setter code
        this.callParent(arguments);
    }
});

请注意,如果您选择手动操作各个参数,callParent总是需要一个数组 - 否则您可以简单地按原样传递函数arguments。也就是说,通常你不需要覆盖setter,文档说明出于优化的原因,你不应该调用任何会触发布局的代码。

另一种选择是挂钩update模板方法。与getter和setter一样,每个config成员也会获得一个“update”前缀方法,默认情况下该方法指向Ext.emptyFn。在设置了值之后调用此方法,并且不会干扰超类,例如

Ext.define('MyClass', {

    config: {
        foo: 'bar'
    },

    // ...

    updateFoo: function(value){
        // do something
    }
});

» Fiddle

答案 1 :(得分:0)

getter和setter方法的默认实现使用属性def palindrome(s): return s == s[::-1] 来存储值,这就是它无法工作的原因。

如果您要覆盖_<name>,则需要设置setName

this._name

演示:Fiddle

但是如果一个更合适的方法,如果你只是想在设置属性值时做一些自定义操作,那就是使用像Ext.define('Student', { config: { name: 'anonymous', age: 0 }, constructor: function(config) { this.initConfig(config); }, setName: function(name) { this._name = name } }); 这样的方法

apply<property>

演示:Fiddle