写一个js文件的loader

我印象中,js脚本文件的loader似乎有,但是完美的,完美到像php的include或者cSharp的using的,貌似没有。有些团队据说有,但是没有一个公认的好的方式,或者说没有一个团队愿意拿出来共享,我觉得这说明,他们的方法都存在问题:或者代码冗余,或者存在n多不确定性,或者只适用于他们自己的环境。 注意我说的是一个文件的loader,是通过script标记的src属性调用,而不是将js代码通过innerHTML写到一个div或者什么标签里。 为什么要写loader呢? 比如jq的冗长是我们经常诟病的一个问题。我在冒死写我自己的类库的一开始,我就确定了一个事情:分文件写。也就是,一个核心的、公共的类库是必需的,然后根据页面需要挂所需的js文件。我觉得这个出发点还是不错的。但是后来我意识到,比如在ui部分,tab标签、无缝滚动、图片轮显、ajax等等诸多部分分在不同的文件中,而往往首页里这些都要用得到,那么,script标记在页头最多时有10个上下。当然,如果你不在意还行。我觉得有点蠢。 jq的冗长是我不要的,script标记过多也不是我要的,所以,我需要一个loader。 但是我还没想好。 这里只做一个简单的实现,实现通过js添加一个script标记,并且确保这个标记引入的文件会被执行。 想到的方式有两种:通过dom添加和通过document.write直接写。 通过dom方式是最方便、简单,并且标准的方式。只要通过document.createElement创建一个script标记,并且按照html标准添加type和src属性,然后把这个标记添加到页面当中去就可以了。但是如我们所知,如果我们不把具体的js代码放到window.onload当中去的时候,js标记的位置是个很重要的问题。也就是说,你的类库文件必须在前,实例应用必须在其后,不但js是逐行的,ie中html也tmd的是逐行的。在添加js标记时,我选择将标记放到head中。并且,head是一个默认标记,就像document,无论你的html中是否有head代码,head标记都是存在的。所以无需判断head标记是否存在,直接用head.appendChild即可。需要注意的问题有二:1、head的获取,在ie下是需要使用getElementsByTagName(‘head’)[0]来获得,其他浏览器直接document.head即可得到。2、执行顺序ie有所不同。我的感觉:在ie下,ie会重新理解标记位置,按script标记在head中的顺序逐行执行引入的文件;而其他浏览器,是按照引入的时间来执行的,比较复合人类的思路。 通过document.write方式,更直接。我先说一下我最终没有采用dom方式的原因:文件加载完成的时间不确定。我幻想过,当我添加了一个新的script标记后,window.onload事件会再次触发一次。当然事实并不是这样。换句话说,我不知道js文件什么时候能够加载完。而当你document.write的时候,所写入的代码会成为html解析的一部分,所以浏览器会等待js文件加载完成以后再执行下面的解析。需要注意的问题:如果在script标记A中使用document.write写了一个script标记B,那么,标记B会紧跟在标记A之后,也就是说是在标记A的外部。所以,在标记A中不能使用动态写入的标记B中的代码,需要在标记A之外重新写script标记来执行标记B中的代码。 最后附上muselite库里暂时新加的window.using代码,这段代码还没有想好怎么用,仅仅完成了文章开头所说的,动态添加的功能而已。 window.MUSELITE_DEFAULT_FOLDER = ‘Scripts’; (function(w, arr){ w._using = function(app){ if(!app || typeof app != ‘string’) return; var i = 0, len = arr.length; for(; i < len; i++) arr[i] === null ? document.write(app) : document.write(arr[i]); } w.using = function(){ if(arguments.length < 1) return; var i ...Read More

Actionscript中MovieClip,Sprite,Shape的区别

在AS变成中,经常会遇到MovieClip,Sprite和Shape。 其中MovieClip最熟悉了,影片剪辑,在flash中就可以创建。MovieClip含有一个时间轴。 而Sprite就是一个没有时间轴的MovieClip,由于这一属性,使得Sprite特别适合作为容器装在不会变化的图片,文本以及图形。 Shape也有graphics属性,可以作图,但是Shape不是一个容器,使得shape不可以addChild,同样的,Shape也不支持鼠标事件。 虽然这么说容易理解,但是实际上,MovieClip是Sprite的子类,所以准确的说,MovieClip是“有时间轴”的Sprite,才是最准确的。

关于JavaScript中的this

只要牢牢记住一点:this指向函数的调用者。 最典型的例子: var obj = { a:1, fn:function(){ alert(this.a); } } obj.fn(); 此时,fn的调用者是obj,所以fn中的this指向obj,所以显示为obj.a。再看: var a = 2; var obj = { a:1, fn:function(){ alert(this.a); } } obj.fn.call(window); 第一行的a,就是等于2的那个,是属于window域的,call会改变调用者,在这里,obj.fn将调用者更改为window,所以this指向window,所以将显示为window.a。 var a = 2; var fn = function(){ alert(this.a); } fn(); 这里,fn也是window域的,所以,其实是在执行window.fn(),那么,调用者为window,所以显示window.a。 下面说一下js创建对象的方式,常用的,如下面这个样子: function o(){ }; o.prototype = { value : 1, fn : function(){ alert(this.value); } ...Read More

JavaScript中Function作为类构造函数时的返回值

function a(){ return this.test(); }; a.prototype.test = function(){ return { a:”12345″ }} var obj = new a(); alert(obj.test); 如果在函数a中不return这个对象,obj会不意外地继承test方法,也就是成为a.prototype的一个指针。但是如果return了,new出来的对象将断开与prototype的链接,变成了一个毫不相干的玩意。 请各位童鞋注意这个问题。 其实,js就不是我们通常所讲的面向对象语言,它没有类的概念。现在的所有的实现js的oo的写法,都是基于js的基于原型继承的面相对象的特性,按照一般概念上的类的写法仿制的。如果又按照一般概念上的类和对象的特点去理解使用它的话,掉到坑里是迟早的事情。 希望各位童鞋在学习js的时候,注意力要放在原型继承上,并在此基础上来考虑new的问题。

模拟私有属性的一个不成熟的办法

抛砖引玉,希望能得到更好的办法来模拟私有属性。

根据userAgent获取浏览器信息

我觉得,无论userAgent多复杂多麻烦,我还是更相信它。至少,世界上没有两个相同的userAgent。 另外,作为一个痴迷于js痴迷于前端的人,我无视360浏览器、遨游、世界之窗、搜狗等诸多产品,我觉得我一直坚持兼容IE6就已经很蛋疼了。 那么,首先,我们搜集一下各个主流浏览器当前版本的userAgent样本,以便做进一步的分析整理。 Chrome 9 Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US) AppleWebKit/534.11 (KHTML, like Gecko) Chrome/9.0.570.0 Safari/534.11 Opera 11 Opera/9.80 (Windows NT 6.1; U; Edition IBIS; zh-cn) Presto/2.7.62 Version/11.00 Safari 5 Mozilla/5.0 (Windows; U; Windows NT 6.1; zh-CN) AppleWebKit/533.19.4 (KHTML, like Gecko) Version/5.0.3 Safari/533.19.4 Firefox 3 Mozilla/5.0 (Windows; U; Windows NT 6.1; zh-CN; rv:1.9.2.13) ...Read More

javascript中的引用与闭包

javascript真是神奇的语言,实在是太灵活了。 javascript中的变量,大体分为两大种。 “直接量”和”引用量”,姑且这么称呼吧,肯定不标准。 :) “直接量”包括,number,string,boolean 除此之外,都是”引用量” 有很多JS的面试题,都在这里搞点花样。 var a=[1,2,3]; var b=a; a[0]=2; console.log(b[0]); 结果:2 深入的理解这段代码。 var a=[1,2,3]; var b=a; 看起来似乎是把数组赋值给a了,其实不然,应该是a引用了数组[1,2,3] , 可以这么理解。内存中存在了一个数组[1,2,3],而变量a其实只是保存了一个对数组[1,2,3]的引用罢了。 那么,b=a就好理解了,b只是复制了这种引用。 所以a[0]的重新赋值,会让b[0]也随着改变。 因为a和b本来就引用了同一个数组。 而如果是直接量的,就不会存在这样的情况。 var a=”hello”; var b=a; a=1; console.log(b); 结果:hello ——————————————————————————————————— 有的时候,需要复制而不是引用,就麻烦了。 var a={attr:1}; 如果需要复制一个a。。怎么办呢? function copy(o){ var obj={}; for(var i in o){ obj[i]=o[i]; } return obj; } 没错,生成一个对象,然后把被复制的对象的所有属性都拷贝一份到新的对象里。。 当然,如果你要拷贝一个数组,就要new一个Array,拷贝一个function,就要new一个Function, ————————————————————————————————————————————– 引用,各种引用,各种各种引用,JS就是由引用组成的。 ...Read More

仿cSharp的String.Format方法,在JavaScript中向String类型添加format方法

cSharp中的String.Format方法,是推荐的对字符串进行拼接方法。比如 string hrefFormat = “<a href=”\” target=”\”_blank\”">{1}</a>”; string hrefHtml = String.Format(hrefFormat, “http://xxx.com”, “链接一”); String.Format的第一个参数为格式化的字符串,后面参数为params不定个数、不定类型,根据索引对应标记{0},{1},{2}… 如果参数个数小于标记最大值或标记不以{0}为最小标记,即会抛出错误 当然,除此之外还有对特定数据类型的专用格式化功能。 当前在muselite库中,主要是采用类似cSharp的字符串格式化写法,实现字符串拼接的功能。代码如下: if (!String.prototype.format) String.prototype.format = function () { if (arguments.length == 0) return this; var _ = this, len = arguments.length, i = 0, regExp; for (; i < len; i++) { regExp = new RegExp(‘\\{‘ + i + ...Read More

Hello World!

This is MK’s kitchen.

关于arguments

今天在群里面,蚂蚁问了一些关于this和arguments的问题,把我所认识的arguments总结一下。 当函数内的执行域生成时,arguments对象就被创建了。 arguments对象由所在函数的CreateArgumentsObject方法创建。 这个方法生成了arguments对象,主要是一个list,包含了函数的实参。与函数的形参没有关系,使得不定参数个数的函数成为可能。 例如: function sum(){ var result=0; for(var i=0;i<arguments.length;i++){ result+=arguments[i]; } return result; } console.log(sum(1,2,3,4)); 结果是10 上文中用了arguments的一个属性length,这个属性的值等于实参的个数。 除此之外,arguments还有个重要的属性,callee arguments.callee指向函数本身 听起来似乎不好理解。 function ex(){ console.log(arguments.callee); } ex(); 结果: function ex(){ console.log(arguments.callee); } 说arguments.callee指向了函数本身。。 这一点很有用,特别在匿名函数的递归中。 var s=function(i){ if(i==1){ return 1; } return i*arguments.callee(i-1); } console.log(s(3)); 结果:6 arguments是一个对象,虽然它像一个数组一样,有length属性,也用数字做下标来表达成员。 有些人将这类的对象,称之为类数组。 function a(){ console.log(arguments instanceof Array); console.log(arguments instanceof Object); ...Read More