Web Frontend Develope, Design, Music, Life——Stay Hungry, Stay Foolish~

在javascript中实现面向对象

最近在看公司的一个框架,整个框架基本都是面向对象,让我对于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);//调用父类的析构函数
}
});

有了这个基础的架子之后让类的继承变得简单,从而可以更方便地实现包,接口等特性。

Mathematic in Javascript

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 是一种垃圾收集式语言,这就是说,内存是根据对象的创建分配给该对象的,并会在没有对该对象的引用时由浏览器收回。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

浏览器兼容性问题小结

在内部分享了浏览器兼容性的一些问题,主要是平常遇到过的但是又不是大家都熟悉的一些问题,PPT在这里:

Ajax跨域访问解决方案

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组件

淘宝北京UED招聘-前端开发工程师

岗位名称:前端开发工程师

要求:

1. 精通各种Web前端技术,包括XHTML/XML/CSS/Javascript/ActionScript等(JS和AS之一即可);
2. 深刻理解Web标准,对可用性、可访问性等相关知识有实际的了解和实践经验;
3. 有基于Ajax或Flash的RIA应用开发经验;
4. 至少精通一门非Web前端脚本的语言(如Java/PHP/C++),并有项目经验;
5. 个性乐观开朗,逻辑性强,善于和各种背景的人合作;
6. 计算机、数学、自动化等相关专业本科以上学历优先。

简历请发邮件至yizhou@taobao.com

使用YUI3组织网站结构

最近在做一个保险的重构项目,在着手开始做之前就是考虑怎么来组织前端的代码,我的做法是使用YUI3,在insure下有一个base.js,这个js定义了整个网站需要的组件,如公共的组件 日历 表单校验 购买流程 提示 级联等等,这些组件可以是使用YUI2开发,也可以是使用YUI3开发,也可以是使用原生的js来写,最后都会通过yui的loader加载后来使用。base.js里面大概是这样的:
yui-min.js的代码
var module = {
‘casecade’:{
fullpath: widgetsUrl+’cascade/cascade.js’,
require: ['node']
}

};//整个网站需要用到的一些模块定义,有新的模块添加或修改时就更新这个module
var yuiCfg  = {};//yui的一些配置
var INS = YUI(yuiCfg);//定义了保险的全局变量INS

前端Assets的目录结构是这样的:

js/
—base.js >定义了widgets组件的各个模块
—widgets/cascade/ >级联菜单组件
—widgets/calendar/ >日历组件
—widgets/validator/ >校验组件
—widgets/… >其它组件
—taikang/tk_traffic.js tk_estimate.js >泰康险种各个功能页面需要用到的js文件
—huatai/ht_traffic.js >华泰险种各个功能页面需要用到的js文件

css/
—index.css >首页的样式
—common.css >公共的样式
—taikang/tk_traffic.css … >泰康险种的样式
—huatai/ht_traffic.css … >华泰险种的样式

比如在tk_traffics.js里面就可以这样来使用,INS.use(’casecade’, ‘validator’, function(Y){
//泰康保险的页面逻辑
});

使用这样的目录结构在工程师嵌套页面的时候有很大的灵活性,因为头部工程师会把它做成一个公共的头,这个里面我把base.js和common.css放在公共头里面,每个险种的页面除了引用这样的公共头之外还会引用这个险种自有的样式以及js代码。把base.js放在头部之后,每个页面想要用某个组件都非常灵活,而且是使用了YUI的异步加载以及动态加载机制,如果服务器端提供了combo之后将会极大地提高前端的性能,对于团队开发来说也是比较灵活的方式。

返回顶部