leadJS初构建

Posted lewo的博客

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了leadJS初构建相关的知识,希望对你有一定的参考价值。

目录:

1. 面向对象篇

2. 数据结构篇

3. 全局函数篇

4. APICloud篇

 

1. 面向对象篇

  JS原本无法进行程序员世界的面向对象编程,故此对JS封装成一种具有面向对象编程能力的JS.

/**
 * ----------------------------------------------------------
 * ----------------------    面向对象篇    ------------------
 * ----------------------------------------------------------
 */

var 
    
    /**
     * 
     * @Title Base
     *
     * @Description 实现js面向对象编程的基类(所有类都是继承于该类)
     * 
     */

    Base = {

        /**
         *
         * @Title is
         *
         * @Description 判断 类与类之间 以及 对象与类之间 关系的基础方法
         * 情况一(类与类之间):
         * 1. 父类.is(子类) -> false
         * 2. 子类.is(父类) -> true
         * 情况二(对象与类之间):
         * 1. 父类对象.is(子类) -> false
         * 2. 子类对象.is(父类) -> true
         *
         * @param {object} type 类名称
         *
         * @return {boolean}
         * 
         */

        is : function(type){
            var 
                self = this;

                /**
                 * 调用对象.is(指定对象)
                 * 判断 调用对象 是否 包含 指定对象(属性)
                 * 或者也可以这样说
                 * 判断 指定对象 是否 包含于 调用对象(属性)
                 */
                
                while ( self ) {

                    if ( self == type ) return true;

                    self = self.__type__; // __type__ : (1)Class-引用其父类 (2)New-实例所属的类

                }

                return false;

        }
    }

    ,

    /**
     * 
     * @Title Class
     *
     * @Description 创建类的函数,用于声明类及继承关系,BaseClass.create.call(this, ..., ...); // 调用基类的构造函数
     *
     * @param {Object} DefineClass 定义类的对象
     *
     * @param {Object} BaseClass 需要继承的类(省略默认为 Base)
     *
     * @return {Class} 创建类 
     * 
     */
    
    Class = function(DefineClass, BaseClass){

        // 默认继承 Base 基类
        
        var 
            parent = BaseClass || Base

            ,

            // 创建类的临时函数壳 _class
            
            _class = function(){

                // __type__ 属性 : 引用其父类
                this.__type__ = parent;

                // 复制类的全部定义到当前创建的类
                for( var member in DefineClass ) {

                    this[member] = DefineClass[member];

                }

            }

            ;

            _class.prototype = parent;

            return new _class();

    }

    ,

    /**
     * 
     * @Title New
     *
     * @Description 创建对象的函数,用于任意类的对象创建
     *
     * @param {Object} ClassName 类
     *
     * @param {Object} ClassParam 类参数(构造函数需要的参数)
     *
     * @return {Object} 创建对象
     * 
     */
    
    New = function(ClassName, ClassParam){

        // 创建对象的临时函数壳 _new
        
        var 

            _new = function(){

                // __type__ 属性 : 据此可以访问到对象所属的类
                this.__type__ = ClassName;

                if(typeof ClassName.create === \'function\'){

                    // 约定 所有 类的构造函数: create ! 
                    ClassName.create.apply(this, ClassParam);

                }

            }

            ;

            _new.prototype = ClassName;

            return new _new();

    }

    ;

编写一个例子来说明:

// 定义一个类名为 ClassName 的类
        var ClassName = Class({
            // create 为 构造函数
            create : function(){
                /**
                 * 注意:成员变量没有私有(private)、保护(protected)、公开(public)
                 * 私有 - 用 \'_\' 开头定义变量
                 * 保护 - 不存在
                 * 公开 - 不用 \'_\' 开头定义变量 
                 */
                // 列举一些成员变量
                this._privateVar = \'privateValue\'; // 私有变量
                this.publicVar = \'publicValue\'; // 公开变量
            },
            // 列举一些成员方法
            _privateFun : function(){ // 私有方法
                // ...
            },
            publicFun : function(){ // 公开方法
                // ...
            }
        });

非常好,程序非常符合我们面向对象编写形式,但是你会问我:继承呢?

// 建立一个类为 ClassName2 继承 ClassName
var ClassName2 = Class({},ClassName);
// 注意:私有变量、方法也会被继承到子类。因为JS原本就没有变量的私有、保护、公开之说

如果你看不懂这些代码,那么你应该多去复习复习面向对象的知识,再回来瞧瞧。好像还忘记告诉你了,你用Class()建立的类默认会继承Base类。

2. 数据结构篇

接下来介绍介绍几种简单的数据结构 http://www.cnblogs.com/jiangxiaobo/p/5619638.html

/**
 * 队列类
 */
var Queue = Class({
    create : function(){
        var 
            self = this
            ,
            argsLen = arguments.length
            ,
            i = 0
            ;

            self.queue = [];

            for(;i<argsLen;i++){
                self.queue.push(arguments[i]);
            }
            self.queue.reverse();
    },
    enter : function(){
        var 
            self = this
            ,
            argsLen = arguments.length
            ,
            i = 0
            ;

            self.queue.reverse();

            for(;i<argsLen;i++){
                self.queue.push(arguments[i]);
            }

            self.queue.reverse();
    },
    out : function(popNum){
        var 
            self = this
            ,
            popNum = !popNum?0:(popNum-1)
            ,
            i = 0
            ;

            for(;i<popNum;i++){
                self.queue.pop();
            }

            return self.queue.pop();
    }
});
/**
 * 堆栈类
 */
var Stack = Class({
    create : function(){
        var 
            self = this
            ,
            argsLen = arguments.length
            ,
            i = 0
            ;

            self.stack = [];

            for(;i<argsLen;i++){
                self.stack.push(arguments[i]);
            }
    },
    enter : function(){
        var 
            self = this
            ,
            argsLen = arguments.length
            ,
            i = 0
            ;

            for(;i<argsLen;i++){
                self.stack.push(arguments[i]);
            }
    },
    out : function(popNum){
        var 
            self = this
            ,
            popNum = !popNum?0:(popNum-1)
            ,
            i = 0
            ;

            for(;i<popNum;i++){
                self.stack.pop();
            }

            return self.stack.pop();
    }
});
/**
 * 延时类
 */
var Deferred = Class({
    create : function(){
        var self = this;
        // 调用父类的构造函数,将所有的参数传给父类
        Queue.create.apply(this,arguments);
    },
    resolve : function(){
        var self = this,then = self.out();
        if(then) then.apply(null,arguments);
    },
    done : function(callback){
        var self = this;
        if(typeof callback === \'function\'){
            self.enter(callback);
        }
    }
},Queue);

这些可能你认为会没有用处,数据结构我个人认为是一种思想,按照这种思想去设计程序,想必会少出一些bug吧。可能队列和堆栈都能明白,但是延时类拿来干嘛?

好,你设想一下,在移动开发中,程序几乎都是异步进行,意思就是在一段程序执行之后可能会等一段时间才能执行下一段程序,那么这空闲的时间内有可能也有其他程序在执行,所以JS程序常常会使用回调来解决这个问题。回调可以使程序按照我们的思路一直回调下去,但是由于回调的层次越深,那么阅读代码就越困难,而且代码也会非常臃肿,不协调,于是有一个方法可以解决这个问题就是这个延时类,具体分析代码如下:

// 有一个延时任务
setTimeout(function(){
    alert(1);
    // 想在 alert(1) 执行之后在执行 alert(2)
    // 于是就会出现 定义一个函数 aa
    // 然后在这里调用
    aa();
});
// alert(2);
function aa(){
    alert(2);
}
//实例化传统类
var dfd = New(Deferred);
//延时任务
setTimeout(function(){
    alert(1);
    dfd.resolve(\'哈哈\');
},1000);
dfd.done(function(str){
    alert(str);
    dfd.resolve();
});
dfd.done(function(){
    alert(3);
});

对比以上两个程序会发现下面的程序更为优雅易懂。

3. 全局函数篇

/**
 * ----------------------------------------------------------
 * ----------------------    全局函数篇    ------------------
 * ----------------------------------------------------------
 */

var 
    
    /**
     * 
     * @Title Extend
     *
     * @Description 对象合并
     *
     * @param  {Object}       des            源对象
     *
     * @param  {Array|Object} src            对象数组
     *
     * @param  {Boolean}      override       是否重写源对象
     *
     * @return {object}                      返回源对象的引用
     * 
     */

    Extend = function(des, src, override){

        var 

            i        = 0

            ,

            l        = 0

            ,

            k        = null

            ,

            argsLen  = arguments.length

            ;

            if ( argsLen === 0 ) {

                return {};

            } else if ( argsLen === 1 ) {

                return arguments[0];

            }

            if ( src instanceof Array ) {

                for ( i = 0, l = src.length; i < l; i++ ) {

                    Extend(des, src[i], override);

                }

            } else {

                for ( k in src ) {

                    if ( override || !(k in des) ) {

                        des[k] = src[k];
                    }

                }
                
            }

            return des;

    }

    ,

    /**
     * 
     * @Title Each
     *
     * @Description 迭代器
     *
     * @param  {Array}      obj      待迭代对象数组
     *
     * @param  {Function}   callback 迭代回调方法
     *
     * @param  {Object}     context  环境变量,用作回调函数中this的对象
     *
     * @param  {*}          arg      传入迭代回调函数的参数
     *
     * @throws {jsonstringify} 缺少参数
     * 
     */
    
    Each = function(obj, callback, context, arg){

        var 

            k     = null

            ,

            argsLen = arguments.length

            ;

            if ( argsLen === 0 || argsLen === 1 ) {

                throw new Error(\'缺少参数\');

            }

            if ( typeof callback !== \'function\' ) {

                throw new Error(\'参数类型必须为function\');

            }

            for ( k in obj ) {

                callback.call( context||null, k, obj[k], arg );

            }

    }

    ,

    /**
     * 
     * @Title VarToBool
     *
     * @Description 将变量值转换为布尔值。规定 \'\'|null|undefined|NaN|0|{}|[] 都为false,其他变量均为true
     *
     * @param  {Object} data 需要判断的变量
     *
     * @return {Boolean}
     * 
     */
    
    VarToBool = function(data){

        var

            _t       = typeof data

            ,

            hasProp  = false

            ,

            prop     = null

            ;

            if ( _t === \'object\' ) {

                for ( prop in data ) {

                    hasProp = true; // 证明该对象存在属性
                    break;

                }

                return hasProp;

            }

            return !!data;

    }

    ,

    /**
     * 
     * @Title GetType
     *
     * @Description 得到 变量 类型 字符串。
     *
     * @param  {*} data 需要得到类型的变量
     *
     * @return {String}
     * 
     * \'abc\'              return \'string\'
     * true               return \'boolean\'
     * 123,NaN,Infinity   return \'number\'
     * []                 return \'array\'
     * {}                 return \'object\'
     * function(){}       return \'function\'
     * new Date           return \'date\'
     * new RegExp         return \'regexp\'
     * Math               return \'math\'
     * null               return \'null\'
     * undefined          return \'undefined\'
     * 
     */
    
    GetType = function(data){

        var 

            _t = \'\'

            ;

            return ( (_t = typeof data) == \'object\' ? data == null && \'null\' || Object.prototype.toString.call(data).slice(8,-1):_t ).toLowerCase();

    }

    ,

    /**
     * 
     * @Title InArray
     *
     * @Description 检查值是否在数组中。
     *
     * @param {*}     val 值
     *
     * @param {Array} arr 数组
     *
     * @return {Boolean} 在数组中返回true,否则返回false
     *
     * @throws {jsonstringify} 数组不存在
     * 
     */
    
    InArray = function(val,arr){

        var 

            i   = 0

            ,

            l   = 0

            ;

            if ( GetType(arr) !== \'array\' ){

                throw new Error(\'数组不存在\');

            }

            for ( i = 0, l = arr.length; i < l; i++ ) {

                if ( arr[i] === val ) {

                    return true;

                }

            }

            return false;

    }

    ;
/**
 * ----------------------------------------------------------
 * ----------------------    DOM操作篇    ------------------
 * ----------------------------------------------------------
 */

var 

    Dom = (function(){

        var dom = function(selector){

            return new dom.fn.init(selector);

        };

        dom.fn = dom.prototype = {

            length : 0,

            selector : \'\',

            nodelist : [],

            init : function(selector){

                var self = this;

                if ( !selector ) { return self; }

                self.selector = selector;

                return self.makeArray(document.querySelectorAll(selector));

            },

            makeArray : function(nodelist){

                var self = this;

                self.nodelist = [];

                if ( !nodelist.length && nodelist.length != 0 ) {

                    // 证明是单个节点
                    self.nodelist.push(nodelist);

                } else if ( nodelist.length && nodelist.length != 0 ) {

                    // 证明是 nodelist
                    for ( var i=0,l=nodelist.length; i<l; i++ ) {

                        self.nodelist.push(nodelist[i]);

                    }

                }

                // else 证明是 []
                
                // else 节点数组为空 或者 也不是单个节点
                
                self.length = self.nodelist.length;

                return self;

            }

        };

        dom.fn.init.prototype = dom.fn;

        // dom 静态扩展 方法
        dom.extend = function(src, override){

            Extend(dom, src, override);

        };

        // dom 动态扩展 方法
        dom.fn.extend = function(src, override){

            Extend(this, src, override);

        };

        dom.fn.each = function(callback,arg){

            Each(this.nodelist,callback,this,arg);

        };


        /**
         * 动态扩展 dom
         */
        dom.fn.extend({

            on : function(name, fn, useCapture){

                var self = this;

                useCapture = useCapture || false;

                self.each(function(index,node){

                    if ( node.addEventListener ) {

                        node.addEventListener(name, fn, useCapture);

                    }

                });

                return self;

            }

            ,

            off : function(name, fn, useCapture){

                var self = this;

                useCapture = useCapture || false;

                self.each(function(index,node){

                    if ( node.removeEventListener ) {

                        node.removeEventListener(name, fn, useCapture);

                    }

                });

                return self;

            }

            ,

            one : function(name, fn, useCapture){

                var self = this;

                useCapture = useCapture || false;

                self.each(function(index,node){

                    var _cb = function(){

                        if ( fn && typeof fn === \'function\' ) { fn(); }

                        if ( node.removeEventListener ) {

                            node.removeEventListener(name, _cb, useCapture);

                        }

                    };

                    if ( node.addEventListener ) {

                        node.addEventListener(name, _cb, useCapture);

                    }

                });

                return self;

            }

            ,

            find : function(selector){

                var self = this;

                if ( !selector ) {

                    return self.makeArray();

                } else {

                    return self.makeArray(self.nodelist[0].querySelectorAll(selector));

                }

            }

            ,

            eq : function(index){

                var self = this;

                if ( !index || index <= 0 ) {

                    return self.makeArray(self.nodelist[0]);

                } else if ( index >= self.length ) {

                    return self.makeArray(self.nodelist[self.length-1]);

                } else {

                    return self.makeArray(self.nodelist[index]);

                }

            }

            ,

            get : function(index){

                var self = this;

                if ( !index || index <= 0 ) {

                    return self.nodelist[0];

                } else if ( index >= self.length ) {

                    return self.nodelist[self.length-1];

                } else {

                    return self.nodelist[index];

                }

            }

            ,

            remove : function(){

                var self = this;

                self.each(function(index,node){

                    node.parentNode.removeChild(node);

                });

                return self;

            }

            ,

            attr : function(name, value){

                var self = this;

                if (arguments.length == 1) {

                    // 获取属性值
                    return self.nodelist[0].getAttribute(name);

                } else if(arguments.length == 2) {

                    // 设置属性值
                    self.each(function(index,node){

                        node.setAttribute(name, value);

                    });

                }

                return self;

            }

            ,

            removeAttr : function(name){

                var self = this;

                if ( !name ) {

                    return self;

                } else {

                    self.each(function(index,node){

                        node.removeAttribute(name);

                    });

                }

                return self;

            }

            ,

            hasClass : function(cls){

                var self = this;

                if (self.nodelist[0].className.indexOf(cls) > -1) {

                    return true;

                } else {

                    return false;

                }

            }

            ,

            addClass : function(cls){

                var self = this;

                self.each(function(index,node){

                    if (\'classList\' in node) {

                        node.classList.add(cls);

                    } else {

                        var preCls = node.className;

                        var newCls = preCls +\' \'+ cls;

                        node.className = newCls;

                    }

                });

                return self;

            }

            ,

            removeClass : function(cls){

                var self = this;

                self.each(function(index,node){

                    if (\'classList\' in node) {

                        node.classList.remove(cls);

                    } else {

                        var preCls = node.className;

                        var newCls = preCls.replace(cls, \'\');

                        node.className = newCls;

                    }

                });

                return self;

            }

            ,

            toggleClass : function(cls){

                var self = this;

                self.each(function(index,node){

                    if (\'classList\' in node) {

                        node.classList.toggle(cls);

                    } else {

                        if (node.className.indexOf(cls) > -1) {

                            var preCls = node.className;

                            var newCls = preCls.replace(cls, \'\');

                            node.className = newCls;

                        } else {

                            var preCls = node.className;

                            var newCls = preCls +\' \'+ cls;

                            node.className = newCls;

                        }

                    }

                });

                return self;

            }

            ,

            offset : function(){

                var self = this,sl = 0,st = 0,rect=null,node = self.nodelist[0];

                sl = Math.max(document.documentElement.scrollLeft, document.body.scrollLeft);

                st = Math.max(document.documentElement.scrollTop, document.body.scrollTop);

                rect = node.getBoundingClientRect();

                return {

                    l: rect.left + sl,

                    t: rect.top + st,

                    w: node.offsetWidth,

                    h: node.offsetHeight

                };

            }

            ,

            data : function(name, value){

                var self = this;

                if (arguments.length == 1) {

                    // 获取属性值
                    return self.nodelist[0].dataset[name];

                } else if(arguments.length == 2) {

                    // 设置属性值
                    self.each(function(index,node){

                        node.dataset[name]=value;

                    });

                }

                return self;

            }

        });


        return dom;

    })();

 

以上是关于leadJS初构建的主要内容,如果未能解决你的问题,请参考以下文章

vue3.0 Composition API 上手初体验 构建 vue 基础代码

vs code初体验

c#代码片段快速构建代码

使用 NodeJS 和 JSDOM/jQuery 从代码片段构建 PHP 页面

#构建之法之初体验

我可以在片段中构建操作栏吗?