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; })();
原创文章请随便转载。愿和大家分享,并且一起进步。-- 江 coder