• javascript OOP(下)(九)


    一、javascript模拟重载

    java中根据参数类型和数量的区别来实现重载,javascript弱类型,没有直接的机制实现重载,javascript中参数类型不确定和参数个数任意,通过判断实际传入的参数的个数来实现重载。

    <script>
    function Person() {
        var args = arguments;
        if (typeof args[0] === 'object' && args[0]) { //判断第一个参数是否为对象,进行相应操作。传参为空时typeof null也是object,所以要同时判断args[0]不为空
            if (args[0].name) {
                this.name = args[0].name;
            }
            if (args[0].age) {
                this.age = args[0].age;
            }
    
        } else {
            if (args[0]) {
                this.name = args[0];
            }
            if (args[1]) {
                this.age = args[1];
            }
        }
    }
    //toString继承自Object,一般的对象toString会显示"[object Object]",没有什么意义,所以可以重新一下,方便输出 Person.prototype.toString
    = function() { return 'name=' + this.name + ',age=' + this.age; } var bosn = new Person('Bosn', 27); bosn.toString(); //name=Bosn,age=27 var lxy = new Person({ name: 'lxy', age: 25 }); lxy.toString(); //name=lxy,age=25 </script>

    二、调用基类方法

    1、调用基类的方法进行初始化

    基类人Person

    学生Student

    初始化Student的时候,初始化了className后需要初始化Person部分,可以通过

    Person.call(this,name);调用基类的方法和属性。

    <script>
    function Person(name){
        this.name=name;
    }
    function Student(name,className){
        this.className=className;
        Person.call(this,name); //调用基类的构造器
    }
    
    var bosn=new Student('Bosn','Network064');
    console.log(bosn); 
    </script>

    输出时能够正确的被初始化。

    2、子类覆盖了基类的方法

    Student的init覆盖了Person的init,初始化Student时需要初始化Person,通过Person.prototype.init.apply(this,arguments);

    <script>
    Person.prototype.init=function(){
    
    };
    
    Student.prototype.init=function(){
        //do sth
        Person.prototype.init.apply(this,arguments);
    }
    </script>

    三、链式调用

     类似jquery选择器链式调用。

    关键要在ClassManager.prototype.addClass操作完成后return this

    <script>
    function ClassManager(){//构造器
    }
    
    ClassManager.prototype.addClass=function(str){ //在构造器上挂载一个方法,表示addClass
    console.log('Class:'+str+' added.');
    return this;// this总是指向ClassManager的实例,所以return就实现了链式调用
    }
    
    var manager=new ClassManager();
    manager.addClass('classA').addClass('classB').addClass('classC');
    //Class:classA added.
    //Class:classB added.
    //Class:classC added.
    
    </script>

    四、抽象类

     没有机制,可以进行模拟。主要是用throw new Error()

    <script>
    function DetectorBase(){
        throw new Error('Abstract class can not be invoked directly!');
        //在构造器里抛一个异常,防止抽象类被直接调用
    }
    DetectorBase.detect=function(){console.log('Detection starting...');}
    DetectorBase.stop=function(){console.log('Detector stopped.');}
    DetectorBase.init=function(){
        throw new Error('Error');
        //想要子类覆盖而不想被直接调用的方法,抛出异常
    }
    
    function LinkDetector(){}
    //通过Object.create实现继承
    LinkDetector.prototype=Object.create(DetectorBase.prototype);
    LinkDetector.prototype.constructor=LinkDetector;
    </script>

    五、definePrototype(ES5)

    <script>
    //ES5里面对于属性有一些getter setter方法,有一些标签
    //configurable:能否delete
    //enumberable:能否for in遍历
    //writable:能否读写属性
    //value:记录属性值,默认为undefine
    //控制属性的访问情况
    
    function Person(name){
        //name可遍历,不可读写,不可删除
        Object.defineProperty(this,'name',{value:name,enumerable:true});
    }
    //ARMS_NUM相当于定义了一个常量,可枚举,不可写,不可删除
    Object.defineProperty(Person,'ARMS_NUM',{value:2,enumerable:true});
    Object.seal(Person.prototype); //Person在初始化之后不想被扩展,不想被配置了,用seal方法
    Object.seal(Person);
    
    function Student(name,className){
        this.className=className;
        Person.call(this,name);
    }
    Student.prototype=Object.create(Person.prototype);
    Student.prototype.constructor=Student;
    </script>

    六、模块化

    模块化工具或者说类库有有seajs,requirejs等。

    模块化的一般形式是:一个定义了私有变量和函数的函数;利用闭包创建可以访问私有变量和函数的特权函数;最后返回这个特权函数,或者把它们保存到一个可访问到的地方。

    1、通过返回一个对象实现简单模块化

    <script>
    var moduleA;//只需要把最核心的东西moduleA放到全局作用域
    moduleA=function(){
        var prop=1;
        function func(){}
        return{ //func和prop不会被泄露到全局作用域
            func:func,
            prop:prop
        }
    }() //moduleA用立即执行的匿名函数
    </script>

    2、通过返回this的方法实现简单模块化

    通过new function(),通过设置this的值,我们知道通过new调用最后会返回this,除非你return的是一个对象。

    <script>
    //通过new默认返回this的方法
    va moduleA;
    moduleA=new function(){
        var prop=1;
        function func(){}
        this.func=func;
        this.prop=prop;
    }
    </script>

    3、模块化应用【update20170307】

    模块化可以摒弃全局变量的使用。促进了信息隐藏和其他优秀的设计实践。对于应用程序的封装,或者构造其他单例对象,模块模式非常有效。

    模块模式也可以用来产生安全的对象。

    例:构造一个用来产生序列号的对象。

    <script>
    var serial_maker=function(){
    /*返回一个用来产生唯一字符串的对象。
    唯一字符串由两部分组成:前缀+序列号。
    该对象包含一个设置前缀的方法,一个设置序列号的方法和一个产生唯一字符串的gensym方法。
    */
    var prefix='';
    var seq=0;
    return{
        set_prefix:function(p){
            prefix=String(p);
        },
        set_seq:function(s){
            seq=s;
        },
        gensym:function(){
            var result=prefix+seq;
            seq+=1;
            return result;
        }
    }
    };
    var seqer=serial_maker();
    seqer.set_prefix('Q');
    seqer.set_seq(1000);
    var unique;
    unique=seqer.gensym(); 
    console.log(unique);//unique是"Q1000"
    unique=seqer.gensym(); 
    console.log(unique);//unique是"Q1001"
    
    </script>

    seqer()的3个方法都没有用到this或者that,因此没有办法损害seqer。除非调用对应的方法,否则没法改变prefix或seq的值。

    seqer对象是可变的,所以它的方法可能会被替换掉,但替换后的方法依然不能访问私有变量。

    比如:

    seqer.gensym=function(){
        var result=prefix+seq;
            seq+=3;
            console.log(seq);
            return result;
    }

    就会报错,因为替换后的方法不能访问私有变量。

    seqer就是一组函数的集合,而且那些函数被授予特权,拥有使用或修改私有状态的能力。

    如果我们把seqer.gensym作为一个值传递给第三方函数,那个函数能用它产生唯一字符串,却不能通过修改它来改变prefix或seq的值。

    参考:

    js模块化历程

    http://www.cnblogs.com/lvdabao/p/js-modules-develop.html

    写了十年JS却不知道模块化为何物?

    https://blog.wilddog.com/?p=587

     深入浅出ES6(十三):类 Class

    http://www.infoq.com/cn/articles/es6-in-depth-classes/

    本文作者starof,因知识本身在变化,作者也在不断学习成长,文章内容也不定时更新,为避免误导读者,方便追根溯源,请诸位转载注明出处:http://www.cnblogs.com/starof/p/4904929.html有问题欢迎与我讨论,共同进步。

  • 相关阅读:
    php小结
    HTML-WEB前端-photoshop切图抠图详解
    JS面向对象的程序设计
    AJAX同步与异步的区别
    数据库的优化
    phpcms网站搬家 至 服务器 完整并且详细过程
    phpcms网页替换验证码功能 及 搜索功能
    用phpcms切换中英文网页的方法(不用解析二级域名)、phpcms完成pc和手机端切换(同一域名)
    JS常用屏蔽代码
    信息安全政策(隔离与监控)
  • 原文地址:https://www.cnblogs.com/starof/p/6264333.html
Copyright © 2020-2023  润新知