【问题标题】:JavaScript Dynamic variablesJavaScript 动态变量
【发布时间】:2014-02-20 11:44:48
【问题描述】:

通过这个脚本,我在运行时向对象添加变量:

function MyDocument(someDocument)
{
if(!(someDocument instanceof KnownDocumentClass))
    throw "Object must be an instance of KnownDocumentClass: " + someDocument;
this.Document = someDocument;
this.Fields = {};
this.updateValues = function()
    {
        for (var _it = this.Document.iterator(); _it.hasNext();) 
        {
            var _property = _it.next(); 
            try 
            {
                this[_property.getQualifiedName()] = _property.getContent();
            }
            catch(err)
            {
                log("Error :"+err);
            }
        }
    }
this.updateValues();

}

所以,例如,我可以使用

var mydoc = new MyDocument(knownjavadoc);
log(mydoc.Creator) // Shows the original content.

此内容可能有多种类型(一些是int,一些是Strings 和许多其他自定义Java 类)。所以log(mydoc.SomeProperty) 可能会返回:

PropertyObjectImpl[id=abc123, data=Some Data, type=Node, order=42]

我知道,我可以向MyDocument 添加一个函数

this.getValueAsString = function(name)
{
    var _prop = this[name];
    if(_prop instanceof PropertyObjectImpl)
       return "PropertyObject with ID : " + _prop.getID();
    else
       return _prop;
}

但出于练习目的,我想直接在这些属性上将此函数添加为toValueString(),以便调用如下:

var value = mydoc.SomeProperty.toValueString()

而不是

var value = mydoc.getValueAsString("SomeProperty");

这可能吗?

【问题讨论】:

    标签: javascript dynamic-function dynamic-properties


    【解决方案1】:

    您可以只覆盖相关类型的 .toString() 实现,而不是实现可能会做同样事情的东西。

    在现有类型上覆盖 .toString()

    Number.prototype.toString = function() {
        // return .toString() logic for Number types
    }
    
    Boolean.prototype.toString = function() {
        // return .toString() logic for Number types
    }
    

    在自定义类型上覆盖 .toString()

    var CustomType = (function() {
        function CustomType() {
            // CustomType logic
        }
    
        CustomType.prototype.toString = function() {
            // return .toString() logic for CustomType
        }
    
        return CustomType;
    })();
    

    请记住,toString() 内置于所有对象的 JavaScript 规范中,因此您可能会坚持这样的约定来覆盖它,而不是实现自己的方法。与实现自定义方法相比,这也不太可能中断,因为 .toString() 应该可以从任何属性调用,而 .toValueString() 只能在实现它的属性上调用。

    编辑:如果您的方法需要为任何类型返回完全自定义的字符串,那么您需要确保将自定义方法实现绑定到现有类型(数字、字符串、布尔值、函数, 对象等)

    编辑 2: 正如所指出的,重写 toString 的默认实现被认为是不好的做法,因此另一个想法是在对象级别绑定您的自定义方法,以便它可以从任何东西调用(因为 JavaScript 中几乎所有东西都扩展了 Object)

    Object.prototype.toValueString = function() {
        // return default implementation for this method;
    }
    
    CustomType.prototype.toValueString = function() {
        // return specific implementation for this method;
    }
    

    【讨论】:

    • 我不建议重新定义 toString,因为它不利于触摸您不拥有的对象(想想与 jQuery 之类的东西相比,PrototypeJs 库已经过时了)。标准/原生对象的行为应符合预期。
    • 感谢您的回答,这不是一个坏主意,但就像 pbo 所说,我不想覆盖所有这些对象的默认 toString()。
    【解决方案2】:

    我对你的问题有点困惑,但我会试一试。

    在 JS 中,有一个将值转换为字符串的标准接口:toString()。这是在 Object 上实现的,这意味着所有对象(以及转换为对象的基元)都将具有预期的行为。

    var obj = {
        age: 25,
        customField: {
            name: "test",
            toString: function () { return this.name };
        }
    };
    
    obj.age.toString(); // "25"
    obj.customField.toString() // "test"
    

    作为旁注,我只会将作为函数构造函数(js 类)的变量/引用大写。这在社区中几乎是标准的。

    【讨论】:

    • 感谢您的回答,但 'obj.customField.toString()' 对我不起作用,因为它返回与 obj.customField ('PropertyObjectImpl[id=abc123, data= Some Data, type=Node, order=42]') 我对这些对象或他的功能没有影响...
    • Js 是动态的,你可以扩展这些对象还是简单地用 toString 方法设置它们?
    • 另一种选择是包装这些对象中的每一个以遵守您需要的任何接口。 Object.create(propertyObject) 是一种创建继承自他的新对象的方法。然后返回附加一个 toString
    猜你喜欢
    • 2011-05-12
    • 1970-01-01
    • 2013-03-25
    • 2014-09-17
    • 2011-09-30
    • 2013-07-10
    • 2019-06-08
    • 2012-10-28
    • 1970-01-01
    相关资源
    最近更新 更多