JavaScript_patterns

一些问题的记录

如何添加事件

// the interface
    var utils = {
        addListener: null,
        removeListener: null
    };
    // the implementation
    if (typeof window.addEventListener === 'function') {
        utils.addListener = function (el, type, fn) {
            el.addEventListener(type, fn, false);
        };
        utils.removeListener = function (el, type, fn) {
            el.removeEventListener(type, fn, false);
        };
    } else if (typeof document.attachEvent === 'function') { // IE
        utils.addListener = function (el, type, fn) {
            el.attachEvent('on' + type, fn);
        };
        utils.removeListener = function (el, type, fn) {
            el.detachEvent('on' + type, fn);
        };
    } else {
        utils.addListener = function (el, type, fn) {
            el['on' + type] = fn;
        };
        utils.removeListener = function (el, type, fn) {
            el['on' + type] = null;
        };
    }

call和apply

// define a function
    var sayHi = function (who) {
        console.log("Hello" + (who ? ", " + who : "") + "!");
    };
    // invoke a function
    sayHi(); // "Hello"
    sayHi('world'); // "Hello, world!"
    // apply a function
    sayHi.apply(null, ["hello"]); // "Hello, hello!"
    sayHi.apply(null); // "Hello!"
    // call a function
    sayHi.call(null,'hello'); // "Hello, hello!"
    sayHi.call(null); // "Hello!"

Curry

function add(x) {
        return function (y) {
            return x + y;
        };
    }
    console.log(add(3)(4)); // 7
    console.log(add(3)); // function
    // create and store a new function
    var add2000 = add(2000);
    console.log(add2000(10)); // 2010

通用化Curry

function curry(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);
        }
    }
    function add(x, y) {
        return x + y;
    }
    var add = curry(add, 5);
    console.log(add(4)); // 9

用闭包实现只get

var my;
    (function () {
        var name = "my";
        my = {
            getName: function () {
                return name;
            }
        };
    }());
    console.log(my.getName());
    var your = (function () {
        var name = "your";
        return {
            getName: function () {
                return name;
            }
        };
    }());
    console.log(your.getName());

暴露方法

Util.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;
                };
        // revealing public API
        return {
            isArray: isArray,
            indexOf: inArray
        };
    }());

类式继承#1->指向父函数的实例

function Parent(name) {
        this.name = name || 'parent';
        this.age = 10;
    }
    Parent.prototype.say = function () {
        return this.name;
    };

    function Child(name) {
        this.name = name;
    }

    function inherit(C, P) {
        /**
         *该继承模式同时继承了两个对象的属性,即添加到this的属性以及原型属性。
         *在绝大多数的时候,并不需要这些自身的属性。
         */
        C.prototype = new P();
    }
    inherit(Child, Parent);

    var child = new Child('child');
    console.log(child.name);    //child
    console.log(child.__proto__.name);    //parent
    console.log(child.age);    //10

类式继承#2-> 借用构造函数

function Parent(name) {
        this.name = name || 'parent';
    }
    Parent.prototype.say = function () {
        return this.name;
    };

    function Child(name) {
        /**
         *可以获得父对象自身成员的真实副本,不会存在覆盖
         * 无法从原型中继承任何东西 ,它并不会为每个实例重新创建原型。
         */
        Parent.apply(this, arguments);
    }

    var child = new Child('child');
    console.log(child.name);    //child
    console.log(child.say());   //Uncaught TypeError: undefined is not a function

类式继承#3->借用并设置原型

function Parent(name) {
        this.name = name || 'parent';
    }
    Parent.prototype.say = function () {
        return this.name;
    };

    function Child(name) {
        //借用构造函数
        Parent.apply(this, arguments);
    }
    //子构造函数的原型使其指向父构造函数创建的新实例
    Child.prototype = new Parent();

    var child = new Child('child');
    console.log(child.say());    //child

类式继承#4->共享原型

function Parent(name) {
        this.name = name || 'parent';
    }
    Parent.prototype.say = function () {
        return this.name;
    };

    function Child(name) {
        this.name = name;
    }
    /**
     * 所以的对象实例实际上都共享了同一个原型。但是,这同时也是一个缺点,
     * 继承链下方的某处存在一个子对象修改了原型,它将会影响到所有的父对象和祖先对象。
     */
    function inherit(C, P) {
        C.prototype = P.prototype;
    }
    inherit(Child, Parent);
    var parent = new Parent();
    var child = new Child('child');
    console.log(child.say());    //child
    console.log(parent.say());    //parent

    Child.prototype.say = function () {
        return this.name+' changed!';
    };
    console.log(child.say());    //child changed!
    console.log(parent.say());    //parent changed!

类式继承#5->临时构造函数

 function Parent(name) {
        this.name = name || 'parent';
    }
    Parent.prototype.say = function () {
        return this.name;
    };

    function Child(name) {}
    /**
     * 这里的子对象仅仅继承了父对象的原型中的属性,原型正是放置可复用功能的位置。
     * 父构造函数添加到this中的任何成员都不会被继承。
     */
    function inherit(C, P) {
        var F = function () {};
        F.prototype = P.prototype;
        C.prototype = new F();
    }
    inherit(Child, Parent);

    var child = new Child('child');
    console.log(child.name);    //undefined
    console.log(child.say);    //function () {...}

现代继承方式#1->原型继承

function object(o) {
        function F() {};
        F.prototype = o;
        return new F();
    }

    function Person() {
        this.name = 'parent';
    }
    Person.prototype.getName = function () {
        return this.name;
    };

    var parent = new Person();
    var child = object(parent);
    console.log(child.getName());    //parent

现代继承方式#2->复制对象

//浅复制
    function extend(parent, child) {
        var i;
        child = child || {};
        for (i in parent) {
            if (parent.hasOwnProperty(i)) {
                child[i] = parent[i];
            }
        }
        return child;
    }
    //深度复制
    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 parent = {
        counts: [1, 2, 3],
        reads: {paper: true}
    };
    var child = extendDeep(parent);
    child.counts.push(4);
    console.log(child.counts.toString());    //1,2,3,4
    console.log(parent.counts.toString());    //1,2,3

现代继承方式#3->方法借用

只是方法借用而已用call或者apply去调用父类的方法

单例实现

function Singleton() {
        // the cached instance
        var instance = this;
        // proceed as normal
        this.name = 'Singleton';
        // rewrite the constructor
        Singleton = function () {
            return instance;
        };
    }
    var s1 = new Singleton();
    var s2 = new Singleton();
    console.log(s1===s2); //true
    console.log(s1.name); //Singleton

迭代器

var Iterator = function (arr) {
        return {
            index: -1,

            hasNext: function () {
                //console.log('index ' + this.index)
                return this.index < arr.length-1;
            },
            hasPrevious: function () {
                return this.index > 0;
            },

            current: function () {
                return arr[ this["index"] ];
            },

            next: function () {
                if (this.hasNext()) {
                    this.index = this.index + 1;
                    return this.current();
                }
                return false;
            }
        }
    };

    var arr = [1, 2, 3, 4, 5];
    var iterator = Iterator(arr);
    while (iterator.hasNext()) {
        console.log(iterator.next());
    }
原文地址:https://www.cnblogs.com/bq12345/p/3888583.html