小议javascript 设计模式 推荐_javascript技巧

记得早前就说过要和大家分享“javascript设计模式”,迟迟没写不是因为我懒,最近确实太忙,忙工作,忙旅游(啊哦?),好不容易这几天空闲了,接下来是兑现之前空口白话的时间了。
在讨论设计模式之前,请确认您已经有一定的脚本编程基础,如果不甚了解,建议可以先查阅本人很久之前写的这篇《浅谈javascript面向对象编程》请看下一篇文章。
讲到设计模式,不得不先重点着墨于“接口设计”,因为接口设计在设计模式中的意义太大了,大于模式本身。直观起见,先介绍一下接口定义的形式:

复制代码 代码如下:

var interface = new Interface("interface",[["getName",1],["getAge",1]]);

可以看出接口函数必须包含两个参数,接口方法定义在一个二维数组中。上例中定义了两个接口方法:getName,getAge,这两个方法都带一个参数,下面我们详细看一下Interface函数的实现代码,从而加深大家对接口的理解。

复制代码 代码如下:

function Interface(name,methods){
if(arguments.length !=2){
console.log("参数必须为二个");
}
this.name = name;
this.methods = [];
if(methods.length<1){
console.log("第二个参数不能为空数组");
}
for(var i=0;len=methods.length,i<len;i++){
if(typeof methods[i][0] !== 'string'){
console.log("第一个参数数据类型必须为字符串");
}
if(methods[i][1] && typeof methods[i][1] !== 'number'){
console.log("第二个参数数据类型必须为整数型");
}
if(methods[i].length == 1){
methods[i][1] = 0;
}
this.methods.push(methods[i]);
}
}

从代码中不难看出,接口函数的定义规则:[1]Interface函数只能包含两个参数,第一个参数为接口名称,第二个参数是一个二维数组[2]第二个参数不允许为空数组[3]methods参数中的第一个参数必须为字符串类型,用以定义方法名,第二个参数必须为整数类型,用以定义方法的参数个数[4]当methods中方法的参数个数为0时,可以省略不写。
接下来要建一个类,让该类继承前面定义的interface接口,那该怎么做呢,别急,我们需要新增一个方法,见如下代码:

复制代码 代码如下:

var ioldfish = function(name,age){
this.name = name;
this.age = age;
Interface.regImplement(this,interface);
}
ioldfish.prototype.getName = function(){
alert(this.name);
};
ioldfish.prototype.getAge = function(){
alert(this.age);
};
var fishwl = new ioldfish("老鱼",27);
fishwl.getName();

Interface.regImplement就是我们要新增的方法,作用就是让ioldfish类按照接口interface的规范编码,否则将会在firebug的控制台抛出异常。
看看这个方法的具体实现代码:

复制代码 代码如下:

Interface.regImplement = function(object){
if(arguments.length<2){
console.log("接口继承参数不能少于二个");
}
for(var i=1;len = arguments.length,i<len;i++){
var interface = arguments[i];
if(interface.constructor !== Interface){
console.log("第三个参数开始必须为接口实例");
}
for(var j=0;len=interface.methods.length,j<len;j++){
var method = interface.methods[j][0];
if(!object[method] || typeof object[method] !=="function" || object[method].getParameters().length !== interface.methods[j][1]){
console.log(""+method+"方法接口不匹配");
}
}
}
}

解读这段代码,你很容易发现:[1]Interface.regImplement继承接口函数的参数至少要有两个,如果有第三个参数,那么该参数必须是Interface接口的实例[2]我们去遍历interface接口中的方法,再与新增类中的方法一一匹配,如果发现继承了该接口规范的类缺少某方法,就会抛出错误提示。[3]接口对于参数个数也进行了匹配,如果接口方法中的参数个数与新增类中方法的个数不匹配也会抛出错误提示。
为了匹配方法中参数个数,这里用到一个getParameters()方法,我们基于Function做个扩展,代码实现如下:

复制代码 代码如下:

Function.prototype.getParameters = function(){
var str = this.toString();
var paramStr = str.slice(str.indexOf("(")+1,str.indexOf(")")).replace(/\s*/g,'');
try{
return (paramStr.length ==0 ? [] : paramStr.split(","));
}
catch(err){
console.log("非法函数");
}
}

接下来,你可以把所讲的Interface函数,Interface.regImplement函数,还有Function.prototype.getParameters函数整合到一个interface.js的文件中,调试一下新建的这个ioldfish类。看看当类中缺少getAge方法时会怎么样?建议新手,各类情况都模拟一下,加强理解吧!如果你确信已经完全理解接口设计,那就跟着我继续往下走。
Javascript设计模式之单体模式Singleton
单体模式Singleton:这是最基础的设计模式,严格来说没什么模式可言,但是却很容易用也很好用,支付宝很多组件都是通过单体模式设计的。事实上在《浅谈javascript面向对象编程》中阐述原型继承的时候就已经用到了该模式,这里简单带过,重点说一下惰性单体,这对一些不是所有用户都需要,在特定情景下才会用到的组件有非常好的优化作用,他可以让组件的实例化推迟到用户触发他的时候。

复制代码 代码如下:

var ioldfish = {
name:'老鱼',
age:27,
getName:function(){
alert(name);
},
getAge:function(){
alert(age);
}
}

上例是一个最简单的单体模式,把本人的资料都整合到ioldfish这个对象字面量中,形成一个模块,同时起到了一个命名空间的作用。

复制代码 代码如下:

var ioldfish =(function(){
var name = '老鱼';
var age = 27;
return{
getName:function(){
alert(name);
},
getAge:function(){
alert(age);
}
}
})();

对第一个单体做简单的修改,通过闭包让name,age成为静态私有变量,确保实例化的时候在内存中始终只有一份,这样更符合单体模式的定义。
下面重点介绍一下惰性单体,废话少说,先看看我们该如何来实现惰性单体:

复制代码 代码如下:

var ioldfish = (function(){
var uniqueInstance;
var name = '老鱼';
var age = 27;
function constructor(){
return{
getName:function(){
alert(name);
},
getAge:function(){
alert(age);
}
}
}
return{
isInstance:function(){
if(uniqueInstance == null){
uniqueInstance = constructor();
}
return uniqueInstance;
}
}
})();
ioldfish.isInstance().getName();

上面的结构公私分明一目了然,私有变量uniqueInstance(标识类是否已经实例化)和私有方法constructor,返回一个公有方法isInstance(通过该方法可以调用私有方法constructor中定义的方法),形如:ioldfish.isInstance().getName();先通过isInstance()方法判断其是否被实例化,然后通过getName()方法获取到闭包内的私有变量name。该模式的应用场景还是很多的,是不是遇见过页面中需要加载很大的一个日历控件,但并非所有用户都用的到呢?是不是…
Javascript设计模式之工厂模式Factory
工厂模式Factory:先创建一个抽象类,然后基于这个抽象类派生出子类,并在子类中创建工厂方法,从而把实例化推迟到对应的子类中进行,说实话,工厂模式在javascript中的应用有些牵强,毕竟javascript不像java存在硬编码带来的困搅,要学习的只是模式的思想,切忌因为模式而模式。
不妨举个偏激点的例子,为tab切换、下拉列表等组件添加定位,渐隐,延迟等效果,我们可以先为这些组件定义一个接口:
  var Iwidget = new Interface("iwidget",[["addEffect"]]);
定义该接口,以便之后派生的子类继承,接口中定义了一个addEffect方法,接口方法实现后,调用的同学大可不必关注各子类中对于addEffect方法的代码实现。

复制代码 代码如下:

var Widget = function(){};
Widget.prototype={
fire:function(model){
var widget = this.createWidget(model);
//有同学问为什么子类都必须定义接口方法,因为下面要调用嘛
widget.addEffect();
return widget;
},
show:function(){
//show代码具体实现
},
hide:function(){
//hide代码具体实现
},
createWidget:function(model){
alert('抽象类,不可以实例化')
}
};

上例先定义一个抽象类Widget,做为派生子类的父类,由于考虑到这两类组件都涉及到隐藏和显示一个容器,所以在父类中预先定义好show和hide方法以便子类继承。

复制代码 代码如下:

var xTab = function(){};
extend(xTab,Widget);
xTab.prototype.createWidget = function(model){
var widget;
switch(model){
case 'position':
widget = new xTabPosition();
break;
case 'anim':
widget = new xTabAnim();
break;
case 'delay':
default:
widget = new xTabDelay();
}
};
var dropDown = function(){};
extend(dropDown,Widget);
dropDown.prototype.createWidget = function(model){
var widget;
switch(model){
case 'position':
widget = new dropDownPosition();
break;
case 'anim':
widget = new dropDownAnim();
break;
case 'delay':
default:
widget = new dropDownDelay();
}
};

子类xTab和dropDown继承了父类,并且重写了createWidget方法,不同的子类根据定位,渐隐,延迟效果分别创建不同的实例,只要创建这些实例的类都实现接口中约定的addEffect方法,至于方法代码如何实现,千篇一律,爱咋整咋整。

复制代码 代码如下:

var xTabPosition = function(){};
xTabPosition.prototype ={
addEffect:function(){
//具体实现代码
}
};
var dropDownPosition = function(){};
dropDownPosition.prototype ={
addEffect:function(){
//具体实现代码
}
};
var dropDownInstance = new dropDown();
dropDownInstance.fire('position');

以此类推,如果您需要为气泡组件添加这些效果,照葫芦画瓢就可以了,说到这里你可以清楚的看到,这种设计模式大大降低了类和类之间的耦合度,而且可以根据具体的交互需求,实现不同的辅助动作,但是也无可避免的增加了代码实现上的复杂性,事实上这种模式并不适合javascript,毕竟它有别于java,不会有类名硬编码的问题,目的是学习他的设计思想,所以以上示例仅供参考,如无大人在旁,小朋友切勿效仿。
对于javascript爱好者来说,更有价值的应该是工厂模式中讲到的的”缓存(memoization)机制”,书上举了个创建XHR对象的例子来说明该特性,但是效果显然不够明显……
memoization名词解释:把函数的每次执行结果都放入一个键值对(数组也可以,视情况而定)中,在接下来的执行中,在键值对中查找是否已经有相应执行过的值,如果有,直接返回该值,没有才 真正执行函数体的求值部分。很明显,找值,尤其是在键值对中找值,比执行函数快多了
在递归调用的时候,memoization的威力才能更好的显现。下面是一个经典的斐波纳契序列,fib(20) 会把fib这个方法执行21891次,如果是fib(40),这会执行331160281次。

复制代码 代码如下:

function fib(n) {
if (n < 2) {
return n;
}
return fib(n - 1) + fib(n - 2);
}

再看看如何使用memoization来实现:

复制代码 代码如下:

var iterMemoFib = (function() {
var cache = [1, 1];
var fib = function(n) {
if (n >= cache.length) {
//将一个递归转换成了一个
for (var i = cache.length; i <= n; i++) {
cache[i] = cache[i - 2] + cache[i - 1];
}
}
return cache[n-1];
}
return fib;
})();

将Function的原型扩展memoize 和unmemoize 方法,这样你可以对任何函数实现memoize和解除memoize,当然,这个方法要慎,对一些不是频繁执行的函数,没必要缓存:

复制代码 代码如下:

Function.prototype.memoize = function() {
var pad = {};
var self = this;
var obj = arguments.length > 0 ? arguments[i] : null;
var memoizedFn = function() {
// 把参数作为数组保存,作为键,把函数执行的结果作为值缓存起来
var args = [];
for (var i = 0; i < arguments.length; i++) {
args[i] = arguments[i];
}
if (!(args in pad)) {
pad[args] = self.apply(obj, arguments);
}
return pad[args];
}
memoizedFn.unmemoize = function() {
return self;
}
return memoizedFn;
}
Function.prototype.unmemoize = function() {
alert("Attempt to unmemoize an unmemoized function.");
return null;
}

使用方法:fib.memoize();
Javascript设计模式之组合模式
组合模式:运用该设计模式可以通过组合对象添加属性和方法,通过递归批量式的让叶子对象得到组合对象的属性和方法。打个比方我们现在要动态创建一个银行列表,按银行类型分为网上银行类,卡通银行类,并可配置他们是否显示。用组合模式如何实现呢?
第一步还是先定义接口,因为要做到某类银行甚至某个银行是否显示可配置,那么我们先约定2个接口,showBank和hideBank。
var IcardItem = new Interface(”icardItem”,[["showBank"],["hideBank"]]);
接下来先定义卡的组合对象,并设置组合对象的基本方法add,remove,getChild,由于这个类继承了IcardItem接口类,所以还定义了showBank,hideBank这两个接口方法。

复制代码 代码如下:

var cardMain = function(id){
this.cards = [];
this.element = document.createElement("div");
this.element.id = id;
Interface.regImplement(this,IcardItem);
};
cardMain.prototype = {
add:function(card){
this.cards.push(card);
this.element.appendChild(card.getElement());
},
remove:function(card){
for(i=0;len=this.cards.length,i<len;i++){
if(cards[i] == card){
this.cards.splice(i,1);
break;
}
this.element.removeChild(card.getElement());
}
},
getChild:function(i){
return this.cards[i];
},
getElement:function(){
return this.element;
},
showBank:function(){
this.element.style.display ="block";
for(i=0;len=this.cards.length,i<len;i++){
this.cards[i].showBank();
}
},
hideBank:function(){
this.element.style.display ="none";
for(i=0;len=this.cards.length,i<len;i++){
this.cards[i].hideBank();
}
}
};

然后定义叶子对象类bankLogo用以创建银行logo,这里银行logo都以带class的a标签标识:

复制代码 代码如下:

var bankLogo = function(bankClassName){
this.element = document.createElement("a");
this.element.className = bankClassName;
Interface.regImplement(this,IcardItem);
};
bankLogo.prototype ={
showBank:function(){
this.element.style.display ="block";
},
hideBank:function(){
this.element.style.display ="none";
},
getElement:function(){
return this.element;
}
};

最后设置一个单体对象,将操作银行的相关信息形成一个模块,方便调用:

复制代码 代码如下:

var BankAction ={
bankList:[],
addBank:function(card){
this.bankList.push(card);
},
innerBank:function(conId){
for(i=0;len=this.bankList.length,i<len;i++){
var cardObj =this.bankList[i].getElement();
}
document.getElementById(conId).appendChild(cardObj);
}
};

到了实现环节了,实例化生成一个包含所有卡的最外层容器,然后根据卡类,分别生成一个放置银行卡和卡通卡的容器,最后生成各银行卡的实例,并按层级关系形成DOM结构:

复制代码 代码如下:

var bankDivT = new cardMain("PayCard");//创建最外层容器
var ebankCard = new cardMain("ebankCard");//创建网银类银行卡容器
var ktCard = new cardMain("ktCard");//创建卡通类银行卡容器
var ccbBank = new bankLogo('Ebank-CMB');//创建招行银行卡
var abcBank = new bankLogo('Ebank-ABC');//创建农行银行卡
var abcKtBank = new bankLogo('Kt-ABC');//创建卡通农行卡
ebankCard.add(ccbBank);
ebankCard.add(abcBank);
ktCard.add(abcKtBank);
bankDivT.add(ebankCard);
bankDivT.add(ktCard);
BankAction.addBank(bankDivT);
BankAction.innerBank("bankList");

将动态生成的银行列表,DOM结构形如:

复制代码 代码如下:

<div id="PayCard">
<div id="ebankCard">
<a class="Ebank-CMB"></a>
<a class="Ebank-ABC"></a>
</div>
<div id="ktCard">
<a class="Kt-ABC"></a>
</div>
</div>

组合模式应用在动态生成用户界面的时候,是非常不错的选择,他可以很大程度的简化粘合性代码,提升维护性。不过还是要慎用,毕竟当叶子对象很多的时候,递归还是存在性能上的问题。
Javascript设计模式之装饰者模式
装饰者模式:可以不创建新的子类,给对象创建新的功能。举例说明:支付宝收银台红包结合余额付款的应用场景。
   var Ieconomics = new Interface("ieconomics",[["getPrice"]]);
首先创建一个组件类,基与该组件实例化的对象,会被作为参数传递给装饰者类,以便装饰者调用到该组件中的各方法。

复制代码 代码如下:

  var economic = function(){
Interface.regImplement(this,Ieconomics);
};
economic.prototype={
getPrice:function(){
//代码实现
}
};

然后创建一个装饰者抽象类,作为派生装饰者选件类的父类:

复制代码 代码如下:

  var economicsDecorator = function(economic){
this.economic = economic;
this.regImplement(economic,Ieconomics);
};
economicsDecorator.prototype={
getPrice:function(){
return this.economic.getPrice();
}
};

最后基于上面这个抽象类,派生出一个装饰者选件类:

复制代码 代码如下:

  //红包装饰者选件类
var coupon = function(economic){
//调用装饰着抽象类的构造函数
economicsDecorator.call(this,economic);
};
extend(coupon,couponDecorator);
coupon.prototype=function(){
//改写getPrice方法
getPrice:function(){
return this.economic.getPrice() - this.getCoupon();
},
getCoupon:function(){
//获取红包总价具体实现
}
};
var myCoupon = new economic();
myCoupon = new coupon(myCoupon);

实现装饰者模式就是这么简单,首先创建一个组件的实例myCoupon,然后将该对象作为参数传递给装饰者选件类coupon。你会发现两句代码中我都把值赋给了变量myCoupon,这是因为他们都实现了同一个接口类,他们之间是可以互换使用的。
看到这里心细的同学可能会发现,我们在coupon类中新增了一个getCoupon方法,目前来看不会有任何问题,但是如果我们继续创建一个购物卷装饰者选件类,然后结合红包一起用呢?

复制代码 代码如下:

//购物卷装饰者选件类
var voucher = function(economic){
economicsDecorator.call(this,economic);
};
extend(voucher,couponDecorator);
voucher.prototype=function(){
getPrice:function(){
return this.getPrice() - this.getVoucher();
},
getVoucher:function(){
//获取优惠卷总价具体实现
}
};
var myCoupon = new economic();
myCoupon = new coupon(myCoupon);
myCoupon = new voucher(myCoupon);

在这种场景下面getCoupon方法已经找不到了,这是因为voucher装饰myCoupon的时候,它的父类economicsDecorator不包含getCoupon方法,那自然是取不到的了,那该怎么办呢?
分析一下装饰者抽象类economicsDecorator,我们传递了一个myCoupon的引用作为参数,我们可以通过这个参数做一些小动作,获得新增加的方法。
 
复制代码 代码如下:

 var economicsDecorator = function(economic){
this.economic = economic;
this.interface = Ieconomics;
for(var k in this.economic){
if(typeof this.economic[key] !== "function"){
continue;
var i;
for(i = 0;len = this.interface.methods.length,i < len; i++) {
//通过遍历比较在接口类中是否包含此方法,如果包含返回下一个
if(key == this.interface.methods[i][0]) {
break;
}
}
if(i < this.interface.methods.length)
continue;
var decorator = this;
//采用匿名函数调用方式来定义新方法
(function(methodName) {
decorator[methodName] = function() {
return decorator.economic[methodName]();
};
})(key);
}
}
}
this.regImplement(economic,Ieconomics);
};
economicsDecorator.prototype={
getPrice:function(){
return this.economic.getPrice();
}
};

看上面的代码,我们对装饰者抽象类做了一些修改,这样做是为了确保在装饰者选件类中一旦定义新方法,可以在装饰者抽象类中动态的定义出来。这里只是提供一个使用装饰者模式的思路,具体的实现代码远比这个复杂,由于项目还在开发中,demo暂不提供,支付宝新版收银台发布后,会跟大家再做个详细的设计分享。
Javascript设计模式之桥接模式
桥接模式:将抽象和其实现分离开来,以便二者独立变化。其实很简单,只是在API和具体事件之间增加一个桥梁,从而降低API和使用他的类和对象之间的耦合。
事实上对大多数同学来说桥接模式并不陌生,下面的this.getName就是一种桥接方法,他是外访问的一个接口,他的内部实现是通过访问内部私有变量来实现的,这个方法起到了外部和内部沟通的桥梁作用。

复制代码 代码如下:

var ioldfish = function(){
var name = '老鱼';
this.getName = function(){
alert(name);
}
}

桥接模式用的最多的还是在事件监听器回调函数。下面这个是获取用户信息的API接口函数:

复制代码 代码如下:

function getUserInfo(userid,callback){
asyncRequest('GET','userInfo?userid='+userid,function(resp){
callback(resp.responseText);
});
}

接下去我们要做的是把这个API和某个事件的触发建立一个桥梁关系
addEvent(element,'click',bridgeMethod);
function bridgeMethod(e){
getUserInfo(this.userid,function(){
//回调函数实现代码
});
}
这里在element对象click的时候触发函数并不是getIserInfo,而是新建了一个桥接方法bridgeMethod,通过这层桥接使得API接口函数和click事件相对独立,这样大大拓宽了API的适用范围。
Javascript设计模式之适配器模式
适配器模式:打个比方,你维护了一个系统,之前一直都是用prototype框架,但是现在打算新引入YUI框架,那如何让两个框架平稳过度呢
,举个例子,如何将prototype中的$方法转换为YUI中的get方法:

复制代码 代码如下:

function $(){};
function YAHOO.util.Dom.get=function(el){};
function prototypeToYuiAdapter(){
return YAHOO.util.Dom.get(arguments);
}

你要在prototype中使用yui的get方法,只需要做以下申明即可:
   $ = prototypeToYuiAdapter;
这样的话,在prototype中就可以使用YUI中的get方法了。本人并不是很推崇这种模式,所以不多做阐述,事实上我觉得不到万不得以,我们根本不需要使用这种模式,作为一名负责任的设计者,我宁可做代码重构也不希望使用该模式,只能作为无奈之下的过渡型方案使用。
Javascript设计模式之门面模式,观察者模式
门面模式:这应该是所有脚本框架中都用到的,最基础的设计模式,随便找个框架中定义好的方法看看就行了,比如说YUI中的setStyle方法等等等等。在这里就不多阐述了。
观察者模式:该设计模式应用在javascript上似乎更为牵强,不甚理解,这里就不说了,以免误人子第,如有心得者不吝赐教。
一天时间都耗在这篇博文上了,好象还有很多想写的,看来要把心里想的东西写清楚还是不容易的,再整理整理再说吧,敬请期待!

时间: 2024-11-05 06:24:55

小议javascript 设计模式 推荐_javascript技巧的相关文章

JavaScript设计模式初探_javascript技巧

目的:设计模式众多,尝试记录下学到的不同设计模式的优劣,方便以后查阅. 前言:半年前看高程的时候看到设计模式这章,云里雾里,不是看不明白,而是不明白为啥要如此麻烦只为创建一个对象.直到最近完成了自己第一个小项目,才体会到当代码量多起来时没有适当的规范与限制是多么大的灾难.于是重新翻开高程,总结下几种我学到的简单设计模式的优劣. 正文:本文一共介绍7种设计模式以及他们的应用场景.优劣. 1.工厂模式 直接用函数来封装对象,将对象作为返回值. function person (name,age) {

学习JavaScript设计模式(接口)_javascript技巧

1.接口概述 1).什么是接口? 接口是提供了一种用以说明一个对象应该具有哪些方法的手段.尽管它可以表明这些方法的语义,但它并不规定这些方法应该如何实现. 2). 接口之利 促进代码的重用. 接口可以告诉程序员一个类实现了哪些方法,从而帮助其使用这个类. 有助于稳定不同类之前的通信方式. 测试和调式因此也能变得更轻松. 在javascript这种弱类型语言中,类型不匹配错误很难跟踪.使用接口可以让这种错误的查找变午更容易一点,因为此时如果一个对象不像所要求的类型,或者没有实现必要的方法,那么你会

浅谈Javascript数组(推荐)_javascript技巧

在程序语言中数组的重要性不言而喻,JavaScript中数组也是最常使用的对象之一,数组是值的有序集合,由于弱类型的原因,JavaScript中数组十分灵活.强大,不像是Java等强类型高级语言数组只能存放同一类型或其子类型元素,JavaScript在同一个数组中可以存放多种类型的元素,而且是长度也是可以动态调整的,可以随着数据增加或减少自动对数组长度做更改. 首先,大概说说数组的基本用法. 数组,即Array类型,是开发中最常用的类型之一,javascript中的数组和其他语言最大的区别就是每

学习JavaScript设计模式(单例模式)_javascript技巧

单例模式的定义:保证一个类仅有一个实例,并提供一个访问它的全局访问点. 单例模式是一种常用的模式,有一些对象我们往往只需要一个,比如线程池.全局缓存.浏览器的window对象.在js开发中,单例模式的用途同样非常广泛.试想一下,当我们单击登录按钮的时候,页面中会出现一个登录框,而这个浮窗是唯一的,无论单击多少次登录按钮,这个浮窗只会被创建一次.因此这个登录浮窗就适合用单例模式. 1.单例模式的使用场景 在使用一种模式之前,我们最好要知道,这种模式的使用场景.用了这么久的单例模式,竟全然不知!用它

学习JavaScript设计模式(封装)_javascript技巧

在JavaScript 中,并没有对抽象类和接口的支持.JavaScript 本身也是一门弱类型语言.在封装类型方面,JavaScript 没有能力,也没有必要做得更多.对于JavaScript 的设计模式实现来说,不区分类型是一种失色,也可以说是一种解脱. 从设计模式的角度出发,封装在更重要的层面体现为封装变化. 通过封装变化的方式,把系统中稳定不变的部分和容易变化的部分隔离开来,在系统的演变过程中,我们只需要替换那些容易变化的部分,如果这些部分是已经封装好的,替换起来也相对容易.这可以最大程

学习JavaScript设计模式(继承)_javascript技巧

1.继承 在javascript中继承是一个非常复杂的话题,比其他任何面向对象语言的中的继承都复杂得多.在大多数其他面向对象语言中,继承一个类只需要使用一个关键字即可.与它们不同,在javascript中要想达到传承公用成员的目的,需要采取一系列措施.更有甚者,javascript属于使用原型式继承的少数语言之一.利益于这种语言的灵活性,你既可使用标准的基于类的继承,也可使用更微妙一些的原型式继承. 2.为什么需要继承? 一般来说,在设计类的时候,我们希望能减少重复性的代码,并且尽量弱化对象间的

2014 年最热门的21款JavaScript框架推荐_javascript技巧

下面,我们将会介绍 2014 年最火的 21 款JavaScript 框架,专为前端开发者准备的哦:)众所周知, JavaScript 框架是 JavaScript编程语言最棒的特性之一. JavaScript 框架是预先编写好的 JavaScript 库,为基于 JavaScript 的应用提供更简单的开发方式.这些 JavaScript框架提供大量的函数,帮助你改善网站任务.现在网络上有着各种各样繁杂的JavaScript 框架,这里我们列举 2014年最火的 21 款JavaScript

16个最流行的JavaScript框架[推荐]_javascript技巧

1. jQuery – Javascript Framework jQuery 是最流行的 JavaScript 框架,它简化了HTML 文档遍历.事件处理.动画和Ajax交互. 2. Dojo Javascript Framework Dojo强大的核心使Web开发更加敏捷,它拥有出色的UI工具库,号称 Unbeatable JavaScript Tools. 3. Sencha Ext JS4 Javascript Framework 官方介绍说是最先进的JavaScript框架,用于构建下

用最通俗易懂的代码帮助新手理解javascript闭包 推荐_javascript技巧

最近看了几篇有关javascript闭包的文章,包括最近正火的汤姆大叔系列,还有<javascript高级程序设计>中的文章,--我看不懂,里面有些代码是在大学教科书中看都没看过的,天书一般.幸好最近遇到两本好书<ppk on javascript>和<object-oriented JavaScript>,正字阅读中,后者还没有中文版,但前者还是建议看原版,写的不复杂,有兴趣的朋友可以看看,适合想进阶的朋友. 今天就结合这两本书,用最浅显的语言和最通俗的方式谈谈jav