00 原型链 继承 设计模式

目录

1 原型链图

2 继承

3 设计模式

1 单例模式

2  惰性单例

3 静态变量

4  适配器模式

5 观察者模式

7 组合模式 看笔记49

8 策略模式

9 命令模式

10 迭代器模式

11 委托模式 请求委托:

12 事件委托


 1 原型链图

instanceof

该关键字用于判定某一个对象是否是某一个构造函数的实例, 原理是:在对象的原型链上查找构造函数的原型

hasOwnProperty:

该方法检测某个对象身上是否包含了指定的属性

内置构造函数

String Number Boolean 是该类型的对应包装类型

Object Array Function RegExp Error Date

函数名.length 得到的是 形参的个数

arguments.length 得到的是 实参的个数

2 继承

1 构造函数式继承  在子构造函数中 调用父构造函数 可以继承父元素的实例属性,不能继承父原型上的属性方法

function Student(name, age, sex, cls) {
    // 构造函数式继承,两种写法
    // Teacher.apply(this, [name, age, sex])
    Teacher.call(this, name, age, sex);
    // 重写属性
    this.cls = cls;
}

2 类式继承:(原型式继承)将子原型对象指向父实例对象,缺点是:不能继承父实例属性;多执行实例化一次父构造函数;子原型对象被污染;constructor指向父构造函数

function Teacher(name, age, sex) {
    this.name = name;
    this.age = age;
    this.sex = sex;
}

function Student(name, age, sex, cls) {
    this.name = name;
    this.age = age;
    this.sex = sex;
}

 // 类式继承
Student.prototype = new Teacher();

3 组合式继承   1 和 2 结合起来

function Teacher(name, age, sex) {
    this.name = name;
    this.age = age;
    this.sex = sex;
}

function Student(name, age, sex, cls) {
    // 构造函数式继承
    Teacher.call(this, name, age, sex);
    // 添加属性
    this.cls = cls;
}
   //类式继承
Student.prototype = new Teacher();

4 寄生式继承 定义寄生类 1:将寄生类的原型指向父原型 2将子原型指向寄生类实例  3更改constructor

function inherite(child, parent) {
    // 定义寄生类
    function F() {
        // 纠正构造函数指向问题
        this.constructor = child;
    }
    // 让寄生类的原型式父类的原型
    F.prototype = parent.prototype;
    // 让子类的原型指向寄生类的原型对象
    // 通过实例化寄生类,代替了实例化父类
    child.prototype = new F();
    // 纠正子类的原型
    // child.prototype.constructor = child;
    // 返回子类
    return child;
}

5 寄生式组合继承  4 和 1结合起来

/***
 * 组合式继承
 *  综合运用构造函数式继承以及寄生式继承
 *  完美的解决了对父类的构造函数以及原型的复用问题。
 *  是目前为止最完美的继承方式了
 * ***/ 
// 学生类
function Student(name, age, sex, cls) {
    // 构造函数式
    Teacher.call(this, name, age, sex);
    // 重写属性
    this.cls = cls;
}
// 子类寄生父类
inherite(Student, Teacher);

3 设计模式

1 单例模式

定义:是能被实例化一次的类或者对象(只能存在一个)

作用:管理命名空间,管理数据,方法的存储

应用:一些代码库中命名空间就是通过单例模式实现的

// 单例模式
        var single = (function() {
            function Demo1(name, age) {
                this.name = name;
                this.age = age;
            }
            
            return function() {
                var instance = new Demo1('小花', 18);
                return instance;
            }
        })();
        //不管输不输出 当函数声明的时候 instance已经被赋值了
        console.log(single());

2  惰性单例

定义:延迟单例类的实例化时间

作用:如果单例类实例化开销很大,页面加载时候,有很多业务逻辑需要执行,并不需要这个单例类,此时我们可以推迟这个单例类的实例化时间

//惰性单例
        var Single1 = (function() {
            function Demo2(name, age) {
                this.name = name;
                this.age = age;
            }
            var instance;
            return function(name, age) {
                if (instance) {
                    return instance;
                } else {
                    return instance = new Demo2(name, age);;
                }
            }
        })();
        var ss = Single1('大明', 20);

3 静态变量

定义: 一旦被定义,只能被读取,无法被修改

我们实现的静态变量有个局限性:只能定义值类型的数据

// 定义闭包
    var Conf = (function() {
        // 定义对象
        var obj = {
            msg: 'hello',
            num: 100,
            title: 'nihao',
            size: {
                width: 100,
                height: 200
            }
        }

        // 定义接口函数 
            // 只定义取值函数 不要定义赋值函数
        return function(key) {
            return obj[key];
        }
    })()


    // 查看数据
    console.log(Conf('msg'));
    console.log(Conf('num'));
    // 改变内部应用类型数据值
    Conf('size').width = 1000;
// 访问引用类型
    console.log(Conf('size').width);

4  适配器模式

// 适配代码库 将代码改为jquery实现
    var Ickt = {
        bindEvent: function(dom, type, fn) {
            $(dom).on(type, fn);
        },
        css: function(dom, key, value) {
            $(dom).css(key, value);
        },
        getStyle: function(dom, key) {
            return $(dom).css(key);
        }
    }


    // 绑定事件
    Ickt.bindEvent(btn, 'click', function() {
        // 改变box的样式
        Ickt.css(box, 'color', 'red');
        // 切换显隐
        Ickt.css(box, 'display', Ickt.getStyle(box, 'display') === 'none' ? 'block' : 'none');
    })

5 观察者模式

定义:观察者模式,又叫发布订阅者模式,又叫消息系统,又叫消息机制,又叫自定义事件,解决主体与观察者之间的耦合问题。

on 用来注册消息 第一个参数表示消息的名称,第二个参数表示回调函数

trigger 用来触发消息,第一个参数表示消息的名,从第二个参数开始表示传递数据

off 用来移除消息的方法。

once 单次订阅方法。

var Observer = (function() {
            _data = {};//存储数据对象

            return {
                on: function(name, fn) {
                    _data[name] ? _data[name].push(fn) : _data[name] = [fn];
                },
                trigger: function(name) {
                    var arg = Array.prototype.slice.call(arguments, 1);
                    if (_data[name]) {
                        for (var i = 0; i < _data[name].length; i++) {
                            _data[name][i](arg);
                        }
                    }
                },
                off: function(name, fn) {
                    if (!name) {
                        _data = {};
                    } else if (!fn) {
                        _data[name] = [];
                    } else {
                        for (var i = 0; i < _data[name].length; i++) {
                            if (_data[name][i] === fn) {
                                _data[name].splice(i, 1);
                            }
                        }
                    }
                },
                once: function(name, fn) {
                    function callback(arg) {
                        Observer.off(name, callback);
                        fn.apply(null, arg);
                    }
                    Observer.on(name, callback);
                }
            }
        })();

7 组合模式 看笔记49

8 策略模式

定义:将一组算法封装起来,使其彼此之间可以相互替换,封装的算法具有独立性,不会随着客户端的变换而变化。行为型设计模式。

// 封装策略对象
    var strategy = (function() {
        // 存储数据的对象
        var _method = {
            username: function(val) {
                if (!/^\w{4,12}$/.test(val)) {
                    return '用户名是4-12位数字字母下划线组合';
                }  
                return '恭喜,用户名可以使用';
            },
            // 验证密码的策略
            password: function(val) {
                // 判断
                if (!/^\w{4,8}$/.test(val)) {
                    return '密码是4-8位数字字母下划线组合'
                }
                return '恭喜,该密码可以使用';
            }
        };

        // 返回接口对象
        return {
            // 使用策略方法
            use: function(name, str) {
                return _method[name](str)
            },
            // 添加策略方法
            add: function(name, fn) {
                _method[name] = fn;
            }
        }
    })()

 // 添加另一种用户名验证
     strategy.add('checkNickName', function(val) {
         if (!/^[a-zA-Z][0-9]{4,8}$/.test(val)) {
             return '用户名是以字母开头后面是4-8位数字';
         }
         return '恭喜, 该用户名可以使用';
     }) 

     // 使用
     var result = strategy.use('checkNickName', 'w123456');
     console.log(333, result);
 // 验证密码
     var result = strategy.use('password', wwwwwwwwwww);
     console.log(result);

9 命令模式

定义:将请求与实现解耦并封装成独立的对象,从而使不同的请求对客户端实现的参数化。

行为型设计模式,将执行的命令封装,解决命令的发起者与命令的执行者之间的耦合

例子:

 // 获取画布
    var canvas = document.getElementById('myCanvas');
    // 获取画笔
    var ctx = canvas.getContext('2d');
    
    // 定义命令对象
    var commond = (function() {
        // 定义存储数据对象
        var _C = {
            // 绘制描边圆
            strokeCirle: function(x, y, r, color) {
                ctx.beginPath();
                ctx.arc(x, y, r, 0, Math.PI * 2);
                ctx.closePath();
                ctx.strokeStyle = color;
                ctx.stroke();
            },
            // 填充圆
            fillCirle: function(x, y, r, color) {
                ctx.beginPath();
                ctx.arc(x, y, r, 0, Math.PI * 2);
                ctx.closePath();
                ctx.fillStyle = color;
                ctx.fill();
            },
            // 绘制矩形
            drawRect: function(x, y, w, h, color) {
                // 判断是否传递color
                if (color) {
                    ctx.fillStyle = color;
                }
                ctx.fillRect(x, y, w, h);
            }

        };

        // 返回接口对象
        return {
            exec: function(name) {
                // 获取剩余参数语法
                var arg = Array.prototype.slice.call(arguments, 1);
                // 执行方法
                _C[name] && _C[name].apply(_C, arg);
            }
        }
    })()

    // 绘制描边圆
    commond.exec('strokeCirle', 200, 200, 100, 'orange');
    // 绘制填充圆
    commond.exec('fillCirle', 200, 200, 100, 'orange');
    // 绘制矩形
    commond.exec('drawRect', 300, 300, 100, 100, 'blue');

10 迭代器模式

定义:在不暴露对象内部结构的同时,可以顺序的访问聚合对象内部的元素。

行为型设计模式

// 封装迭代器类
    function Iterator(select) {
        // 接收数据
        this.select = select;
        // 获取元素
        this.elements = document.querySelectorAll(select);
        // 索引值
        this.index = 0;
    }

    // 添加方法
    Iterator.prototype = {
        // 补回constructor
        constructor: Iterator,
        // 获取当前元素
        getCurrentElement: function() {
            return this.elements[this.index];
        },
        // 获取上一个元素
        prev: function() {
            // 改变索引值
            this.index--;
            // 做边界限制
            if (this.index < 0) {
                throw new Error('前面没有元素了');
            }

            // 返回元素
            return this.getCurrentElement();
        },
        // 获取下一个元素
        next: function() {
            // 改变索引值
            this.index++;
            // 做判断
            if (this.index > this.elements.length - 1) {
                throw new Error('已经是最后一个了')
            }
            // 返回元素
            return this.getCurrentElement();
        },
        // 获取第一个元素的方法
        first: function() {
            return this.getCurrentElement();
        },
        // 获取最后一个元素的方法
        last: function() {
            // 改变索引值
            this.index = this.elements.length - 1;
            // 获取元素
            return this.getCurrentElement();
        }
    }
    var iterator = new Iterator('li');
    var li1 = iterator.getCurrentElement();
    var li2 = iterator.first()
    var li3 = iterator.next();
    var li4 = iterator.last()

11 委托模式 请求委托:

多个对象接收并处理同一请求,他们将请求委托给另一个对象统一处理请求。

解决请求与委托者之间的耦合

被委托者接收到请求分发给委托者去处理

// 数据分发
    $.get('/data/all.json', function(res) {
        tools.renderHeader(res.data.header);
        tools.renderBody(res.data.body);
        tools.renderFooter(res.data.footer);
    })


    // 封装一个工具方法
    var tools = {
        renderHeader: function(html) {
            $('#header').html(html);
        },
        renderBody: function(html) {
            $('#body').html(html);
        },
        renderFooter: function(html) {
            $('#footer').html(html);
        }
    }

12 事件委托

事件委托:将所有元素的事件绑定委托给同一个父元素,根据事件冒泡捕获机制,可以在父元素绑定事件中获取的触发事件的这个元素,根据这个元素具有的某类特征(例如元素名称,元素id,元素类,元素属性等等)做不同的处理,实现事件从父元素到被委托的元素传递。其特点:

减少事件数量

预言未来元素,新增的元素也可以绑定事件

避免内存外泄:通常创建一个对象需要占用一些内存,这类占用是有意义的;有时候一些已             经被删除数据还占用着内存,这部分内存对我们来说是没用的,就是外泄内存

//list是父元素 里面有p和h1,给他们注册点击时 背景色改变事件
list.onclick = function(e) {
        // 获取触发事件的元素
        var target = e.target;
        // 判断
        if (target.tagName === 'P') {
            // 如果是p改变背景颜色为orange
            target.style.backgroundColor = 'orange';
        } else if (target.tagName === 'H1') {
            // 如果是h1改变背景颜色为yellowgreen
            target.style.backgroundColor = 'yellowgreen';
        }
    }   

jQuery中的事件委托  

on方法和delegate方法都可以实现事件委托,当事件触发的时候 父元素身上的事件不会执行 而是指定的元素执行,也不需要通过事件对象判断是否是触发事件的元素 这一点明显优于Javascript

    // jquery中的事件委托 通过on方法
    $('#list').on('click', 'li', function() {
        console.log(this);
    })

    // 使用更具有语义化的方法 delegate
    $('#list').delegate('li', 'click', function() {
        console.log(this);
    })

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值