vue1.0 Observer watcher 双向绑定简单js实现

来源:https://segmentfault.com/a/1190000004384515

(function(){
    //Observer
    var Observer = cc.Class.extend({
        ctor: function(value){
            this.value = value;
            this.walk(value);
        },
        walk: function(value){
            Object.keys(value).forEach(function(key, ind, arr){
                this.convert(key,value[key]);
            },this);
        },
        convert: function(key, val){
            defineReactive(this.value, key, val);
        }
    });
    var defineReactive = function(obj, key, val){
        var dep = new Dep();
        var childOb = observer(val);
        Object.defineProperty(obj, key, {
            enumberable: true,
            configurable: true,
            get: function(){
                console.log("get");
                if(Dep.target){
                    dep.addSub(Dep.target);
                }
                return val;
            },
            set: function(newValue){
                console.log("set",newValue);
                var value = val;
                if(newValue === value){
                    return;
                }
                childOb = observer(newValue);
                dep.notify();
            }
        })
    };
    var observer = function(value, vm){
        if (!value || typeof value !== 'object') {
            return;
        }
        return new Observer(value);
    };
    //订阅器
    var Dep = cc.Class.extend({
        ctor: function(){
            this.subs = [];
        },
        addSub:function(sub){
            this.subs.push(sub);
        },
        notify:function(){
            this.subs.forEach(function(sub, ind, arr){
                sub.update();
            })
        },
    });
    Dep.target = null
    //watcher
    var Watcher = cc.Class.extend({
        ctor: function(vm, expOrFn, cb){
            this.cb = cb;
            this.vm = vm;
            //暂时只考虑expression的情况
            this.expOrFn = expOrFn;
            this.value = this.get();
        },
        update: function(){
            this.run();
        },
        run: function(){
            var value = this.get();
            if(value !== this.value){
                this.value = value ;
                this.cb.call(this.vm);
            }
        },
        get: function(){
            Dep.target = this;
            //暂时只考虑expression的情况
            var value = this.vm._data[this.expOrFn];
            Dep.target = null;
            return value;
        }
    });
    //Vue
    var vue = cc.Class.extend({
        ctor: function(options){
           this.$options = options || {};
           var data = this._data = this.$options.data;
           Object.keys(data).forEach(function(key, ind, arr){
               this._proxy(key);
           },this);
           observer(data, this);
        },
        $watcher: function(expOrFn, cb, options){
            new Watcher(this, expOrFn, cb);
        },
        _proxy: function(key){
            var self = this;
            Object.defineProperty(self, key, {
                configurable: true,
                enumberalbe: true,
                get:function proxyGetter(){
                    return self._data[key];
                },
                set: function proxySetter(val){
                    self._data[key] = val;
                }
            });
        }
    });

    mj.vue = vue;
})();

js 模拟jq 实现 $ 选择器

(function(){
    var jQ = function(selector, father){
        return new jQ.prototype.init(selector);
    };
    jQ.prototype = {
        length:0,
        init:function(selector, father){
            var _document = father || ja.view,
                classInt = 0,
                res = this;
            if (typeof selector != "string" || !selector ){
                if(typeof selector == "object" && selector.hasOwnProperty("length")){
                    for(var i = 0 ; i < selector.length ; i++){
                        this[classInt] = selector[i];
                        classInt++;
                    }
                }else{
                    this[classInt] = selector;
                    classInt++;
                }

            }else{
                var props = selector.trim().split(" "),
                    selector = props.shift(),
                    selectLast = props.join(" "),
                    mark = selector.charAt(0);
                if(mark == "["){
                    var selector=selector.replace(/[\[\]]/g,""),
                        arr = selector.split("=");
                    key = arr.length > 1 ? arr[0].trim() : "name",
                        val = arr.length > 1 ? arr[1].trim() : arr[0].trim();
                    //遍历children
                    // ja.log(key,val);
                    _document.children.map(function(ele){
                        return (function(father,deep){
                            // var res = [];
                            if(typeof father[key] !="undefined" && father[key] == val){

                                this[classInt] = father;
                                classInt++;
                            }
                            var c = father.children;
                            if(c && deep < 5){
                                deep++;
                                for(var i in c){
                                    arguments.callee.call(this,c[i],deep);
                                }
                            }
                            // return res;
                        }).call(this,ele,0);
                    }.bind(this))
                }else if(mark == "."){
                    var res = this.__class(selector.substring(1));
                    res.map(function(ele){
                        this[classInt] = ele;
                        classInt++;
                    }.bind(this));

                }
            }
            this.length = classInt;
            return this;
        },
        /*原型方法,不暴露*/
        //类选择器位置列表
        __class:function(className){
            var arr = [];
            switch (className){
                case "mainView":
                    arr.push(ja.view);
                    break;
                case "setBalance":
                    arr.push(ja.setb);
                    break;
                case "gameBalance":
                    arr.push( ja.gameb);
                    break;
                case "playerFrameList":
                    for(var key in ja.view.playerInfoHandler.playerFrameList){
                        arr.push(ja.view.playerInfoHandler.playerFrameList[key].view);
                    }
                    break;
                case "playerArea":
                    arr.push( ja.view.posLocal2Player);
                    break;
                case "playerOut":
                    ja.view.posLocal2Player.map(function(ele){
                        arr.push( ele.outTile);
                    });
                    break;
                default:
                    return null
            }
            return arr;
        },
        //通过选择器确定子元素获取方式
        _selector: function(selector, father){
            if(typeof selector != "string" || !selector){
                return this;
            }
            father = father ? father.children : Array.prototype.slice.apply(this);
            var mark = selector.charAt(0);
            switch(mark){
                case "[":
                    var reg = /\[(([\w\W]+)=["']?([\w\W]+)["']?|([\w\W]+))\]/;
                    var reg_res = reg.exec(selector);
                    var res_key = reg_res[2] || "name";
                    var res_val = reg_res[3] || reg_res[4];
                    var res = [];
                    father.map(function(ele){
                        return (function(fa, deep){

                            if(typeof fa[res_key] != "undefined" && fa[res_key] == res_val){
                                res.push(fa);
                            }

                            if (fa.children.length > 0 && deep < 5){
                                deep++;
                                for( var i = 0 ; i < fa.children.length ; i++){
                                    var add = arguments.callee.call(this,fa.children[i],deep);
                                }
                            }
                            return res;
                        }).call(this,ele,0);
                    }.bind(this));

                    return res;
                case ":":

                    break;
                case "*":

                    break;
                default:

            }
        },
        //表达式筛选器,未完成
        _expression:function(expression){
            if(!expression){

            }
            switch (expression){
                case "first":
                    return 0;
                case "last":
                    return
            }
        },
        /*过滤*/
        find:function(selector){
            var res = this._selector(selector);
            return new jQ.prototype.init(res);
        },
        parent:function(){
            var arr = [];
            Array.prototype.slice.apply(this).map(function(ele,ind){
                arr.push(ele["parent"]);
            }.bind(this));
            if(arr.length > 0){
                var res = arr.length == 1 ? arr.shift() : arr;
                return new jQ.prototype.init(res);
            }
        },
        parents:function(){

        },
        child:function(selector){

        },
        /*操作*/
        attr:function(selector, setValue){
            var arr = [];
            Array.prototype.slice.apply(this).map(function(ele,ind){
                if(typeof setValue == "undefined"){
                    if(typeof ele[selector] != "undefined"){
                        arr.push(ele[selector]) ;
                    }else if(typeof ele["_"+selector] != "undefined"){
                        arr.push(ele["_"+selector]) ;
                    }

                }else{
                    ele[selector] = setValue;
                }
            }.bind(this));
            if(arr.length > 0){
                return arr.length == 1 ? arr.shift() : arr;
            }
        },
        hide:function(){
            Array.prototype.slice.apply(this).map(function(ele){
                ele.setVisible(false);
            })
        },
        show:function(){
            Array.prototype.slice.apply(this).map(function(ele){
                ele.setVisible(true);
            })
        },
    };
    jQ.prototype.init.prototype = jQ.prototype;
    return window.$ = jQ;
})()

js 模拟类, 继承

var initializing = false, fnTest = /xyz/.test(function() { xyz; }) ? /\b_super\b/ : /.*/;
    //构造基类
    this.jaClass = function() {};
    jaClass.extend = function(props){
        var _super = this.prototype;
        initializing = true;
        var prototype = new this();
        initializing = false;

        for (var name in props){
            //这一段是赋值到prototype中,运用三元运算符的方式很灵活
            //满足函数的条件作为函数插入到prototype中
            prototype[name] = typeof props[name] =="function" &&
            typeof _super[name] == "function" && fnTest.test(props[name]) ?
                (function(name, fn) {
                    return function(){
                        var tmp = this._super;
                        this._super = _super[name];
                        var ret = fn.apply(this, arguments);
                        this._super = tmp;
                        return ret;
                    };
                })(name, props[name]) :
                props[name]
        }

        function Class(){
            if(!initializing && this.ctor)
                this.ctor.apply(this, arguments);
        }

        //子类prototype指向父类的实例,继承的关键
        Class.prototype = prototype ;
        Class.prototype.constructor = Class;
        //子类自动获得extend方法,arguments.callee 指向当前正在执行的函数
        Class.extend = arguments.callee;
        return Class;
    };

原生js 一次性函数

// 创建一个一次性事件
function onetime(node, type, callback) {

    // 创建事件
    node.addEventListener(type, function(e) {
        // 移除事件
        e.target.removeEventListener(e.type, arguments.callee);
        // 调用处理器
        return callback(e);
    });

}

js 真值表

nullundefinedfalse"false"Boolean(false)[][[]]""String("")0Number(0)"0"String("0")[0]true"true"Boolean(true)1Number(1)"1"String("1")[1]-1Number(-1)"-1"String("-1")[-1]Infinity-InfinityObject()NaNnullundefinedfalse"false"Boolean(false)[][[]]""String("")0Number(0)"0"String("0")[0]true"true"Boolean(true)1Number(1)"1"String("1")[1]-1Number(-1)"-1"String("-1")[-1]Infinity-InfinityObject()NaN=====>= && <=>=<=else

正则符号过滤 并添加反义符

// 正则符号前加反义符,避免正则符号导致匹配错误
function regular_encode (string){
  return string.replace( /[+\\*?.\[\]\{\}\|\(\)\<\=]/g, function(word){return "\\"+word} );
}
//应用
var string = "df+54d[dfdf]";
string.replace( /[+\\*?.\[\]\{\}\|\(\)\<\=]/g, function(word){return "\\"+word} )
//输出:"df\+54d\[dfdf\]"

js md5

来源:http://www.oschina.net/code/snippet_12_8927

/**
*
*  MD5 (Message-Digest Algorithm)
*  http://www.webtoolkit.info/
*
**/
  
var MD5 = function (string) {
  
    function RotateLeft(lValue, iShiftBits) {
        return (lValue<>>(32-iShiftBits));
    }
  
    function AddUnsigned(lX,lY) {
        var lX4,lY4,lX8,lY8,lResult;
        lX8 = (lX & 0x80000000);
        lY8 = (lY & 0x80000000);
        lX4 = (lX & 0x40000000);
        lY4 = (lY & 0x40000000);
        lResult = (lX & 0x3FFFFFFF)+(lY & 0x3FFFFFFF);
        if (lX4 & lY4) {
            return (lResult ^ 0x80000000 ^ lX8 ^ lY8);
        }
        if (lX4 | lY4) {
            if (lResult & 0x40000000) {
                return (lResult ^ 0xC0000000 ^ lX8 ^ lY8);
            } else {
                return (lResult ^ 0x40000000 ^ lX8 ^ lY8);
            }
        } else {
            return (lResult ^ lX8 ^ lY8);
        }
    }
  
    function F(x,y,z) { return (x & y) | ((~x) & z); }
    function G(x,y,z) { return (x & z) | (y & (~z)); }
    function H(x,y,z) { return (x ^ y ^ z); }
    function I(x,y,z) { return (y ^ (x | (~z))); }
  
    function FF(a,b,c,d,x,s,ac) {
        a = AddUnsigned(a, AddUnsigned(AddUnsigned(F(b, c, d), x), ac));
        return AddUnsigned(RotateLeft(a, s), b);
    };
  
    function GG(a,b,c,d,x,s,ac) {
        a = AddUnsigned(a, AddUnsigned(AddUnsigned(G(b, c, d), x), ac));
        return AddUnsigned(RotateLeft(a, s), b);
    };
  
    function HH(a,b,c,d,x,s,ac) {
        a = AddUnsigned(a, AddUnsigned(AddUnsigned(H(b, c, d), x), ac));
        return AddUnsigned(RotateLeft(a, s), b);
    };
  
    function II(a,b,c,d,x,s,ac) {
        a = AddUnsigned(a, AddUnsigned(AddUnsigned(I(b, c, d), x), ac));
        return AddUnsigned(RotateLeft(a, s), b);
    };
  
    function ConvertToWordArray(string) {
        var lWordCount;
        var lMessageLength = string.length;
        var lNumberOfWords_temp1=lMessageLength + 8;
        var lNumberOfWords_temp2=(lNumberOfWords_temp1-(lNumberOfWords_temp1 % 64))/64;
        var lNumberOfWords = (lNumberOfWords_temp2+1)*16;
        var lWordArray=Array(lNumberOfWords-1);
        var lBytePosition = 0;
        var lByteCount = 0;
        while ( lByteCount < lMessageLength ) {
            lWordCount = (lByteCount-(lByteCount % 4))/4;
            lBytePosition = (lByteCount % 4)*8;
            lWordArray[lWordCount] = (lWordArray[lWordCount] | (string.charCodeAt(lByteCount)<>>29;
        return lWordArray;
    };
  
    function WordToHex(lValue) {
        var WordToHexValue="",WordToHexValue_temp="",lByte,lCount;
        for (lCount = 0;lCount<=3;lCount++) {
            lByte = (lValue>>>(lCount*8)) & 255;
            WordToHexValue_temp = "0" + lByte.toString(16);
            WordToHexValue = WordToHexValue + WordToHexValue_temp.substr(WordToHexValue_temp.length-2,2);
        }
        return WordToHexValue;
    };
  
    function Utf8Encode(string) {
        string = string.replace(/\r\n/g,"\n");
        var utftext = "";
  
        for (var n = 0; n < string.length; n++) {
  
            var c = string.charCodeAt(n);
  
            if (c < 128) {
                utftext += String.fromCharCode(c);
            }
            else if((c > 127) && (c < 2048)) {
                utftext += String.fromCharCode((c >> 6) | 192);
                utftext += String.fromCharCode((c & 63) | 128);
            }
            else {
                utftext += String.fromCharCode((c >> 12) | 224);
                utftext += String.fromCharCode(((c >> 6) & 63) | 128);
                utftext += String.fromCharCode((c & 63) | 128);
            }
  
        }
  
        return utftext;
    };
  
    var x=Array();
    var k,AA,BB,CC,DD,a,b,c,d;
    var S11=7, S12=12, S13=17, S14=22;
    var S21=5, S22=9 , S23=14, S24=20;
    var S31=4, S32=11, S33=16, S34=23;
    var S41=6, S42=10, S43=15, S44=21;
  
    string = Utf8Encode(string);
  
    x = ConvertToWordArray(string);
  
    a = 0x67452301; b = 0xEFCDAB89; c = 0x98BADCFE; d = 0x10325476;
  
    for (k=0;k