• javascript模式及javascript学习终极篇


     activeElement属性 焦点元素

    代码检测工具http://www.jslint.com/#JSLINT_OPTIONS

     ECMAScript 5 http://www.cnblogs.com/aaa6818162/archive/2012/09/09/2677280.html

      javascript性能比较   http://www.cnblogs.com/aaa6818162/archive/2012/09/12/2681236.html

     javascript 杂谈之哪种写法你更喜欢? http://www.cnblogs.com/aaa6818162/archive/2012/06/04/2534835.html

    分享15款很棒的 JavaScript 开发工具  http://www.cnblogs.com/aaa6818162/archive/2011/07/19/2110157.html

    实例---------类的几种写法

    //几种类的写法
    如果想定义OMS.prdgird.DD 必须构造三次检查,每次检查都针对定义的一个对象或者属性。


    var OMS = OMS || {};
    //静态方法 如果存在一个命名空间,便不会重新创建它。
    OMS.namespace = function (ns_string) {
        var parts = ns_string.split('.'),
             parent = OMS,
             i;

        if (parts[0] === "OMS") {
            parts = parts.slice(1);
        }
        for (i = 0; i < parts.length; i += 1) {
            if (typeof parent[parts[i]] === "undefined") {
                parent[parts[i]] = {};
            }
            parent = parent[parts[i]];
        }
        return parent;
    };


    OMS.namespace("OMS.prdgird");

    //构造函数
    OMS.prdgird = function (gridid) {
        this.girdid = gridid;
        var msg = "sss"; //私有属性
    }
    //原型方法
    OMS.prdgird.prototype = {
        addRow: function () {
            alert("addRow" + this.girdid);
        },
        delRow: function () {
            alert("delRow" + this.girdid);
        }
    }

    OMS.namespace("OMS.prdgird.salemark");
    OMS.prdgird.salemark = function () {

    }
    OMS.prdgird.salemark.prototype = {
        show: function () { alert("show"); }
    }



    //改进写法
    OMS.namespace("OMS.paygird");
    OMS.paygird = (function () {

        //构造函数
        var myclass = function () { };


        //静态方法
        myclass.staticMethod = function () {
            alert("staticMethod");
        }

        //普通方法
        myclass.prototype = {
            addRow: function () {
                alert("addRow");
            },
            delRow: function () {
                alert("delRow");
            }
        }

        return myclass;
    } ());


    //类的普通实现
    var prdgird = new OMS.prdgird();
    prdgird.girdid = "ffffffffffffff";
    prdgird.addRow();

    var salemark = new OMS.prdgird.salemark();
    salemark.show();

    var paygird = new OMS.paygird();
    paygird.addRow();
    OMS.paygird.staticMethod();

     继承的几种写法

    /// <reference path="jquery-easyui-1.2.5/jquery-1.7.1.min.js" />


    var OMS = OMS || {};
    //静态方法
    OMS.namespace = function (ns_string) {
        var parts = ns_string.split('.'),
             parent = OMS,
             i;

        if (parts[0] === "OMS") {
            parts = parts.slice(1);
        }
        for (i = 0; i < parts.length; i += 1) {
            if (typeof parent[parts[i]] === "undefined") {
                parent[parts[i]] = {};
            }
            parent = parent[parts[i]];
        }
        return parent;
    };


    //改进写法1
    OMS.namespace("OMS.paygird");
    OMS.paygird = (function () {

        //构造函数
        var myclass = function () {

            this.method = function () {
                alert("method");
            };
        };


        //静态方法
        myclass.staticMethod = function () {
            alert("staticMethod");
        }

        //普通方法
        myclass.prototype = {
            addRow: function () {
                alert("addRow");
            },
            delRow: function () {
                alert("delRow");
            }
        }

        return myclass;
    } ());


    //继承1
    var inherit = (function () {
        var F = function () { };
        return function (C, P) {
            F.prototype = P.prototype;
            C.prototype = new F();
            C.uber = P.prototype;
            C.prototype.constructor = C;
        }
    } ());
    var child = function () { };
    inherit(child, OMS.paygird); //继承 只继承prototype下的方法
    new child().addRow(); //成功
    new child().method(); //错误
    child.staticMethod(); //错误


    //继承2
    var child = function () {
        OMS.paygird.call(this);//继承this下的方法
    };
    inherit(child, OMS.paygird); //继承 只继承prototype下的方法
    new child().addRow(); //成功
    new child().method(); //成功
    child.staticMethod(); //错误

    //继承3
    var child = $.extend(new OMS.paygird(), {});
    child.addRow(); //成功
    child.method(); //成功
    child.staticMethod();//失败

    //继承4 最佳吧感觉借助jquery的extend
    var child = $.extend(OMS.paygird, {});
    new child().addRow()//成功
    new child().method(); //成功
    child.staticMethod();//成功

    //继承5
    var parent = new OMS.paygird(); 
    var child = Object(parent);
    child.addRow()//成功
    child.method(); //成功
    child.staticMethod(); //失败

    ////继承6 这个功能都实现了不知道好不好
    var child = Object(OMS.paygird);
    new child().addRow()//成功
    new child().method(); //成功
    child.staticMethod(); //成功

    一、javascript基本技巧

    1.尽量少用全局变量

    2.变量释放时的副作用

    隐藏全局变量与明确定义的全局变量有细微的不同,不同之处在于能否使用delete操作符撤销变量。

    1)使用var创建的全局变量不能删除。

    2)不使用var创建的隐含全局变量可以删除。

    3.单一var模式

    如下:

            function func() {
                var a = 1,
                    b = 2,
                    sum = a + b,
                    i,
                    j;
            }


     

     4.for循环

            function looper() {
                var i = 0,
                    max,
                    myarray = [];
                for (i = 0, max = myarray.length; i < max; i++) {

                }
            }

     5.for-in循环

    // the object
    var man = {
        hands: 2,
        legs: 2,
        heads: 1
    };
    // somewhere else in the code
    // a method was added to all objects
    if (typeof  Object.prototype.clone === "undefined") {
        Object.prototype.clone = function () {};
    }

    for (var i in man) {
        if (man.hasOwnProperty(i)) { // filter
            console.log(i, ":", man[i]);
        }
    }
    /*
    result in the console
    hands : 2
    legs : 2
    heads : 1
    */
    // 2.
    // antipattern:
    // for-in loop without checking hasOwnProperty()
    for (var i in man) {
        console.log(i, ":", man[i]);
    }
    /*
    result in the console
    hands : 2
    legs : 2
    heads : 1
    clone: function()
    */

    6.不要增加内置的原型

            if (typeof Object.prototype.myMethod !== "function") {
                Object.prototype.myMethod = function () {

                };
            }

    7.避免使用隐式类型转换

    在使用比较语句的时候使用===和!===操作

    8.避免使用eval()

     二、构造函数

    1.强者使用new的模式 避免忘记使用new所带来的问题

            function A() {
                var that = {};
                that.Method = function () {
                };
                return that;
            }

    2.自调用构造函数

            function A() {
                if (!(this instanceof A)) {
                    return new A();
                }

                //或 在ES5的严格模式中并不支持rguments.callee属性
                //if (!(this instanceof arguments.callee)) {
                //  return new arguments.callee();
                // }

                var that = {};
                that.Method = function () {
                };
                return that;
            }

    3.

    三、函数
    1.回调模式

     


     //回调函数
            var obj = function () {
                this.name = "liww";
                obj.prototype.Mehthod = function () {
                    alert(this.name);
                }
            }

            var findNodes = function (callback) {
                if (typeof callback === "function") {
                    callback();
                }
            };
            var ser = new obj();
            findNodes(ser.Mehthod); //得不到name 因为this指向了findNodes

            ////////////////////////////////////////////////////////////////////////////////////////
            //正确的方式是传递回调函数并且传递回调函数所属的对象
            var findNodes = function (callback, callback_obj) {
                if (typeof callback === "function") {
                    callback.call(callback_obj);
                }
            };
            var ser = new obj();
            findNodes(ser.Mehthod, ser);

            //////////////////////////////////////////////////////////////////////////////////////////

            //带动态参数的回调
            var obj = function () {
                this.name = "liww";
                obj.prototype.Mehthod = function (time1, time2) {
                    alert(this.name + time1 + time2);
                }
            }

            var findNodes = function (callback, callback_obj, parameter) {
                if (typeof callback === "function") {
                    callback.apply(callback_obj, parameter);
                }
            };
            var ser = new obj();
            findNodes(ser.Mehthod, ser, ["2222222", "333333"]); 
     

    2.自定义函数

     


     var scareMe = function () {
            alert("Boo!");
            scareMe = function () {
                alert("Double boo!");
            };
        };

        scareMe(); // Boo!
        scareMe(); // Double boo!

        //适用于函数有些初始化工作并只执行一次的情况
        //缺点:当它重新定义本身的时候已经添加到原始函数的任何属性都会丢失
     

     

    2.即时函数

     

    (fuction(){

    alert('watch out');}());

     

    3.即时对象初始化

    ({
    // here you can define setting values
    //
     a.k.a. configuration constants
    max 600,
    maxheight: 400,
    // you can also define utility methods
    gimmeMax: function () {
    return this.maxwidth + "x" + this.maxheight;
    },
    // initialize
    init: function () {
    console.log(this.gimmeMax());
    // more init tasks...
    }
    }).init();

     

    4.函数属性--备忘模式

            var myFunc = function (param) {
                if (!myFunc.cache[param]) {
                    var result = {};
                    // ... expensive operation ...
                    myFunc.cache[param] = result;
                }
                return myFunc.cache[param];
            };
            // cache storage
            myFunc.cache = {};

    5.配置对象--即传人参数序列化成一个json

             var conf = {
                username: "batman",
                first: "Bruce",
                last: "Wayne"
            };
            addPerson(conf);

    6.curry化函数[方法的参数动态]

             function schonfinkelize(fn) {
                var slice = Array.prototype.slice,
                    stored_args = slice.call(arguments, 1);
                return function () {
                    var new_args = slice.call(arguments),
                        args = stored_args.concat(new_args);
                    return fn.apply(null, args);
                };
            }

     

            // a normal function
            function add(a, b, c, d, e) {
                return a + b + c + d + e;
            }
            // works with any number of arguments
            schonfinkelize(add, 1, 2, 3)(5, 5); // 16
            // two-step currying
            var addOne = schonfinkelize(add, 1);
            addOne(10, 10, 10, 10); // 41
            var addSix = schonfinkeliz

     
    四、对象创建模式

     1.命名空间

    通用命名空间函数

     


    var MYAPP = MYAPP || {};
    MYAPP.namespace = function (ns_string) {
        var parts = ns_string.split('.'),
            parent = MYAPP,
            i;
        // strip redundant leading global
        if (parts[0] === "MYAPP") {
            parts = parts.slice(1);
        }
        for (i = 0; i < parts.length; i += 1) {
            // create a property if it doesn't exist
            if (typeof parent[parts[i]] === "undefined") {
                parent[parts[i]] = {};
            }

            parent = parent[parts[i]];
        }
        return parent;
    };

     // assign returned value to a local var
    var module2 = MYAPP.namespace('MYAPP.modules.module2');
    module2 === MYAPP.modules.module2; // true
    //
     skip initial `MYAPP`
    MYAPP.namespace('modules.module51');
    // long namespace
    MYAPP.namespace('once.upon.a.time.there.was.this.long.nested.property');

     

     2私有属性

    私有成员

    特权方法:是指那些可以访问私有成员的公共方法。

     

    3.揭示模式:将私有方法揭示为公共方法

    var myarray;
    (function () {
        var astr = "[object Array]",
            toString = Object.prototype.toString;
        function isArray(a) {
            return toString.call(a) === astr;
        }
        function indexOf(haystack, needle) {
            var i = 0,
                max = haystack.length;
            for (; i < max; i += 1) {
                if (haystack[i] === needle) {
                    return i;
                }
            }
            return −1;
        }

        myarray = {
            isArray: isArray,
            indexOf: indexOf,
            inArray: indexOf
        };
    }());

     

    4.模块模式

    MYAPP.namespace('MYAPP.utilities.array');
    MYAPP.utilities.array = (function () {
            // dependencies
        var uobj  = MYAPP.utilities.object,
            ulang = MYAPP.utilities.lang,
            // private properties
            array_string = "[object Array]",
            ops = Object.prototype.toString;
            // private methods
            // ...
            // end var
        // optionally one-time init procedures
        // ...
        // public API
        return {
            inArray: function (needle, haystack) {
                for (var i = 0, max = haystack.length; i < max; i += 1) {
                    if (haystack[i] === needle) 

                        return true;
                    }
                }
            },
            isArray: function (a) {
                return ops.call(a) === array_string;
            }
            // ... more methods and properties
        };
    }());

     

    5.揭示模块模式

    MYAPP.utilities.array = (function () {
            // private properties
        var array_string = "[object Array]",
            ops = Object.prototype.toString,
            // private methods
            inArray = function (haystack, needle) {
                for (var i = 0, max = haystack.length; i < max; i += 1) {
                    if (haystack[i] === needle) {
                        return i;
                    }
                }
                return −1;
            },
            isArray = function (a) {
                return ops.call(a) === array_string;
            };
            // end var
        // revealing public API
        return {
            isArray: isArray,
            indexOf: inArray
        };
    }());

     

    6。创建构造函数的模块

    MYAPP.namespace('MYAPP.utilities.Array');
    MYAPP.utilities.Array = (function () {
            // dependencies
        var uobj  = MYAPP.utilities.object,
            ulang = MYAPP.utilities.lang,
            // private properties and methods...
            Constr;
            // end var
        // optionally one-time init procedures
        // ...
        // public API -- constructor
        Constr = function (o) {
            this.elements = this.toArray(o);
        };
        // public API -- prototype
        Constr.prototype = {
            constructor: MYAPP.utilities.Array,
            version: "2.0",
            toArray: function (obj) {
                for (var i = 0, a = [], len = obj.length; i < len; i += 1) {
                    a[i] = obj[i];
                }
                return a;
            }
        };
        // return the constructor
        // to be assigned to the new namespace
        return Constr;
    }());

     

    7.沙箱模式

     提供了一个可用于模块运行的环境,且不会对其他模块和个人沙箱造成任何影响。

     function Sandbox() {
            // turning arguments into an array
        var args = Array.prototype.slice.call(arguments),
            // the last argument is the callback
            callback = args.pop(),
            // modules can be passed as an array or as individual parameters
            modules = (args[0] && typeof args[0] === "string") ? args : args[0],
            i;
        // make sure the function is called
        // as a constructor
        if (!(this instanceof Sandbox)) {
            return new Sandbox(modules, callback);
        }
        // add properties to `this` as needed:
        this.a = 1;
        this.b = 2;
        // now add modules to the core `this` object
        // no modules or "*" both mean "use all modules"
        if (!modules || modules === '*') {
            modules = [];
            for (i in Sandbox.modules) {
                if (Sandbox.modules.hasOwnProperty(i)) {
                    modules.push(i);
                }
            }
        }
        // initialize the required modules
        for (i = 0; i < modules.length; i += 1) {
            Sandbox.modules[modules[i]](this);
        }
        // call the callback
        callback(this);
    }
    // any prototype properties as needed
    Sandbox.prototype = {
        name: "My Application",
        version: "1.0",
        getName: function () {
            return this.name;
        }
    };

     

    8.公有静态成员

    // constructor
    var Gadget = function (price) {
        this.price = price;
    };
    // 静态方法
    Gadget.isShiny = function () {
        // this always works

        var msg = "you bet";
        if (this instanceof Gadget) {
            // this only works if called non-statically
            msg += ", it costs $" + this.price + '!';
        }
        return msg;
    };
    // 向该原型中添加一个普通方法
    Gadget.prototype.isShiny = function () {
        return Gadget.isShiny.call(this);
    };
    Testing a static method call:
    Gadget.isShiny(); // "you bet"
    Testing an instance, nonstatic call:
    var a = new Gadget('499.99');
    a.isShiny(); // "you bet, it costs $499.99!"

     

    9.私有静态成员

    // 构造函数
    var Gadget = (function () {
        // static variable/property
        var counter = 0,
            NewGadget;
        // this will become the
        // new constructor implementation
        NewGadget = function () {
            counter += 1;
        };
        // a privileged method
        NewGadget.prototype.getLastId = function () {
            return counter;
        };
        // overwrite the constructor
        return NewGadget;
    }()); // execute immediately
    Testing the new implementation:
    var iphone = new Gadget();
    iphone.getLastId(); // 1
    var ipod = new Gadget();
    ipod.getLastId();   // 2
    var ipad = new Gadget();
    ipad.getLastId();   // 3

     

    10.对象常量

     

    11.链模式

    可以使你能够一个接一个的调用对象的方法,而无需将前一个操作返回的值赋给变量,并且无需将你的调用分割成多行。 
    var obj = {
        value: 1,
        increment: function () {
            this.value += 1;
            return this;
        },
        add: function (v) {
            this.value += v;
            return this;
        },
        shout: function () {
            alert(this.value);
        }
    };
    // chain method calls
    obj.increment().add(3).shout(); // 5
    //
     as opposed to calling them one by one
    obj.increment();
    obj.add(3);
    obj.shout(); // 5
     

     

     实例


     1 var OMS = OMS || {};
     2 OMS.namespace = function (ns_string) {
     3     var parts = ns_string.split('.'),
     4         parent = OMS,
     5         i;
     6 
     7     if (parts[0] === "OMS") {
     8         parts = parts.slice(1);
     9     }
    10     for (i = 0; i < parts.length; i += 1) {
    11         if (typeof parent[parts[i]] === "undefined") {
    12             parent[parts[i]] = {};
    13         }
    14         parent = parent[parts[i]];
    15     }
    16     return parent;
    17 };
    18 
    19 OMS.namespace("gird");
    20 
    21 OMS.gird = function () {
    22     var girdId = "datagrid";
    23     var toolbarId = "toolbar";
    24     this.init = function (girdId, toolbarId) {
    25         girdId = girdId;
    26         toolbarId = toolbarId;
    27     };
    28 
    29     this.search = function () {
    30         var jsonSearch = utility.paramsToJson($("#" + toolbarId + " input,select").fieldSerialize());
    31         $("#" + girdId).datagrid("getPager").pagination("options").pageNumber = 1;
    32         $("#" + girdId).datagrid('options').queryParams = jsonSearch;
    33         $("#" + girdId).datagrid('reload');
    34     };
    35 
    36     this.refurbish = function () {
    37         $("#" + toolbarId + " input").clearFields();
    38         $("#" + toolbarId + " select").each(
    39         function () {
    40             $(this).get(0).selectedIndex = 0;
    41         }
    42         );
    43         $("#" + girdId).datagrid("getPager").pagination("options").pageNumber = 1;
    44         $("#" + girdId).datagrid('options').queryParams = {};
    45         $("#" + girdId).datagrid('reload');
    46     };
    47 }
     
    五、代码复用模式

     jQuery框架提供的拷贝功能非常强大,支持简单对象的深拷贝与浅拷贝。但是,它还不是类级的继承,因为它的拷贝只作用于简单对象(如{name:'zcj',age:28})。

    1.类式继承模式--默认模式

    function inherit(C, P) {
        C.prototype = new P();
    }

    var kid = new Child();
    kid.say(); // "Adam"

     

    缺点:同时继承了两个对象的属性,即添加到this的属性以及原型属性

           它并不支持将参数传递到子构造函数中,而子构造函数然后又将参数传递到父构造函数中。

    var s = new Child('Seth');
    s.say(); // "Adam"

     

    2.类式继承模式--借用构造函数

    // 父构造函数

    function Parent(name) {
        this.name = name || 'Adam';
    }
    // 向原型添加功能

    Parent.prototype.say = function () {
        return this.name;
    };
    // 子构造函数

    function Child(name) {
        Parent.apply(this, arguments);
    }
    var kid = new Child("Patrick");//kid获得了自身的属性name 但是却从未继承say方法
    kid.name; // "Patrick"  
    typeof kid.say; // "undefined"

     

    这种方式的缺点:只能继承在父构造函数中添加到this的属性。prototype不会被继承。

    在高级面向对象语言中,类的存储是很优美的,对类的每个实例来说,其不同的部分就是用于描述其状态的属性,而它们的行为(即方法)都是相同的,所以在运行期只会为每个类实例的属性分配存储空间,方法则是每个类实例所共享的,是不占用存储空间的。

    优点:在于可以获得父对象自身成员的真实副本,并且也不会存在子对象意外覆盖父对象属性的风险。

     

    3. 类式继承模式--借用和设置原型

    // 父构造函数

    function Parent(name) {
        this.name = name || 'Adam';
    }
    // 添加原型方法

    Parent.prototype.say = function () {
        return this.name;
    Figure 6-5. A CatWings object inspected in Firebug
    Classical Pattern #3—Rent and Set Prototype | 123
    };
    // 子构造函数
    function Child(name) {
        Parent.apply(this, arguments);
    }
    Child.prototype = new Parent();
    var kid = new Child("Patrick");
    kid.name; // "Patrick"
    kid.say(); // "Patrick"
    delete kid.name;
    kid.say(); // "Adam"

    优点:可以继承父对象中的一切东西,同时安全的修改自身的属性。

    缺点:父构造函数被调用两次,因此这导致了其效率低下的问题。最后自身的属性会被继承两次。

     

    4. 类式继承模式--共享原型

    前提 任何值得继承的东西都得放置在原型中实现。所以仅将子对象的原型与父对象的原型设置为相同即可。

    function inherit(C, P) {
        C.prototype = P.prototype;
    }

     

    5.类式继承模式--临时构造函数

     通过断开父对象与子对象的原型之间的直接链接关系,从而解决了共享同一个原型带来的问题。

    function inherit(C, P) {
        var F = function () {};
        F.prototype = P.prototype;
        C.prototype = new F();
    }

    这种模式中,父构造函数添加到this中的任何成员都不会被继承。

     

    5.适用于项目中的最佳方法----圣杯模式

     

    function inherit(C, P) {
        var F = function () {};
        F.prototype = P.prototype;
        C.prototype = new F();
        C.uber = P.prototype;
        C.prototype.constructor = C;
    }

     

    var inherit = (function () {
        var F = function () {};
        return function (C, P) {
            F.prototype = P.prototype;
            C.prototype = new F();
            C.uber = P.prototype;
            C.prototype.constructor = C;
        }
    }());

     

    6.Klass

    var klass = function (Parent, props) {
        var Child, F, i;
        // 1.构造函数
        Child = function () {
            if (Child.uber && Child.uber.hasOwnProperty("__construct")) {
                Child.uber.__construct.apply(this, arguments);
            }
            if (Child.prototype.hasOwnProperty("__construct")) {
                Child.prototype.__construct.apply(this, arguments);
            }
        };
        // 2.继承
        Parent = Parent || Object;
    Klass | 129
        F = function () {};
        F.prototype = Parent.prototype;
        Child.prototype = new F();
        Child.uber = Parent.prototype;
        Child.prototype.constructor = Child;
        // 3.添加方法
        for (i in props) {
            if (props.hasOwnProperty(i)) {
                Child.prototype[i] = props[i];
            }
        }
        // return the "class"
        return Child;
    };

    7.原型继承

     

    方式1:自身属性和构造函数原型的属性都将被继承

    // 父构造函数 
    function Person() {
        // an "own" property
        this.name = "Adam";
    }
    // 添加到原型的属性

    Person.prototype.getName = function () {
        return this.name;
    };
    // 创建一个新的person类对象

    var papa = new Person();
    // 继承

    var kid = object(papa);
    // 测试自身属性和原型
    kid.getName(); // "Adam

     

    方式2:仅继承现有构造函数的原型对象

    // 父构造函数
    function Person() {
        // an "own" property
        this.name = "Adam";
    }
    // 添加到原型的属性

    Person.prototype.getName = function () {
        return this.name;
    };
    // 继承
    var kid = object(Person.prototype);
    typeof kid.getName; // "function", because it was in the prototype
    typeof kid.name; // "undefined", because only the prototype was inherited

     

    8.通过复制属性实现继承

    function extend(parent, child) {
        var i;
        child = child || {};
        for (i in parent) {
            if (parent.hasOwnProperty(i)) {
                child[i] = parent[i];
            }
        }
        return child;
    }

     

    //浅复制

    var dad = {
        counts: [1, 2, 3],
        reads: {paper: true}
    };
    var kid = extend(dad);
    kid.counts.push(4);
    dad.counts.toString(); // "1,2,3,4"
    dad.reads === kid.reads; // true

     

    //深复制

    function extendDeep(parent, child) {
        var i,
            toStr = Object.prototype.toString,
            astr = "[object Array]";
        child = child || {};
        for (i in parent) {
            if (parent.hasOwnProperty(i)) {
                if (typeof parent[i] === "object") {
                    child[i] = (toStr.call(parent[i]) === astr) ? [] : {};
                    extendDeep(parent[i], child[i]);
                } else {
                    child[i] = parent[i];
                }
            }
        }
        return child;
    }

     

    var dad = {
        counts: [1, 2, 3],
        reads: {paper: true}
    };
    var kid = extendDeep(dad);
    kid.counts.push(4);
    kid.counts.toString(); // "1,2,3,4"
    dad.counts.toString(); // "1,2,3"
    dad.reads === kid.reads; // false
    kid.reads.paper = false;

    5.

    六、设计模式

    1.单例模式

    var Universe;
    (function () {
    var instance;
    Universe = function Universe() {
    if (instance) {
    return instance;
    }
    instance = this;
    // all the functionality
    this.start_time = 0;
    this.bang = "Big";
    };
    }());

     

    2.

     
    7.类的几种写法

     

        //最近实践

           var Parent = function () {
                this.name = name || 'Adam';
            }

            Parent.prototype = {
                say: function () {
                    alert("111");
                },
                hello: function () {
                    alert("hello");
                }
            };

     

     

    1)构造函数法
    /*
     * Person类:定义一个人,有个属性name,和一个getName方法 
     * @param {String} name 
     
    */
    function Person(name) { 
        this.name = name; 
        this.getName = function() { 
            return this.name; 
        } 
    }  

    var p1 = new Person("Jack"); 
    var p2 = new Person("Tom"); 
    console.log(p1 instanceof Person);//true 
    console.log(p2 instanceof Person);//true 
    这种方式的优点是:可以根据参数来构造不同的对象实例 ,缺点是构造时每个实例对象都会生成getName方法版本,造成了内存的浪费 。

     2、原型方式
      var Person = function (name) {
                Person.prototype.name = name
                Person.prototype.getName = function () { return this.name; }
            }

            var p1 = new Person("111");
            var p2 = new Person("222");
            alert(p1.getName()); //222 
            alert(p2.getName()); //222 
     

    可以看出输出的都是222,原型方式的缺点就是不能通过参数来构造对象实例 (一般每个对象的属性是不相同的) ,优点是所有对象实例都共享getName方法(相对于构造函数方式),没有造成内存浪费 。 

     

    3、构造函数+原型
            var Person = function (name) {
                this.name = name;

                if (Person._init == undefined) {
                    alert("我只执行一次!");
                    Person.prototype.getName = function () {
                        return this.name;
                    }
                    Person._init = 1;
                }
            }

            var p1 = new Person("Andy"); //第一次new会弹出'我只执行一次!' 
            var p2 = new Person("Lily"); //以后new的对象不会再执行了
            p1.getName(); //Andy
            p2.getName(); //Lily
    a 、可以通过传参构造对象实例
    b 、对象实例都共享同一份方法不造成内存浪费
    c 、代码风格也比较紧凑
    8、继承的几种写法

    最佳实践

    var inherit = (function () {
        var F = function () {};
        return function (C, P) {
            F.prototype = P.prototype;
            C.prototype = new F();
            C.uber = P.prototype;
            C.prototype.constructor = C;
        }
    }());

    拷贝组合继承

    function extend(subC, baseC) { 
        for (var ptototypeName in baseC.prototype) { 
            if (typeof(subC.prototype[ptototypeName]) === 'undefined') { 
                subC.prototype[ptototypeName] = baseC.prototype[ptototypeName]; //原型属性的拷贝 
            } 
        } 
        subC.prototype.constructor = subC; //增强 

    var BaseClass = function() { 
        this.className = "Base"; 
    }; 
    BaseClass.prototype = { 
        showName: function() { 
            alert(this.className); 
        } 
    }; 
    var SubClass = function() { 
        BaseClass.call(this); //只执行一次父类构造函数 
        this.classDesc = "SubClass"; 
    }; 
    SubClass.prototype = { 
        showDesc: function() { 
            alert(this.classDesc); 
        } 
    }; 
    extend(SubClass, BaseClass); //不破坏子类原型链的位置二
    /*!
     * jQuery源码分析-extend函数
     * jQuery版本:1.4.2
     * 
     * ----------------------------------------------------------
     * 函数介绍
     * jQuery.extend与jQuery.fn.extend指向同一个函数对象
     * jQuery.extend是jQuery的属性函数(静态方法)
     * jQuery.fn.extend是jQuery函数所构造对象的属性函数(对象方法)
     *
     * ----------------------------------------------------------
     * 使用说明
     * extend函数根据参数和调用者实现功能如下:
     * 1.对象合并:
     * 对象合并不区分调用者,jQuery.extend与jQuery.fn.extend完全一致
     * 也就是说对jQuery对象本身及jQuery所构造的对象没有影响
     * 对象合并根据参数区分,参数中必须包括两个或两个以上对象
     * 如:$.extend({Object}, {Object}) 或 $.extend({Boolean},{Object}, {Object})
     * 对象合并返回最终合并后的对象,支持深度拷贝
     * 
     * 2.为jQuery对象本身增加方法:
     * 这种方式从调用者和参数进行区分
     * 形式为 $.extend({Object})
     * 这种方式等同于 jQuery.{Fnction Name}
     * 
     * 3.原型继承:
     * 原型继承方式可以为jQuery所构造的对象增加方法
     * 这种方式也通过调用者和参数进行区分
     * 形式为 $.fn.extend({Object})
     * 这种方式实际上是将{Object}追加到jQuery.prototype,实现原型继承
     * 
     * ----------------------------------------------------------
     * 
     
    */
     
    // jQuery.fn = jQuery.prototype
    //
     jQuery.fn.extend = jQuery.prototype.extend
    jQuery.extend = jQuery.fn.extend = function(){

        //目标对象
        var target = arguments[0] || {},    
        
        //循环变量,它会在循环时指向需要复制的第一个对象的位置,默认为1
        //如果需要进行深度复制,则它指向的位置为2
        i = 1,    
        
        //实参长度
        length = arguments.length,    
        
        //是否进行深度拷贝
        //深度拷贝情况下,会对对象更深层次的属性对象进行合并和覆盖
        deep = false,    
        
        //用于在复制时记录参数对象
        options,    
        
        //用于在复制时记录对象属性名
        name,    
        
        //用于在复制时记录目标对象的属性值
        src,    
        
        //用于在复制时记录参数对象的属性值
        copy;
        
        //只有当第一个实参为true时,即需要进行深度拷贝时,执行以下分支
        if (typeof target === "boolean") {
            //deep = true,进行深度拷贝
            deep = target;
            
            //进行深度拷贝时目标对象为第二个实参,如果没有则默认为空对象
            target = arguments[1] || {};
            
            //因为有了deep深度复制参数,因此i指向的位置为第二个参数
            i = 2;
        }
        
        //当目标对象不是一个Object且不是一个Function时(函数也是对象,因此使用jQuery.isFunction进行检查)
        if (typeof target !== "object" && !jQuery.isFunction(target)) {
            
            //设置目标为空对象
            target = {};
        }
        
        //如果当前参数中只包含一个{Object}
        //如 $.extend({Object}) 或 $.extend({Boolean}, {Object})
        //则将该对象中的属性拷贝到当前jQuery对象或实例中
        //此情况下deep深度复制仍然有效
        if (length === i) {
            
            //target = this;这句代码是整个extend函数的核心
            //在这里目标对象被更改,这里的this指向调用者
            //在 $.extend()方式中表示jQuery对象本身
            //在 $.fn.extend()方式中表示jQuery函数所构造的对象(即jQuery类的实例)
            target = this;
            
            //自减1,便于在后面的拷贝循环中,可以指向需要复制的对象
            --i;
        }
        
        //循环实参,循环从第1个参数开始,如果是深度复制,则从第2个参数开始
        for (; i < length; i++) {
            
            //当前参数不为null,undefined,0,false,空字符串时
            //options表示当前参数对象
            if ((options = arguments[i]) != null) {
                
                //遍历当前参数对象的属性,属性名记录到name
                for (name in options) {
                    
                    //src用于记录目标对象中的当前属性值
                    src = target[name];
                    
                    //copy用于记录参数对象中的当前属性值
                    copy = options[name];
                    
                    //存在目标对象本身的引用,构成死循环,结束此次遍历
                    if (target === copy) {
                        continue;
                    }
                    
                    //如果需要进行深度拷贝,且copy类型为对象或数组
                    if (deep && copy && (jQuery.isPlainObject(copy) || jQuery.isArray(copy))) {
                    
                        //如果src类型为对象或数组,则clone记录src
                        //否则colne记录与copy类型一致的空值(空数组或空对象)
                        var clone = src && (jQuery.isPlainObject(src) || jQuery.isArray(src)) ? src : jQuery.isArray(copy) ? [] : {};
                        
                        //对copy迭代深度复制
                        target[name] = jQuery.extend(deep, clone, copy);
                        
                        //如果不需要进行深度拷贝
                    } else if (copy !== undefined) {
                        
                        //直接将copy复制给目标对象
                        target[name] = copy;
                    }
                }
            }
        }
        
        //返回处理后的目标对象
        return target;
    };


    /**
     * jQuery框架本身对extend函数的使用非常频繁
     * 典型示例为jQuery.ajax
     * 
     
    */

    //使用extend对jQuery对象本身进行扩展,只给了一个参数对象
    //
    该对象中的属性将被追加到jQuery对象中
    jQuery.extend({
     
        //jQuery.ajax
        //$.ajax
     
        //这里的origSettings参数是自定义的ajax配置
        //jQuery对象本身有一个ajaxSettings属性,是默认的ajax配置
        ajax: function(origSettings){ 
     
            //这里使用extend对ajax配置项进行合并
            //第一个参数表示进行深度拷贝
            //首先将第3个参数jQuery.ajaxSettings(即jQuery默认ajax配置)复制到第2个参数(一个空对象)
            //然后将第4个参数(自定义配置)复制到配置对象(覆盖默认配置)
            //这里的s就得到了最终的ajax配置项
            var s = jQuery.extend(true, {}, jQuery.ajaxSettings, origSettings);
      
            //其它相关代码...(省略)
        }
    }); 

    附录:

    Object类型

    Object类型用于创建自定义对象(实例),

    var cat= new Object();//推荐
    cat.name="sunny";
    cat.legs=
    4;

    Object类型的属性和方法如下:

    1. 构造函数:Object()
    2. hasOwnProperty(PropertyName):检查给的属性是否在当前的对象实例中,注:PropertyName必须以字符串给定
    3. isPrototypeOf(object):检查传递的对象,是否是另一个对象的原型。注:这里牵扯到原型和原型链,所以以后具体在讲,目前大家先知道有这么个方法
    4. propertyIsEnumerable(PropertyName):检查给定的属性是否能用for-in 语句来枚举。注:PropertyName必须以字符串给定
    5. toLocaleString():返回的字符串与执行环境的地区对应
    6. toString():返回字符串
    7. valueOf():返回对象的字符串、数值或布尔值表示
      
      
      复制代码
      var cat={
             name:"sunny",
             legs:4
      };
      
      alert('cat.hasOwnProperty("name"):'+cat.hasOwnProperty("name")+"\r\n"+
      'cat.hasOwnProperty("age"):'+cat.hasOwnProperty("age")+"\r\n"+
      'cat.propertyIsEnumerable("name"):'+cat.propertyIsEnumerable("name")+"\r\n"+
      'cat.toLocaleString():'+cat.toLocaleString()+"\r\n"+
      'cat.toString():'+cat.toString()+"\r\n"+
      'cat.toLocaleString():'+cat.toLocaleString()+"\r\n"+
      'cat.valueOf():'+cat.valueOf());

    对象属性的访问方法

         1. 点表示法  cat.name

         2. 方括号表示法:cat["name"]

          注1:方括号访问的优点是:

     A. 可以通过变量来访问属性    

    var  pName="name";
    alert(cat[pName]);

    B. 如果属性名中包含会导致语法错误的字符,或者属性名使用的是关键字或保留字,也可以用方括号表示法。

      cat["lovely brother"]="Tom"; 属性名中包含空格所以不能使用点表示法访问它

    注2:访问属性推荐使用点表示法,除非没办法用点表示法的时候选择用方括号访问

  • 相关阅读:
    多个自定义覆盖物注册点击事件,点击某个覆盖物后获得它的坐标
    C# 文件操作(全部) 追加、拷贝、删除、移动文件、创建目录 修改文件名、文件夹名
    如何添加EXEStealth 2.5x 壳
    PACS系统简易
    好用的后端模版
    E信通项目总结[转]
    平台型产品的设计思路[转]
    baidu思维脑图在线编辑器
    Web 前端攻防(2014版)-baidu ux前端研发部
    访谈标叔:给新人设计师的建议【转】
  • 原文地址:https://www.cnblogs.com/aaa6818162/p/2646359.html
Copyright © 2020-2023  润新知