javascript初学记4 -- 对象

由于js的对象已经有很多解释,决定读一段关于制作js class库的源码,以加深印象。

(function(){
    'use strict';

    // saving constants
    var VERSION = '1.0';
    var ORIGINAL = window.Class;

    // creating global class variable
    var Class = window.Class = function (obj) {
        obj = obj || {};
        // call initialize if given
        var constructor = function () {
            return (this.initialize) ? this.initialize.apply(this, arguments) : self;
        };
        // adds implement to the class itself
        if(obj.implement) {
            var self = window === this ? copy(constructor.prototype) : this; // copy是Object.create
            var imp = obj.implement; // 抽取obj.implement,其是一个Class对象数组
            remove(obj, 'implement'); // 抽取完后删除obj的implement属性
            obj = extend(obj, implement(imp)); // 保存数组中所有Class对象属性
        }
        // assign prototypes
        constructor.prototype = copy(obj); // 复制obj,并将prototype链相连
        // assign correct constructor for correct instanceof comparison
        constructor.constructor = constructor; // 将constructor绑定为自己
        // save initial object as parent so it can be called by this.parent
        constructor._parent = copy(obj); // 将parent设定为obj的copy
        // attaching class properties to constructor
        for(var i = 0, values = ['extend', 'implement', 'getOptions', 'setOptions']; i < values.length; i++) {
            constructor[values[i]] = Class[values[i]]; // 将Class的原生方法拓展到constructor上
        }

        return constructor; // 返回这个constructor,即返回了一个新的类
    };

    // adding class method extend
    Class.extend = function (obj) {
        var self = this; // 拓展方法
        // check if implement is passed through extend
        if(obj.implement) {
            this.prototype = extend(this.prototype, implement(obj.implement)); // 拓展prototype链,如果有implement状态时
            // remove implement from obj
            remove(obj, 'implement'); // 消除obj的implement属性,防止后面拓展的时候加上
        }
        // check if we should invoke parent when its called within a method
        for(var key in obj) { // 判断该obj是否是函数且当中含有parent字符,即判断是否为一个类
            obj[key] = typeof obj[key] === 'function' && /parent/.test(obj[key].toString()) ? (function (method, name) {
                return function () {
                    this.parent = self._parent[name]; // 监测到含有this.parent()等字样时,就会将this.parent指向原本的parent
                    return method.apply(this, arguments);
                }; //有则返回一个能够执行该方法,并且将parent规定为当前对象的_parent
            })(obj[key], key) : obj[key] // 要么返回传入的参数后生成的类,要么返回原本属性
        }
        // assign new parent
        this._parent = extend(this._parent, obj, true); // 拓展自身父类
        // assign new prototype
        this.prototype = extend(this.prototype, obj); // 拓展自身方法
        // return the class if its assigned
        return this;
    };

    // adding class method implement
    Class.implement = function (array) {
        return this.prototype = extend(this.prototype, implement(array)); // 拓展方法
    };

    // gets options from constructor
    Class.getOptions = function () {
        return this.prototype.options || {}; // 返回prototype中options属性的值
    };

    // sets options for constructor
    Class.setOptions = function (options) {
        return this.prototype.options = extend(this.prototype.options, options); // 设定prototype中options的值
    };

    // preventing conflicts
    Class.noConflict = function () {
        // reassign original Class obj to window
        window.Class = ORIGINAL;
        return Class; // noConflict
    };

    // returns current running version
    Class.version = VERSION;

    // helper for assigning methods to a new prototype
    function copy(obj) {
        var F = function () {};
            F.prototype = obj.prototype || obj;
        return new F();
    }

    // insures the removal of a given method name
    function remove(obj , name, safe){
        // if save is active we need to copy all attributes over.
        if(safe) {
            var safeObj = {};
            for(var key in obj) {
                if(key !== name) safeObj[key] = obj[key]; // safe代表返回新对象
            }
        } else {
            delete obj[name]; // 直接删除
        }
        return safeObj || obj; // 请选择你的结局
    }

    // helper for merging two object with each other
    function extend(oldObj, newObj, preserve) {
        // failsave if something goes wrong
        if(!oldObj || !newObj) return oldObj || newObj || {};

        // make sure we work with copies
        oldObj = copy(oldObj);  // 确保操纵的是一个copy,不影响原本的对象,并返回新对象
        newObj = copy(newObj);

        for(var key in newObj) {
            if(Object.prototype.toString.call(newObj[key]) === '[object Object]') {
                extend(oldObj[key], newObj[key]); // 深度遍历
            } else {
                // if preserve is set to true oldObj will not be overwritten by newObj if
                // oldObj has already a method key
                oldObj[key] = (preserve && oldObj[key]) ? oldObj[key] : newObj[key]; // 有preserve则不替换原本具有的属性
            }
        }

        return oldObj; // 返回旧对象
    }

    // helper for implementing other classes or objects
    function implement(array) {
        var collection = {};

        for(var i = 0; i < array.length; i++) {
            // check if a class is implemented and save its prototype
            if(typeof(array[i]) === 'function') array[i] = array[i].prototype; // 保存原型

            // safely remove initialize
            var safe = remove(array[i], 'initialize', true); // 去掉initialize属性

            // we use implement again if array has the apropriate methiod, otherwise we extend
            if(safe.implement) {
                collection = implement(safe.implement); // 如果还有implement属性,继续处理
            } else {
                collection = extend(collection, safe); // 没有则将属性拓展
            }
        }

        return collection; //返回新的包含所有方法的对象
    }

})();

由于注释已经标在上面,后面只挑几个关键点

  function copy(obj) {
        var F = function () {};
            F.prototype = obj.prototype || obj;
        return new F();
    }

这个是典型的原型继承方式,通过创造一个prototype连向指定对象的空对象,这样即避免重新实例化属性,也能取到这个属性,Object.create

prototype放方法,实例化属性,非常清晰。

 function extend(oldObj, newObj, preserve) {
        // failsave if something goes wrong
        if(!oldObj || !newObj) return oldObj || newObj || {};

        // make sure we work with copies
        oldObj = copy(oldObj);  // 确保操纵的是一个copy,不影响原本的对象,并返回新对象
        newObj = copy(newObj);

        for(var key in newObj) {
            if(Object.prototype.toString.call(newObj[key]) === '[object Object]') {
                extend(oldObj[key], newObj[key]); // 深度遍历
            } else {
                // if preserve is set to true oldObj will not be overwritten by newObj if
                // oldObj has already a method key
                oldObj[key] = (preserve && oldObj[key]) ? oldObj[key] : newObj[key]; // 有preserve则不替换原本具有的属性
            }
        }

        return oldObj; // 返回旧对象
    }

继承对象还有另一个方法,就是直接将属性遍历安放在上面,extend。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值