JavaScript OOP动态getter setter - 我做错了什么

时间:2012-10-17 03:42:43

标签: javascript oop

我一直在努力寻找一种方法来完成这项工作。这真让我烦恼。我已经阅读了很多关于 OOP 的文章,虽然我知道我的代码并不完美,但我似乎无法解决我在下面的代码中概述的最初问题。

除动态getter/setter外,所有代码都有效 - 如果您在代码中阅读我的评论或运行代码,您可以轻松了解原因。

我有一种感觉,我想做的事情无法完成。有人可以告诉我哪里出错了,或者说我不能按照我提出的方式完成。

            var ext = {
        db: {
            string: function(def){
                def=def || {};
                def.type = "string";
                return def;
            },
            autoId: function(def){
                def=def || {};
                def.defaultvalue = function(){
                    return Math.uuid(def.length, def.radix)
                    return def;
                }
            }
        },
    }
    /*
     * @ext.base:       base class I can build out with common methods
     *                  
     */
    ext.base = function(){
        /*
         * place holder for the raw object data - 
         * 
         * {a:"martin webb",b:"is struggling with this"
         * 
         */
        this._rawdata={}; // this can later be strigified for storage; 

    };
    ext.base.prototype ={
        init:function(o){
            // pass in rawdata;
            this.load(o);
        },
        put:function(){
            //code removed
        },
        load: function(rawdata){
            this._rawdata=rawdata || {};
        }

    }
    /*
     * @ext.kind:       builds a new object we can use to make entities from our kind
     *                  martin=new people();
     * 
     */
    ext.db.kind=function(o){
        this._kind=function(o){this.init(o);} //this will pass any passed in object in the base class at init;
        this._kind.prototype = ext.base.prototype;

        var self=this;

        var prop,i=97; //ascii for "a";
        for (prop in o){
            if (o.hasOwnProperty(prop)) {
                /*
                 * This is like a dynamic getter setter, we are adding it to the prototype;
                 * 
                 * if you run the code when the function below is called
                 * value="martin webb" I need the var i to equal 97, and prop to = "name"
                 * in the function. I need a way to pass in and conserver these dynamic values
                 */
                this._kind.prototype[prop] = 
                    function(value){
                        if (value) {
                            self.rawdata[i] = value; //ERROR i=99!
                        }
                        return self.rawdata[i] ; //get the correct data using the key 
                    };

                    i++;
                }

        }
        return this._kind; // return our new object so we can use it like var martin=new people();
    }
    debugger;
    //lets make a new kind;
    var people={};
    people.name=ext.db.string();
    people.info=ext.db.string();
    people = new ext.db.kind(people);
    //and now make some entities usinhg it;
    var martin=new people();


    //THE CODE WILL GO WRONG HERE, THE SETTER WILL NOT WORK (SEE ABOVE)

    martin.name("martin webb")
    martin.info("is struggling with this code")

    var mike = new people({
        a: "mike",
        b: "has the solution"
    });
    console.log(mike.name()) //--> mike

1 个答案:

答案 0 :(得分:0)

我找到了解决方案。答案是使用机箱并捕获循环索引(i)。

的文章中对此进行了精美的解释

Explaining javascript Scope and closures

我的代码的更改如下并且有效!

           var prop, i = 97; //ascii for "a";
            //loop each property and make our own get/setter that works
            //off our underlying compressed rawdata;
            for (prop in o) {
                if (o.hasOwnProperty(prop)) {
                    /*
                     * this is the trick
                     * use an enclosure and pass our loop index in the bottom
                     * with a self calling function, this locks the value of i;
                     */
                    this._kind.prototype[prop] = function(k){
                        return function(value){
                            var key=String.fromCharCode(k);
                            //if we have a value passed in set it!
                            if (value){
                                this._rawdata[key]=value;
                            }
                            //always return our value;
                            return this._rawdata[key];
                        };
                      }(i); //here we call our function and lock index i;

                    i++;
                }//end loop;