最近在看公司的一个框架,整个框架基本都是面向对象,让我对于javascript的强大之处感到兴奋,基本可以完全模拟其它语言的一些特性。
先来看看实现类的实现:
function ClassA(){
this._init.apply(this, arguments);
}
(function(){
this._init = function(p1, p2){//构造函数
this.a = p1;
this.b = p2;
};
this.f1 = function(){}//类方法
}).apply(ClassA.prototype);
改进一下为:
function __newClass(){
return function(){
this._init.apply(this, arguments);
};
}
function _class(className, classImp){
var clazz = __newClass();
window[className] = clazz;
classImp.apply(clazz.prototype);
}
基类构建完成后,就要实现继承,需要稍微修改一下_class这个类:
function _class(className, superClass, classImp){
var clazz = __newClass();
clazz.prototype = new superClass();
var _super = superClass.prototype;
window[className] = clazz;
classImp.apply(clazz.prototype, [_super]);//这样子类就可以引用父类的原型对象
}
_class(”ClassB”, ClassA, function(_super){
this._init = function(){
_super._init.call(this);//调用父类的构造函数
this._name = “ClassB”;
};
this.dispose = function(){
_super.dispose.apply(this);//调用父类的析构函数
}
});
有了这个基础的架子之后让类的继承变得简单,从而可以更方便地实现包,接口等特性。
1.阶乘(阶乘指从1乘以2乘以3乘以4一直乘到所要求的数)
function factorial(n){
return n?n*factorial(n-1):1;
}
一般不建议使用递归,另一种:
function factorial(n){
var k=1;
for(var i=1; i<=n; i++){
k = k*i;
}
return k;
}
2.排列数(从n个不同的元素中取m(m≤n)个元素的所有排列的个数,叫做从n个不同元素中取出m个元素的排列数,记为Anm)
A(n,m)=n*(n-1)*…..(n-m+1) —-> A(n,m)=n!/(n-m)!
function A(n, m){
return factorial(n)/factorial(m);
}
3.组合数(从n个不同的元素中取m(m≤n)个元素的所有组合的个数,叫做从n个不同元素中取出m个元素的组合数,记为Cnm )
C(n,m)=A(n,m)/m!=n!/(m!*(n-m)!) —-> C(n,m)=C(n,n-m)
function C(n, m){
return factorial(n)/(factorial(m)*factorial(n-m));
}
4.区间(区间是数集的一种表示形式,区间的表示形式与集合的表示形式相同)
function Between(a, b){
var r = [];
if(b==undefined){
b = a;
a = 0;
}
do{
r.push(a);
a+=1;
}while(a<=b);
return r;
}
4.斐波那契数列(斐波那契数列指的是这样一个数列:1、1、2、3、5、8、13、21、……这个数列从第三项开始,每一项都等于前两项之和。)
function fibonacci(n){
var i=1, s = 1, n1 = 1, n2 = 1;
for(;i<n;i++){
s = n1+n2;
n1 = n2;
n2 = s;
}
return n1;
}
5.素数/质数(只有1和它本身这两个因数的自然数叫做质数。)
function isPrime(n){
if(n<3)return true;
for(var i=2; i<=Math.sqrt(n); i++){
if(n%i == 0)return false;
}
return true;
}
还有一种方法是利用正则表达式的特性:
function isPrime(n){
var r = [];
while(r.length<n)r.push(’1′);
return !/^1?$|^(11+?)\1+$/.test(r.join(”));
}
rolandog在留言中说取得r,可以这样while(n){r[--n] = ‘1′;},可以提高一点性能。
数学在计算机编程中的应用无处不在,HTML5 Canvas的出现必将会掀起图形编程的一个新高潮!!
相关资源:http://rolandog.com/math-js/
JavaScript 是一种垃圾收集式语言,这就是说,内存是根据对象的创建分配给该对象的,并会在没有对该对象的引用时由浏览器收回。JavaScript 的垃圾收集机制本身并没有问题,但浏览器在为 DOM 对象分配和恢复内存的方式上却有些出入。
Internet Explorer 和 Mozilla Firefox 均使用引用计数来为 DOM 对象处理内存。在引用计数系统,每个所引用的对象都会保留一个计数,以获悉有多少对象正在引用它。如果计数为零,该对象就会被销毁,其占用的内存也会返回 给堆。虽然这种解决方案总的来说还算有效,但在循环引用方面却存在一些盲点。
内存泄露的模式大概有以下几种:
1.循环引用导致了内存泄漏,JavaScript 对象 obj 拥有到 DOM 对象的引用,表示为 DivElement。而 DOM 对象则有到此 JavaScript 对象的引用,由 expandoProperty 表示。可见,JavaScript 对象和 DOM 对象间就产生了一个循环引用。由于 DOM 对象是通过引用计数管理的,所以两个对象将都不能销毁。
obj=document.getElementById(”DivElement”);
document.getElementById(”DivElement”).expandoProperty=obj;
obj.bigString=new Array(1000).join(new Array(2000).join(”XXXXX”));
2.由外部函数调用引起的内存泄漏,通过调用外部函数 myFunction 创建循环引用。同样,JavaScript 对象和 DOM
对象间的循环引用也会导致内存泄漏。
function myFunction(element)
{
this.elementReference = element;
// This code forms a circular reference here
//by DOM–>JS–>DOM
element.expandoProperty = this;
}
function Leak() {
//This code will leak
new myFunction(document.getElementById(”myDiv”));
}
3.Javascript闭包引起的内存泄漏,闭包功能非常强大,原因是它们使内部函数在外部函数返回时也仍然可以保留对此外部函数的变量的访问。不幸的是,闭包非常易于隐藏 JavaScript 对象 和 DOM 对象间的循环引用。
function closureDemoParentFunction(paramA)
{
var a = paramA;
return function closureDemoInnerFunction (paramB)
{
alert( a +” “+ paramB);
};
};
var x = closureDemoParentFunction(”outer x”);
x(”inner x”);
Javascript内存泄漏工具:
1.Drip/sIEve
2. Javascript Leaks Detector
3. Leak Monitor
了解更多请阅读:
http://www.ibm.com/developerworks/cn/web/wa-memleak/
http://djjchobits.javaeye.com/blog/375465
ajax本身实际上是通过XMLHttpRequest对象来进行数据的交互,而浏览器出于安全考虑,不允许js代码进行跨域操作,所以就诞生了很多跨域的解决方案。当本域和子域间进行访问时最简单的就是设置document.domain,当不同域的访问,大概有下列方法:
1.web端代理的方式,即用户访问A网站时所产生的对B网站的跨域访问请求均提交到A网站的指定页面,由该页面代替用户页面完成交互,从而返回合适的结果。
2.iframe,解决方案就是用window.location对象的hash属性,利用JS改变hash值网页不会刷新,可以这样实现通过JS访问hash值来做到通信,大体就是AB网站各嵌入一个对方网站的iframe,然后通过连续不断的监听hash值的变化来进行通信。比如A网站通过改变B网站iframe的hash后,B网站监听到hash的变化后就进行处理,这种方式需要开发者可以控制两个网站的代码。
3.通过script标签来请求,原理就是在本域内的A内生成一个JS标签,它的SRC指向请求的另外一个域的某个页面B,这个src里面通常会加一个A页面定义好的回调函数,B返回数据即可,可以直接返回调用这个回调函数,这种跨域的通信方式被称为JSONP,此方案存在的缺陷是, script的src属性完成该调用时采取的方式时get方式,如果请求时传递的字符串过大时,可能会无法正常运行。
4.window.name,window.name是一种解决跨域数据传输的新技术,通过在iframe中加载一个跨域的HTML文件,并且在HTML文件中设置window.name的值为需要传给接受者的数据,接收者就可以取得到window.name的值并且返回,比较关键的是同源策略的影响对location的控制不受限制,所以需要加载一个代理的页面来让发送页面读取window.name.
5.使用flash,原理是JavaScript将数据提交给本域下的 Flash,通过 Flash 中转去访问其他域的接口,只需要其他域的根目录下有一个crossdomain.xml文件,文件中设置允许所有域名或允许本域访问即可。
了解更多,请看:
http://www.phpchina.com/html/48/n-33848.html
http://www.sitepen.com/blog/2008/07/22/windowname-transport/
http://www.planabc.net/2008/09/01/window_name_transport/
http://hikejun.com/demo/windowname/demo_windowname.html
http://blog.s135.com/ajaxcdr/
客户端数据存储有很多种,最常见的就是Cookie的方式,如YUI中Cookie组件,cookie是存储于访问者的计算机中的变量。每当同一台计算机通过浏览器请求某个页面时,就会发送这个 cookie。你可以使用 JavaScript 来创建和取回 cookie 的值,几乎所有浏览器都有这个功能,缺点是存储量太小(4k),数据访问不够灵活,一般允许每个网站使用20个,不能跨浏览器,每次请求都要把数据发送给服务器端。
DOM Storage
如果浏览器支持HTML5,将有以下客户端本地存储特性:sessionStorage/localStorage/globalStorage
seesionStorage在会话结束后就会销毁,localStorage是持久化存储,他们的存储空间更大,达到了10M,简洁的接口如setItem(),getItem(),removAttribute();操作非常方便。
Flash Share Object
Flash as3下的ShareObject类可以用于本地存储,ShareObject有两种格式:本地和远程。在客户端存储需要用到Flash Local Share Object,myLSO = SharedObject.getLocal(’foo’); myLSO.data.myObj = myObj;//直接将数据对象存储到data中,然后通过ExternalInterface可以让javascript和flash进行通讯,比较方便,同样YUI中也有swfStore组件。使用Flash存储的优点是跨浏览器支持良好,默认提供了100K,可向用户申请更多空间。
UserData
在IE下可以使用css的behavior进行存储,.userData{behavior:url(#default#userdata);}或者obj.style.behavior = ‘url(”#default#userData”)’;
userData对象有下列成员:expires,XMLDocument,getAttribute(),load(),removeAttribute(),save(),setAttribute();如:o.setAttribute(’adam’, ‘http://adamlu.com/’);o.save(’lu’);单个页面提供了128K,每个域提供了1024K的存储空间。
还有其它的一些不常用的存储方式如:window.name/Silverlight/Open Database/Application Cache等,这里http://ningxiaotao.javaeye.com/blog/683611有更多介绍,在平常的开发中一般会结合上面介绍的几种方式来用,如YUI中的Storage组件。
表单验证在很多地方需要用到,如何实现通用的表单验证呢?如何让前后端的验证一致呢?最近在做的一个项目中碰到了这个问题,后端的表单验证基于一个TPL模板,或者说是一个XML的规则验证文件,前端则是通过这个XML转换的JSON串来进行验证,这个JSON串的制定在前期比较关键,制定的好的话对于前端的代码量来说可以大大减少,因此在设计这个JSON串的时候,我把每个表单元素作为JSON的KEY,而VALUE则为一个包含各个验证规则的OBJECT,每个规则都是一个OBJECT,里面相对应着一条errmsg,整个JSON与后端的XML文件无缝地进行转换,最终实现了前后端的验证一致,而且可以适用于每个页面的表单验证。
点此看DMEO
级联菜单有很多种,有固定级数的级联,有无限级数的级联,有静态的级联,也有动态的级联(ajax加载选项)。设计级联菜单需要用到HTML的Select控件,Option控件,下面是几个级联菜单的例子。
1.静态数据级联,最多四级。
2.静态数据级联,最多三级。(网上的)
3.动态数据,无限级。
参考:
Select 对象集合
集合 描述
options[] 返回包含下拉列表中的所有选项的一个数组。
Select 对象属性
属性 描述
disabled 设置或返回是否应禁用下拉列表。
form 返回对包含下拉列表的表单的引用。
id 设置或返回下拉列表的 id。
length 返回下拉列表中的选项数目。
multiple 设置或返回是否选择多个项目。
name 设置或返回下拉列表的名称。
selectedIndex 设置或返回下拉列表中被选项目的索引号。
size 设置或返回下拉列表中的可见行数。
tabIndex 设置或返回下拉列表的 tab 键控制次序。
type 返回下拉列表的表单类型。
Select 对象方法
方法 描述
add() 向下拉列表添加一个选项。
blur() 从下拉列表移开焦点。
focus() 在下拉列表上设置焦点。
remove() 从下拉列表中删除一个选项。
Select 对象事件句柄
事件句柄 描述
onchange 当改变选择时调用的事件句柄。
Option 对象
Option 对象代表 HTML 表单中下拉列表中的一个选项。在 HTML 表单中 <option> 标签每出现一次,一个 Option 对象就会被创建。您可通过表单的 elements[] 数组访问一个 Option 对象,或者通过使用 document.getElementById()。
Option 对象的属性
属性 描述
defaultSelected 返回 selected 属性的默认值。
disabled 设置或返回选项是否应被禁用。
form 返回对包含该元素的 <form> 元素的引用。
id 设置或返回选项的 id。
index 返回下拉列表中某个选项的索引位置。
label 设置或返回选项的标记 (仅用于选项组)。
selected 设置或返回 selected 属性的值。
text 设置或返回某个选项的纯文本值。
value 设置或返回被送往服务器的值。
JAVASCRIPT QUIZ
整理了一些Javascript的小测试,可以试着先不看结果做一下。
直接看DEMO
在CSS Trick上面看到了一篇讲跨域Iframe调整的文章,DEMO在这里。要做到跨域Iframe高度自适应,需要可以控制两个域内的内容,主要的技术是通window.location.hash来传递信息。
先来看看主域的内容: 继续阅读 »