前言: javascript 项目中原生态的语法用得比较少了,都是基于jQuery开发,但在移动项目中还是比较麻烦的。想整理个简单点的框架。这篇文章是基于 javascript dom 高级程序设计这本书来讨论的,这本书在框架开发方面还是比较好的。javascript 框架能够便于利用,最好能像C# Java 这类面向对象语言来组织代码和复用功能模块,因此这里说说javascript面向对象的一些开发方式。例如命名空间,对象,对象的继承等等。
(function () { //命名空间 if (!window.TScript) { window['TScript'] = {} } function $() { var elements = new Array(); for (var i = 0; i <= arguments.length; i++) { var element = arguments[i]; if (typeof element == 'string') { element = document.getElementById(element); } if (arguments.length == 1) { return element; } elements.push(element); } return elements; }; window['TScript']['$'] = $; )();
访问的时候就可以直接使用 TScript.$('id')。获取javascript对象了,这样TScript实际上就是一个命名空间。但是是否会觉得 TScript.$ 这样每次都加个TScript太罗嗦,可以这样:
(function($){ // $("id") })(TScript.$);
这样通过立即执行函数来简化操作,就像通常开发jQuery 插件一样,(function($){ //采用jQuery对象 })(jQuery);
这里在网上收集到两种命名空间的方式,实际上是构建一个函数,来注册命名空间可以复用,比较方便。
1. YUI的。
//YUI命名空间的实现方法 var YAHOO = window.YAHOO || {}; YAHOO.namespace = function(ns) { if (!ns || !ns.length) { return null; } var levels = ns.split("."); var nsobj = YAHOO; //如果申请的命名空间是在YAHOO下的,则必须忽略它,否则就成了YAHOO.YAHOO了 for (var i=(levels[0] == "YAHOO") ? 1 : 0; i<levels.length; ++i) { //如果当前命名空间下不存在,则新建一个关联数组。 nsobj[levels[i]] = nsobj[levels[i]] || {}; nsobj = nsobj[levels[i]]; } //返回所申请命名空间的一个引用; return nsobj; };2. 不知名的。主要是可以做成com.oschina.* 这种java包风格的。
Namespace = new Object(); Namespace.register = function (namespace) { var nsArray = namespace.split('.'); var sEval = ""; var sNs = ""; for (var i = 0; i < nsArray.length; i++) { if (i != 0) { sNs += "."; } sNs += nsArray[i]; sEval += "if(typeof(" + sNs + ")=='undefined')" + sNs + "=new Object();"; } if (sEval != "") { eval(sEval); } };
前面提到javascript里的一切都是对象,其实这里说对象是构建一个类似java 的构造函数:
function Apple(color) { this.color = color; } var apple = new Apple("red");这里总结一下比较常用的对象继承方式,在js里说继承主要是共用一些数据,减少内存。通常采用原型来实现propertype。例如:
function Fruit() { } Fruit.prototype.des = "水果"; function Apple(area) { this.area = area; } var F = function () { }; //这里采用空对象做中介,实现继承 F.prototype = Fruit.prototype; Apple.prototype = new F(); Apple.prototype.constructor=Apple
这里为什么用空对象做中介,因为如果直接Apple.prototype=Fruit.prototype。这样它们共用的是同一份数据,如果对Apple.prototype的修改会反映到Fruit上去。
YUI做了一个封装,类似命名空间一样:
function extend(Child, Parent) { var F = function () { }; F.prototype = Parent.prototype; Child.prototype = new F(); Child.prototype.constructor = Child; Child.uber = Parent.prototype; //上级父对象的引用 }还有一种jquery的拷贝赋值的方式继承:
//jquery 拷贝继承,将父对象的所有属性拷贝赋值给子对象 function deepCopy(p, c) { var c = c || {}; for (var i in p) { if (typeof p[i] === 'object') { //针对属性是对象的需要递归拷贝属性,深拷贝 c[i] = (p[i].constructor === Array) ? [] : {}; deepCopy(p[i], c[i]); } else { c[i] = p[i]; } } return c; } var Apple = deepCopy(Fruit);
可以一句话来说明下:this关键字引用的是包含它的函数作为某个对象的方法被调用时的那个对象。
我们知道在js脚本里面,所有的成员,包括变量,函数都是windows是对象的成员。那么在下面的例子中:
value = "window"; function testThis() { this.value = "testThis"; } testThis(); alert(value);// testThis;这里函数直接调用,那么调用函数的对象是window ,因此函数内的this指的是window。
那么下面:
value = "window"; function testThis() { this.value = "testThis"; } var obj = new testThis(); alert(obj.value);//testThis alert(value);//window第一次弹出的是testThis,这是由于此时testThis函数作为对象来访问,那么函数内的this就表示实例化的这个obj对象,详相当于在函数内部将value覆盖了。而函数外部的value没有影响,仍然作为window的成员,所以第二次弹出window。