search

Home  >  Q&A  >  body text

javascript - 一段Js继承里面的代码不是很看得懂,请教下。

var arr = [];
    var slice = arr.slice;
    function create() {
        if( arguments.length == 0 || arguments.length > 2 ) throw '参数错误';
        //此处两个属性一个是被继承的类,一个为原型方法
        var parent = null;
        var properties = slice.call(arguments);
        //如果第一个参数为类(function),那么就将之取出
        if( typeof properties[0] === 'function' )
            parent = properties.shift();
            properties = properties[0];

        //新建类,这个类最好会被返回,构造函数入口为initialize原型方法
        function klass() {
            this.initialize.apply(this, arguments);
        }

        //为其指定父类,没有就为空
        klass.superclass = parent;
        //其子类集合(require情况下不一定准确)
        klass.subclasses = [];
        //如果存在父类就需要继承
        if( parent ) {
            //新建一个空类用以继承,其存在的意义是不希望构造函数被执行
            //比如 klass.prototype = new parent;就会执行其initialize方法
            var subclass = function() {
            };
            subclass.prototype = parent.prototype;
            klass.prototype = new subclass();
            parent.subclasses.push(klass);
        }
        var ancestor = klass.superclass && klass.superclass.prototype;
        //遍历对象(其实此处这样做意义不大,我们可以强制最多给两个参数)
        //注意,此处为一个难点,需要谨慎,进入addMethods

        for( var k in properties ) {
            var value = properties[k];
            console.log(ancestor,value);
            //console.log(k)
            //满足条件就重写
            if( ancestor && typeof value == 'function' ) {
                var argslist = /^\s*function\s*\(([^\(\)]*?)\)\s*?\{/i.exec(value.toString())[1].replace(/\s/i, '').split(',');
                //只有在第一个参数为$super情况下才需要处理(是否具有重复方法需要用户自己决定)
                if( argslist[0] === '$super' && ancestor[k] ) {
                    value = (function(methodName, fn) {
                        //console.log(fn)
                        return function() {
                            var scope = this;
                            var args = [function() {
                                return ancestor[methodName].apply(scope, arguments);
                            }];
                            return fn.apply(this, args.concat(slice.call(arguments)));
                        };
                    })(k, value);  //1
                }
            }
            klass.prototype[k] = value;
        }
        if( !klass.prototype.initialize )
            klass.prototype.initialize = function() {
            };
        klass.prototype.constructor = klass;
        console.log(new klass())
        return klass;
    }

以上是继承代码
下面是使用代码

 var AbstractView = create({
        initialize:function(opts) {
            opts = opts || {};
            this.wrapper = opts.wrapper || $('body');
            //事件集合
            this.events = {};
            this.isCreate = false;
        },
        on:function(type, fn) {
            if( !this.events[type] ) this.events[type] = [];
            this.events[type].push(fn);
        },
        trigger:function(type) {
            if( !this.events[type] ) return;
            for( var i = 0, len = this.events[type].length; i < len; i++ ) {
                this.events[type][i].call(this)
            }
        },
        createHtml:function() {
            throw '必须重写';
        },
        create:function() {
            this.root = $(this.createHtml());
            this.wrapper.append(this.root);
            this.trigger('onCreate');
            this.isCreate = true;
        },
        show:function() {
            if( !this.isCreate ) this.create();
            this.root.show();
            this.trigger('onShow');
        },
        hide:function() {
            this.root.hide();
        }
    });



   var Alert = create(AbstractView, {
        createHtml:function() {
            return '<p class="alert">这里是alert框</p>';
        }
    });
    var v1 = new Alert();
    v1.show();
    var AlertTitle = create(Alert, {
        initialize:function($super) {
            this.title = '';
            $super();
        },
        createHtml:function() {
            return '<p class="alert"><h2>' + this.title + '</h2>这里是带标题alert框</p>';
        },
        setTitle:function(title) {
            this.title = title;
            this.root.find('h2').html(title)
        }
    });
    var v2 = new AlertTitle();
    v2.show();
    v2.setTitle('我是标题');
    var AlertTitleButton = create(AlertTitle, {
        initialize:function($super) {
            this.title = '';
            $super();
            this.on('onShow', function() {
                var bt = $('<input type="button" value="点击我" />');
                bt.click($.proxy(function() {
                    alert(this.title);
                }, this));
                this.root.append(bt)
            });
        }
    });
    var v3 = new AlertTitleButton();
    v3.show();
    v3.setTitle('我是标题和按钮的alert');

-----分隔线啦啦啦-----

value = (function(methodName, fn) {
    //console.log(fn)
    return function() {
        var scope = this;
        var args = [function() {
            return ancestor[methodName].apply(scope, arguments);
        }];
        return fn.apply(this, args.concat(slice.call(arguments)));
               };
   })(k, value);  
                    
                  

在上面这个代码段里面
fn.apply(this, args.concat(slice.call(arguments)))这句话的意思是说执行fn函数,但是argument明明是空值 为什么还要去合并数组args.concat(slice.call(arguments)),而且上面那整段代码都不是很理解,请大大指教,thx :)

PHP中文网PHP中文网2817 days ago193

reply all(1)I'll reply

  • PHPz

    PHPz2017-04-10 17:36:38

    arguments是实际调用value函数的参数列表,怎么会是空值?

    reply
    0
  • Cancelreply