动态创建JavaScript本机对象

时间:2014-10-18 07:31:39

标签: javascript

相当长的问题。但它基本上描述了我想要的内容。这里的代码用于创建任何对象according to user input到输入文本字段。如果我想创建数字,字符串或对象,我只是必须在text field中编写Number / String / Object。

引入了一个按钮来调用createObj.getObjName并从文本字段获取输入。它尝试匹配任何三种类型的对象(数字/字符串/对象)的输入。然后它调用一个bool函数 [problem lies here i think] 使用**list_keys array**使用Array.prototype.some进行迭代,assigned with objects是使用包含不同对象名称的json对象创建的。new keyword使用THIS keyword创建

问题是调用检查功能我试图强迫 createObj 在其中指示 console.log(this) 对象而不是window object.I尝试过 input html button element 它为我提供了 <input type='button' id='btn' value="create"> 的输出。

(function() {
    var list = {
        "Number": new Number(),
        "String": new String(),
        "Object": new Object(),
        "Array": new Array()
    }
    var list_keys = Object.keys(list);
    var createObj = {
        re: null,
        text: null,
        match: null,
        newObj: null,
        getObjName: function() {
            this.re = /Number|Object|String/;
            this.text = document.getElementById('text').value;
            this.match = this.text.match(this.re);
            var bool = check.call(this);
            if (bool) {
                this.makeObj(list.this.match[0]);
            }
        },
        makeObj: function(obj) {
            this.newObj = obj;
        }
    };

    function check() {
        console.log(this);
        return list_keys.some(function(el, indx, arr) {
            return this.match[0] === el;
        });
    }
    document.getElementById('btn').addEventListener('click', createObj.getObjName);
})();

但是我希望这可以引用createObj本身。为什么它指的是HTML元素?我该如何解决这个问题?

完整代码:

{{1}}

2 个答案:

答案 0 :(得分:2)

你可以绑定对象,就像这样

createObj.getObjName.bind(createObj)

这将返回一个新功能,this引用createObj内的getObjName

此外,如果根本没有匹配怎么办?

return this.match[0] === el;

这会在运行时失败,因为this.match将为null。所以你可能想做这样的事情

return this.match && list_keys.some(...);

如果我以更好的方式编写相同的代码,我会做这样的事情

(function() {
    var MyObject = {
        newObject: null,
        createObject: function() {
            var text = document.getElementById('text').value;
            if (window.hasOwnProperty(text)) {
                this.newObject = new window[text];
            }
        }
    }

    document.getElementById('btn').addEventListener('click', 
        MyObject.createObject.bind(MyObject));

})();

答案 1 :(得分:1)

将函数绑定到事件时,this引用事件绑定的html节点。你可以通过各种方式解决这个问题。首先想到的是直接引用createObj

getObjName: function() {
    createObj.re = /Number|Object|String/;
    createObj.text = document.getElementById('text').value;
    createObj.match = this.text.match(createObj.re);
    var bool = check.call(createObj);
    if (bool) {
        this.makeObj(list.createObj.match[0]);
    }
},

这不太理想,因为它通过名称引用对象,这意味着如果更改对象的名称,则必须更改对它的所有引用。如果您(或使用您的代码的其他开发人员)定义了新的createObj,那么它也会出现问题。由于它是按名称引用对象,因此它将开始使用新声明的对象而不是您的对象。一个改进是为对象创建一个别名(通常称为该别名):

getObjName: function() {
    that.re = /Number|Object|String/;
    that.text = document.getElementById('text').value;
    that.match = this.text.match(that.re);
    var bool = check.call(that);
    if (bool) {
        this.makeObj(list.that.match[0]);
    }
},
...
var that = createObj

问题在于that通常意味着在上下文丢失的范围内引用this,而不是任意对象(在这种情况下为createObj)。

此外,我不确定该函数是否属于createObj的方法,或者至少属于包含数据的结构。关注点的分离很重要,而

var createObj = {
    re: null,
    text: null,
    match: null,
    newObj: null,

关注您正在操纵的数据,getObjNamemakeObj关注事件处理和使用收集的数据制作对象。我提取出一个结构来保存数据,然后我会在其他对象中使用它:

var descriptors = {
    re: null,
    text: null,
    match: null,
    newObj: null
}

var getObjName = function() {
    descriptors.re = /Number|Object|String/;
    descriptors.text = document.getElementById('text').value;
    descriptors.match = descriptors.text.match(descriptors.re);
    var bool = check.call(descriptors);
    if (bool) {
        makeObj(list.descriptors.match[0]);
    }
}
var makeObj = function(obj) {
    this.newObj = obj;
}
function check() {
    console.log(this);
    return list_keys.some(function(el, indx, arr) {
        return this.match[0] === el;
    });
}
document.getElementById('btn').addEventListener('click', getObjName);

这将结构与功能分开,更好地传达了部分的意图(descriptors保存所有数据,getObjName处理事件,makeObj实例化新对象。

但是,从设计的角度来看,getObjName违反了单一责任原则,但仍存在一个问题。它的任务是处理事件并获取对象的名称。我重构了事件处理部分,以保持getObjName的意图:

var getObjName = function(descriptors) {
    descriptors.re = /Number|Object|String/;
    descriptors.text = document.getElementById('text').value;
    descriptors.match = this.text.match(descriptors.re);
    return check.call(descriptors);
}

document.getElementById('btn').addEventListener('click', function() {
    if (getObjName(descriptors)) {
        makeObj(list.descriptors.match[0]);
    }
});