javascript面向对象包装类Class封装类库剖析

javascript是个入门门槛很低的语言,甚至一个从来没有接触过javascript的技术人员,几小时内就可以写出一个简单有用的程序代码。

但是如果因此你就下结论:javascript是门简单的语言。那你就大错特错了。想写出高性能的代码,同样需要具备一个高级程序员的基本素养。

一个java或者c++程序员,不一定能写出高性能的javascript代码,但更容易写出高性能的javascript代码。
javascript的简单是基于它“胸襟广阔”的包容性。它声明时,不需要指定类型,甚至可以任意的转换类型。它面向对象,却没有类(Class)的限制。它是一门崇尚自由又非常严谨的语言,如果你是一个自由主义者,那么,拥抱javascript吧!

面向对象编程(OOP)是一种流行的编程方法。但javascript的OOP,较之JAVA、c++有很大的同,主要体现它的继承方式不同。javascript是基于原型PROTOTYPE继承的。所有对象都是基于原型链,最终追述到Object对象。

这里不想讨论过多的关于javascript的继承方式和其它语言的继承方式的不同之处。主要讨论如何封装javascript的Class,以便更好的管理和维护基础代码,减少重复代码,以及更好的模块化编程。

下面是几个github上找到的比较好的Class封装类库:
一、MY-CLASS
项目地址:https://github.com/jiem/my-class
先看基本用法:
a、新建一个类


代码如下:

(function(){
//新建类
varPerson=my.Class({
//添加静态方法
STATIC:{
AGE_OF_MAJORITY:18
},
//构造函数
constructor:function(name,age){
this.name=name;
this.age=age;
},
//实例方法
sayHello:function(){
console.log('Hellofrom'+this.name+'!');
},
//实例方法
drinkAlcohol:function(){
this.age<Person.AGE_OF_MAJORITY?
console.log('Tooyoung!Drinkmilkinstead!'):
console.log('Whiskeyorbeer?');
}
});
//暴露给命名空间
myLib.Person=Person;
})();
varjohn=newmyLib.Person('John',16);
john.sayHello();//log"HellofromJohn!"
john.drinkAlcohol();//log"Tooyoung!Drinkmilkinstead!"

b、继承一个类


代码如下:

(function(){
//Dreamer继承Person
varDreamer=my.Class(Person,{
//构造方法
constructor:function(name,age,dream){
Dreamer.Super.call(this,name,age);
this.dream=dream;
},
//实例方法
sayHello:function(){
superSayHello.call(this);
console.log('Idreamof'+this.dream+'!');
},
//实例方法
wakeUp:function(){
console.log('Wakeup!');
}
});
//Super访问父类
varsuperSayHello=Dreamer.Super.prototype.sayHello;
//暴露给全局命名空间
myLib.Dreamer=Dreamer;
})();
varsylvester=newmyLib.Dreamer('Sylvester',30,'eatingTweety');
sylvester.sayHello();//log"HellofromSylvester!IdreamofeatingTweety!"
sylvester.wakeUp();//log"Wakeup!"

c、给类添加新方法


代码如下:

//给myLib.Dreamer添加新方法
my.extendClass(myLib.Dreamer,{
//添加静态方法
STATIC:{
s_dongSomeThing:function(){
console.log("dosomething!");
}
},
//添加实例方法
touchTheSky:function(){
console.log('Touchingthesky');
},
//添加实例方法
reachTheStars:function(){
console.log('Sheissopretty!');
}
});

d、实现一个类的方法


代码如下:

//声明一个新类
myLib.ImaginaryTraveler=my.Class({
travel:function(){console.log('Travelingonacarpet!');},
crossOceans:function(){console.log('SayinghitoMobyDick!');}
});
(function(){
//Dreamer继承Person实现ImaginaryTraveler的方法
varDreamer=my.Class(Person,ImaginaryTraveler,{
//构造方法
constructor:function(name,age,dream){
Dreamer.Super.call(this,name,age);
this.dream=dream;
}
//...
});
//暴露给全局命名空间
myLib.Dreamer=Dreamer;
})();
varaladdin=newDreamer('Aladdin');
aladdininstanceofPerson;//true
aladdininstanceofImaginaryTraveler;//false
aladdin.travel();
aladdin.wakeUp();
aladdin.sayHello();

如果怕忘记new操作符


代码如下:

varPerson=my.Class({
//youcannowcalltheconstructorwithorwithoutnew
constructor:function(name,city){
if(!(thisinstanceofPerson))
returnnewPerson(name,city);
this.name=name;
this.city=citye;
}
});

下面看一下my.class的源代码解析:
my.Class实现思路基本是这样的,如果只有一个参数,那么声明的是一个基础类,这个参数是用来声明新类的方法和属以及构造函数。它不是继承而来,但它可以被继承。

继承的思路,就是如果有两个参数,第一个参数做为父类被继承,第二参数用来声明新类的方法和属性以及构造函数,它同样可以被继承。

如果有三个以上参数那么,除出第一个参数做为继承的父类,最后一个参数用声明新类的方法和属性以及构造函数。中间的参数是用类来扩展新类的方法。当然也可以通过my.extendClass扩展新方法。
同时,类库为commonJS和浏览环境都提供了支持!


代码如下:

/*globalsdefine:true,window:true,module:true*/
(function(){
//Namespaceobject
varmy={};
//保证AMD分模块可用
if(typeofdefine!=='undefined')
define([],function(){
returnmy;
});
elseif(typeofwindow!=='undefined')
//保证客户端可用
window.my=my;
else
//保证后台可用
module.exports=my;
//============================================================================
//@methodmy.Class
//@paramsbody:Object
//@paramsSuperClass:function,ImplementClasses:function...,body:Object
//@returnfunction
my.Class=function(){
varlen=arguments.length;
varbody=arguments[len-1];//最后一个参数是指定本身的方法
varSuperClass=len>1?arguments[0]:null;//第一个参数是指继承的方法,实例和静态部分均继承
varhasImplementClasses=len>2;//如果有第三个参数,那么第二个就是implementClass,这里其实只继承实例对象
varClass,SuperClassEmpty;
//保证构造方法
if(body.constructor===Object){
Class=function(){};
}else{
Class=body.constructor;
//保证后面不覆盖constructor
deletebody.constructor;
}
//处理superClass部分
if(SuperClass){
//中间件实现实例属性的继承
SuperClassEmpty=function(){};
SuperClassEmpty.prototype=SuperClass.prototype;
Class.prototype=newSuperClassEmpty();//原型继承,解除引用
Class.prototype.constructor=Class;//保证constructor
Class.Super=SuperClass;//父对象访问接口
//静态方法继承,重载superClass方法
extend(Class,SuperClass,false);
}
//处理ImplementClass部分,其实只继承实例属性部分,除SuperClass#arguments[0]#和body#arguments[length-1]#
if(hasImplementClasses)
for(vari=1;i<len-1;i++)
//implement是继承的实例属性部分,重载父对象implementClass方法
extend(Class.prototype,arguments[i].prototype,false);
//处理本身声明body部分,静态要STATIC指定,实例部分要删除STATIC部分
extendClass(Class,body);
returnClass;
};
//============================================================================
//@methodmy.extendClass
//@paramsClass:function,extension:Object,?override:boolean=true
varextendClass=my.extendClass=function(Class,extension,override){
//静态部分继承静态部分
if(extension.STATIC){
extend(Class,extension.STATIC,override);
//保证实例部分不继承静态方法
deleteextension.STATIC;
}
//实例属性继继承实例部
extend(Class.prototype,extension,override);
};
//============================================================================
varextend=function(obj,extension,override){
varprop;
//其实这里的flase是表明,覆盖父对象的方法
if(override===false){
for(propinextension)
if(!(propinobj))
obj[prop]=extension[prop];
}else{
//这里其实不覆盖父对象的方法,包括toString
for(propinextension)
obj[prop]=extension[prop];
if(extension.toString!==Object.prototype.toString)
obj.toString=extension.toString;
}
};
})();

二、KLASS
项目地址:https://github.com/ded/klass
先看使用方法:
a、新建一个类


代码如下:

//声明一个类
varPerson=klass(function(name){
this.name=name
})
.statics({//静态方法
head:':)',
feet:'_|_'
})
.methods({//实例方法
walk:function(){}
})

b、继承一个类


代码如下:

//SuperHuman继承Person
varSuperHuman=Person.extend(function(name){
//自动调用父类的构造方法
})
.methods({
walk:function(){
//显式声明调用父类的walk方法
this.supr()
this.fly()
},
fly:function(){}
})
newSuperHuman('Zelda').walk()

c、字面量方式声明一个类


代码如下:

varFoo=klass({
foo:0,
initialize:function(){
this.foo=1
},
getFoo:function(){
returnthis.foo
},
setFoo:function(x){
this.foo=x
returnthis.getFoo()
}
})

d、实现一个类的方法
因为有时候你可能希望覆写或者混合一个实例方法,可以这样:


代码如下:

//可以传递一个字面量去继承
varAlien=SuperHuman.extend({
beam:function(){
this.supr()
//beamintospace
}
})
varSpazoid=newAlien('Zoopo')
if(beamIsDown){
//覆写beam方法
Spazoid.implement({
beam:function(){
this.supr()
//fallbacktojets
this.jets()
}
})
}

下面看一下klass源代码解析
klass的基本设计思路很明确,极力的模仿其它语言的继承方式。比如:子类构造方法调用父类的构造方法,还可以显式的声明调用父类的方法。

这种判断都是基于正则匹配:fnTest=/xyz/.test(function(){xyz;})?/\bsupr\b/:/.*/;关键字"super"
如果显示的声明了要调用父类的方法,那么声明方法的时候,就包装成一个内部调用父类方法且返回相同值的函数,给当前类的方法。

另一方面,构造方法,也是比较灵活的。如果显示的声明了initialize,那么这就是构造方法。否则如果参数是个function那么它就做为构造方法,否则就用父类的构造方法。

通过statics方式添加静态方法,通过实例的implements和静态方法methods添加实例方法。
通过父类的extend实现继承。
同时,类库为commonJS和浏览环境都提供了支持!


代码如下:

/**
*Klass.js-copyright@dedfat
*version1.0
*https://github.com/ded/klass
*Followoursoftwarehttp://twitter.com/dedfat:)
*MITLicense
*/
!function(context,f){
//fnTest用来验证是否可能通过正则找出调用super父类方法的方法
varfnTest=/xyz/.test(function(){xyz;})?/\bsupr\b/:/.*/,
noop=function(){},
proto='prototype',
isFn=function(o){
returntypeofo===f;
};
//基础类
functionklass(o){
returnextend.call(typeofo==f?o:noop,o,1);
}
//包装成一个借用super同名方法的函数
functionwrap(k,fn,supr){
returnfunction(){
//缓存原this.super
vartmp=this.supr;
//暂把this.super改造成借用super的同名方法above
//供o里显式的声明(fnTest.text(fn)==true)要借用super的同名方法使用
this.supr=supr[proto][k];
//借用执行并保存返回值
varret=fn.apply(this,arguments);
//恢复原this.super
this.supr=tmp;
//返回返回值,保证wrap后的返回值跟原来一致
returnret;
};
}
//如果o和super有同名方法,且o显式声明借用super的同名方法,就wrap成一个待执行函数供使用
//如果没有显式的声明借用super的同名方法,或者是o独有的方法,或者不是方法就直接用
functionprocess(what,o,supr){
for(varkino){
//如果是非继承方法,按方法注释规则执行,最终都放进what
if(o.hasOwnProperty(k)){
what[k]=typeofo[k]==f
&&typeofsupr[proto][k]==f
&&fnTest.test(o[k])
?wrap(k,o[k],supr):o[k];
}
}
}
//继承方法的实现,fromSub是用来控制是否继承而来,上面的klass里面fromSub是1,表明非继承而来,构造函数不借用super执行
functionextend(o,fromSub){
//noop做为媒介类实现原型继承的解除引用
noop[proto]=this[proto];
varsupr=this,
prototype=newnoop(),//创建实例对象供原型继承使用,解除引用
isFunction=typeofo==f,
_constructor=isFunction?o:this,//如果o是一个构造方法就用,否则由this来决定构造函数
_methods=isFunction?{}:o,//如果o是一个{...}应该用methods放到fn原型里,如果里面有initialize就是构造函数,如果o是函数就由上面_constructor决定o是构造函数
fn=function(){//因为kclass借助了kclass,所以最终实际上返回的就是fn,fn其实就新类的构造函数
//1如果o是{...}就会被methods直接过滤并添加到fn的原型里,如果o里面有initialize,那么fn的原型里就有initialize,那么它就是构造方法
//2如果o是function,methods什么也添加不到fn的原型里,但是_constructor会接受o当构造函数
//3如果o是{....},同时里面也没有initialize,那么就是this当构造函数,如果在klass里由call决定,显然构造函数是noop,如果在非基础类里,构造函数就是父类的构造函数
//由于o不是函数不会自动调用父类的构造函数,只是把父类的构造函数当做当前类的构造函数----这都是由于this的指向决定的
console.log(this);
if(this.initialize){
this.initialize.apply(this,arguments);
}else{
//调用父类构造方法
//如上面3,o不是函数,不会调用父类的构造方法
//基础类无父类,不会调用父类构造方法
fromSub||isFn(o)&&supr.apply(this,arguments);
//调用本类构造方法
//参考上面2,3要么是noop要么是o
console.log(_constructor==noop);
_constructor.apply(this,arguments);
}
};
//构造原型方法的接口
fn.methods=function(o){
process(prototype,o,supr);
fn[proto]=prototype;
returnthis;
};
//执行实现新类原型,保证新类的constructor
fn.methods.call(fn,_methods).prototype.constructor=fn;
//保证新类可以被继承
fn.extend=arguments.callee;
//添加实例方法或者静态方法,statics:静态方法,implement实例方法
fn[proto].implement=fn.statics=function(o,optFn){
//保证o是一个object对象,如果o是一个字符串,那么就是添一个方法的情况,如果o是一个object对象说明是批量添加的
//因为要从o里面拷贝
o=typeofo=='string'?(function(){
varobj={};
obj[o]=optFn;
returnobj;
}()):o;
//添加实例方法或者静态方法,statics:静态方法,implement实例方法
process(this,o,supr);
returnthis;
};
returnfn;
}
//后台用,nodejs
if(typeofmodule!=='undefined'&&module.exports){
module.exports=klass;
}else{
varold=context.klass;
//防冲突
klass.noConflict=function(){
context.klass=old;
returnthis;
};
//前台浏览器用
//window.kclass=kclass;
context.klass=klass;
}
}(this,'function');

三、还有一种简单实现
实现思路很简单,就是利用ECMAScript5原型式继承Object.create方法,封装成一个方法,如果不支持ECMAScript5的环境,就平移退化到


代码如下:

functionF(){};
F.prototype=superCtor.prototype;
ctor.prototype=newF();
ctor.prototype.constructor=ctor;

同样的,除最后一个参数是当前类的方法声明,其它参数均做为继承父类,需要循环继承,但当这里处理的相对比较简单,没涉及到覆盖。你可以自己动手添加。


代码如下:

varClass=(function(){
/**
*Inheritsfunction.(node.js)
*
*@paramctorsubclass'sconstructor.
*@paramsuperctorsuperclass'sconstructor.
*/
varinherits=function(ctor,superCtor){
//显式的指定父类
ctor.super_=superCtor;
//ECMAScript5原型式继承并解除引用
if(Object.create){
ctor.prototype=Object.create(superCtor.prototype,{
constructor:{
value:ctor,
enumerable:false,
writable:true,
configurable:true
}
});
}else{
//无Object.create方法的平稳退化
functionF(){};
F.prototype=superCtor.prototype;
ctor.prototype=newF();
ctor.prototype.constructor=ctor;
}
};
/**
*Classfunction.
*/
returnfunction(){
//最后一个参数是新类方法、属性和构造函数声明
varsubClazz=arguments[arguments.length-1]||function(){};
//initialize是构造函数,否构造函数就是一个空函数
varfn=subClazz.initialize==null?function(){}:subClazz.initialize;
//继承除最一个参数以的类,多继承,也可以用作扩展方法
for(varindex=0;index<arguments.length-1;index++){
inherits(fn,arguments[index]);
}
//实现新类的方法
for(varpropinsubClazz){
if(prop=="initialize"){
continue;
}
fn.prototype[prop]=subClazz[prop];
}
returnfn;
}
})();

看下面实例:


代码如下:

/**
*ThedefinitionofCatClass.
*/
varCat=Class({
/**
*Constructor.
*
*@paramnameCat'sname
*/
initialize:function(name){
this.name=name;
},
/**
*Eatfunction.
*/
eat:function(){
alert(this.name+"iseatingfish.");
}
});
/**
*ThedefinitionofBlackCatClass.
*/
varBlackCat=Class(Cat,{
/**
*Constructor.
*
*@paramnameCat'sname.
*@paramageCat'sage.
*/
initialize:function(name,age){
//calltheconstructorofsuperclass.
BlackCat.super_.call(this,name);
this.age=age;
},
/**
*Eatfunction.
*/
eat:function(){
alert(this.name+"("+this.age+")iseatingdog.");
}
});
/**
*ThedefinitionofBlackFatCatClass.
*/
varBlackFatCat=Class(BlackCat,{
/**
*Constructor.
*
*@paramnameCat'sname.
*@paramageCat'sage.
*@paramweightCat'sweight.
*/
initialize:function(name,age,weight){
//calltheconstructorofsuperclass.
BlackFatCat.super_.call(this,name,age);
this.weight=weight;
},
/**
*Eatfunction.
*/
eat:function(){
alert(this.name+"("+this.age+")iseatingdog.Myweight:"+this.weight);
}
});
/**
*ThedefinitionofDogClass.
*/
varDog=Class({});
varcat=newBlackFatCat("John",24,"100kg");
cat.eat();
//true
alert(catinstanceofCat);
//true
alert(catinstanceofBlackCat);
//true
alert(catinstanceofBlackFatCat);
//true
alert(cat.constructor===BlackFatCat);
//false
alert(catinstanceofDog);

四、mootools类库的Class
源码解析可以看这里:http://www.cnblogs.com/hmking/archive/2011/09/30/2196504.html
看具体用法:
a、新建一个类


代码如下:

varCat=newClass({
initialize:function(name){
this.name=name;
}
});
varmyCat=newCat('Micia');
alert(myCat.name);//alerts'Micia'
varCow=newClass({
initialize:function(){
alert('moooo');
}
});

b、继承的实现


代码如下:

varAnimal=newClass({
initialize:function(age){
this.age=age;
}
});
varCat=newClass({
Extends:Animal,
initialize:function(name,age){
this.parent(age);//callsinitalizemethodofAnimalclass
this.name=name;
}
});
varmyCat=newCat('Micia',20);
alert(myCat.name);//alerts'Micia'.
alert(myCat.age);//alerts20.

c、扩充类的实现


代码如下:

varAnimal=newClass({
initialize:function(age){
this.age=age;
}
});
varCat=newClass({
Implements:Animal,
setName:function(name){
this.name=name
}
});
varmyAnimal=newCat(20);
myAnimal.setName('Micia');
alert(myAnimal.name);//alerts'Micia'.

五、悟透javascript:语法甘露
先看用法实例
a、创建类


代码如下:

//创建类Person
varPerson=Class(object,{
Create:function(name,age){
this.name=name;
this.age=age;
},
SayHello:function(){
alert("Hello,I'm"+this.name+","+this.age+"yearsold.");
}
});
varBillGates=New(Person,["BillGates",53]);
BillGates.SayHello();

b、继承类


代码如下:

//Employee继承Person
varEmployee=Class(Person,{
Create:function(name,age,salary){
Person.Create.call(this,name,age);
//调用基类的构造函数
this.salary=salary;
},
ShowMeTheMoney:function(){
alert(this.name+"$"+this.salary);
}
});
varSteveJobs=New(Employee,["SteveJobs",53,1234]);
SteveJobs.SayHello();
SteveJobs.ShowMeTheMoney();

下面是源码分析:显然,多了一个New方法,创建类和新建类的实例都被巧妙的封装了。形成了一个有意义的整体!还有一点不同的地方,所有的类都基于字面量,而不是基于函数。代码很简短,但其中原理却很丰富也很巧妙,可以细细品味一番!


代码如下:

//创建类的函数,用于声明类及继承关系
functionClass(aBaseClass,aClassDefine){
//创建类的临时函数壳
functionclass_(){
this.Type=aBaseClass;
//我们给每一个类约定一个Type属性,引用其继承的类
for(varmemberinaClassDefine)
this[member]=aClassDefine[member];
//复制类的全部定义到当前创建的类
};
class_.prototype=aBaseClass;
returnnewclass_();
};
//创建对象的函数,用于任意类的对象创建
functionNew(aClass,aParams){
//创建对象的临时函数壳
functionnew_(){
this.Type=aClass;
//我们也给每一个对象约定一个Type属性,据此可以访问到对象所属的类
if(aClass.Create)
aClass.Create.apply(this,aParams);
//我们约定所有类的构造函数都叫Create,这和DELPHI比较相似
};
new_.prototype=aClass;
returnnewnew_();
};

由于写的比较笼统,可能有很多地方没有解析到,也可能有不准确的地方,还望指正。
看完上面几种解析,相信息自己也可以写出一个自己的封装类库出来,至于,怎么实现看个人喜好了。但基本的思都是一样的基于原型的继承方式和循环拷贝新方法。

原文来自:穆乙 http://www.cnblogs.com/pigtail/

(0)

相关推荐

  • Javascript封装id、class与元素选择器方法示例

    由于各个浏览器都支持的选择方法只有如下三种: 1.document.getElementById() 2.document.getElementsByName() 3.document.getElementsByTagName() 所以在封装选择器的时候要考虑浏览器的兼容性. 示例代码如下: <script>//封装id选择器 function $(selector){ var c=selector.substring(0,1);//获取第一个字符 if(c=="#"){

  • 详解js中class的多种函数封装方法

    本文实例讲解了js中class的多种函数封装方法,分享给大家供大家参考,具体内容如下 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>关于class的多种函数封装</title> <style> body{ margin: 0; } li{ height: 20px; } </style

  • JS封装通过className获取元素的函数示例

    本文实例讲述了JS封装通过className获取元素的函数.分享给大家供大家参考,具体如下: <div id="box"> <div class="star"></div> <div class="star"></div> <div class="app"></div> <p class="star"></

  • Node.js中对通用模块的封装方法

    在Node.js中对模块载入和执行进行了包装,使得模块文件中的变量在一个闭包中,不会污染全局变量,和他人冲突. 前端模块通常是我们开发人员为了避免和他人冲突才把模块代码放置在一个闭包中. 如何封装Node.js和前端通用的模块,我们可以参考Underscore.js 实现,他就是一个Node.js和前端通用的功能函数模块,查看代码: 复制代码 代码如下: // Create a safe reference to the Underscore object for use below.  var

  • Javascript 面向对象(二)封装代码

    写个小例子: 第一步:做一个"手机的类" 复制代码 代码如下: var MobilePhone = (function(){ ---- })() 第二步:考虑这个类,里需要那些类的私有属性,这里我想定义的是实例出来手机的数量 复制代码 代码如下: var MobilePhone = (function(){ //私有属性 var count = 0; //代表手机的数量 })() 第三步:创建一个构造函数,即实例时候,对产生的新象的一个初始化,例如属性,方法的初始化;在这个例子中,每一

  • JS类的封装及实现代码

    1. 定义js类 js并不是一种面向对向的语言, 没有提供对类的支持, 因此我们不能像在传统的语言里那样 用class来定义类, 但我们可以利用js的闭包封装机制来实现js类, 我们来封装一个简的Shape类. 复制代码 代码如下: function ShapeBase() { this.show = function() { alert("ShapeBase show"); }; this.init = function(){ alert("ShapeBase init&q

  • javascript面向对象包装类Class封装类库剖析

    javascript是个入门门槛很低的语言,甚至一个从来没有接触过javascript的技术人员,几小时内就可以写出一个简单有用的程序代码. 但是如果因此你就下结论:javascript是门简单的语言.那你就大错特错了.想写出高性能的代码,同样需要具备一个高级程序员的基本素养. 一个java或者c++程序员,不一定能写出高性能的javascript代码,但更容易写出高性能的javascript代码. javascript的简单是基于它"胸襟广阔"的包容性.它声明时,不需要指定类型,甚至

  • 详解JavaScript面向对象实战之封装拖拽对象

    目录 概述 1.如何让一个DOM元素动起来 2.如何获取当前浏览器支持的transform兼容写法 3.如何获取元素的初始位置 5.我们需要用到哪些事件? 6.拖拽的原理 7. 我又来推荐思维导图辅助写代码了 8.代码实现 part1.准备工作 part2.功能函数 part3.声明三个事件的回调函数 9.封装拖拽对象 概述 为了能够帮助大家了解更多的方式与进行对比,我会使用三种不同的方式来实现拖拽. 不封装对象直接实现: 利用原生JavaScript封装拖拽对象: 通过扩展jQuery来实现拖

  • JavaScript面向对象中的封装和继承你了解吗

    目录 1.面向对象 1.封装 2.原型对象 3.继承 总结 1.面向对象 [三大显著特征]: 封装.继承.多态 1.封装 [解释]: 封装的本质就是将有关联的代码组合在一起. [优势]: 保证代码可以复用提高代码的维护效率 [以前的封装方法]: 函数封装 function fn(){} 命名空间封装 let o={ name:'zhangsan', age:20 } let obj={ name:'lisi', age:18 } [新的封装方法]: 构造函数 //自定义构造函数 function

  • javascript 面向对象全新理练之数据的封装

    今天主要讨论如何在 JavaScript 脚本中实现数据的封装(encapsulation).数据封装说的简单点就是把不希望调用者看见的内容隐藏起来.它是面向对象程序设计的三要素之首,其它两个是继承和多态,关于它们的内容在后面再讨论. 关于数据封装的实现,在 C++.Java.C# 等语言中是通过 public.private.static 等关键字实现的.在 JavaScript 则采用了另外一种截然不同的形式.在讨论如何具体实现某种方式的数据封装前,我们先说几个简单的,大家所熟知却又容易忽略

  • 深入剖析JavaScript面向对象编程

    二. Javascript 面向对象编程:构造函数的继承 本节主要介绍,如何生成一个"继承"多个对象的实例. 比如,现在有一个"动物"对象的构造函数, function Animal(){ this.species = "动物"; } 还有一个"猫"对象的构造函数, function Cat(name,color){ this.name = name; this.color = color; } 怎样才能使"猫&qu

  • Javascript 面向对象编程(一) 封装

    学习Javascript,最难的地方是什么? 我觉得,Object(对象)最难.因为Javascript的Object模型很独特,和其他语言都不一样,初学者不容易掌握. 下面就是我的学习笔记,希望对大家学习这个部分有所帮助.我主要参考了以下两本书籍: <面向对象的Javascript>(Object-Oriented JavaScript) <Javascript高级程序设计(第二版)>(Professional JavaScript for Web Developers, 2nd

  • javascript 面向对象编程基础:封装

    很长一段时间以来(这里本人要幸灾乐祸地说),js是"一种点缀的作用,完成很有限的功能,诸如表单验证之类,其语言本身也一直被当作过程化的语言使用,很难完成复杂的功能.".但是(这里本人要苦大仇深.痛心疾首地说),"而Ajax的出现使得复杂脚本成为必需的组成部分,这就对 JavaScript 程序设计提出了新的要求,很多Ajax应用开始利用JavaScript面向对象的性质进行开发,使逻辑更加清晰.事实上,JavaScript 提供了完善的机制来实现面向对象的开发思想."

  • javascript 面向对象封装与继承

    整理一下js面向对象中的封装和继承. 1.封装 js中封装有很多种实现方式,这里列出常用的几种. 1.1 原始模式生成对象 直接将我们的成员写入对象中,用函数返回. 缺点:很难看出是一个模式出来的实例. 代码: 复制代码 代码如下: function Stu(name, score) {             return {                 name: name,                 score: score             }         }    

  • javascript面向对象三大特征之封装实例详解

    本文实例讲述了javascript面向对象三大特征之封装.分享给大家供大家参考,具体如下: 封装 封装(Encapsulation):就是把对象内部数据和操作细节进行隐藏.很多面向对象语言都支持封装特性,提供关键字如private来隐藏某些属性和方法.要想访问被封装对象中的数据,只能使用对象专门提供的对外接口,这个接口一般为方法.调用该方法能够获取对象内部数据. 在JavaScript语言中没有提供专门的信息封装关键字,不过可以使用闭包来创建,只允许从对象内部访问的方法和属性.另外,接口也是数据

  • JavaScript面向对象三个基本特征实例详解【封装、继承与多态】

    本文实例讲述了JavaScript面向对象三个基本特征.分享给大家供大家参考,具体如下: 了解过面向对象的同学应该都知道,面向对象三个基本特征是:封装.继承.多态,但是对于这三个词具体可能不太了解.对于前端来讲接触最多的可能就是封装与继承,对于多态来说可能就不是那么了解了. 封装 在说封装之先了解一下封装到底是什么? 什么是封装 封装:将对象运行所需的资源封装在程序对象中--基本上,是方法和数据.对象是"公布其接口".其他附加到这些接口上的对象不需要关心对象实现的方法即可使用这个对象.

随机推荐