JS面向对象编程(转载)
什么是面向对象编程(OOP)?用对象的思想去写代码,就是面向对象编程。
面向对象编程的特点
- 抽象:抓住核心问题
- 封装:只能通过对象来访问方法
- 继承:从已有对象上继承出新的对象
- 多态:多对象的不同形态
对象的组成
- 属性:对象下面的变量叫做对象的属性
- 方法:对象下面的函数叫做对象的方法
var arr = [];
arr.number = 10; //对象下面的变量:叫做对象的属性 //alert( arr.number );
//alert( arr.length ); arr.test = function(){ //对象下面的函数 : 叫做对象的方法
alert(123);
}; arr.test();//方法 arr.push();//方法
arr.sort();
创建一个对象
var obj=new Object();//创建一个空的对象
obj.name='小明'; //属性
obj.showName=function(){ //方法
alert(this.name);//this指向obj
}
obj.showName();//小明
如果需要创建两个或多个对象
var obj1=new Object();//创建一个空的对象
obj1.name='小明'; //属性
obj1.showName=function(){ //方法
alert(this.name);//this指向obj
}
obj1.showName();//小明 var obj2=new Object();//创建一个空的对象
obj2.name='小灰'; //属性
obj2.showName=function(){ //方法
alert(this.name);//this指向obj
}
obj2.showName();//小灰
使用Object函数或对象字面量都可以创建面向对象,但需要创建多个对象时,会产生大量的重复代码,可通过工厂方式来解决这个问题
工厂方式 -------------------- 面向对象中的封装函数
//工厂方式 : 封装函数 function createPerson(name){
var obj = new Object();
obj.name = name;
obj.showName = function(){
alert( this.name );
}; return obj;
} var p1 = createPerson('小明');
p1.showName();
var p2 = createPerson('小强');
p2.showName();
创建对象用工厂方式来实现,可以传递参数,由于创建对象都是使用Object的原生构造函数来实现的,因此无法识别对象类型
构造函数模式 -------------------- 给一个对象添加方法
//new 后面调用的函数叫构造函数
function CreatePerson(name){
this.name=name;
this.showName=function(){
alert(this.name);
}
}
var p1=new CreatePerson('小明');//当new去调用一个函数时,函数中的this就是创建出来的对象而函数中的返回值就是this
p1.showName();
var p2=new CreatePerson('小强');
p2.showName();
使用自定义的构造函数,定义对象类型的属性和方法,与工厂方式的区别:
- 没有显式的创建对象
- 直接将属性和方法赋给this对象
- 没有return语句
上面例子中:CreatePerson构造函数生成的两个对象p1与p2都是CreatePerson的实例
虽然构造函数解决了上面工厂方式的问题,但是它一样存在缺点,就是在创建对象时,每个对象都有一套自己的方法,每定义一个函数都实例化了一个对象
例如:
function CreatePerson(name){ this.name = name;
this.showName = function(){
alert( this.name );
}; } var p1 = new CreatePerson('小明');
//p1.showName();
var p2 = new CreatePerson('小强');
//p2.showName(); alert( p1.showName == p2.showName ); //false 它们的值相同,地址不同
测试例子中的p1.showName与p2.showName是否会相等,弹出的结果是false,说明p1和p2实例都包含一个不同的showName实例
再来举几个例子:
var a = [1,2,3];
var b = [1,2,3]; alert( a == b ); //false 值相同,地址不同 var a = 5;
var b = a;
b += 3
alert(b); //8
alert(a); //5 基本类型 : 赋值的时候只是值的复制
var a = [1,2,3];
var b = a;
b.push(4);
alert(b); //[1,2,3,4]
alert(a); //[1,2,3,4] 对象类型 : 赋值不仅是值的复制,而且也是引用的传递
var a = [1,2,3];
var b = a;
b = [1,2,3,4];
alert(b); //[1,2,3,4]
alert(a); //[1,2,3]
对比上面的几个例子,不难看出基本类型和对象类型的区别了,对象类型的赋值不仅是值的复制,也是引用的传递;提到了对象的引用应该很清楚上述p1.showName==p2.showName为何会返回结果是false
原型模式(prototype) -------------------- 给一类对象添加方法
原型(prototype):重写对象下面公用的属性或方法,让公用的属性或方法在内存中只存在一份(提高性能),也就是说所有在原型对象中创建的属性或方法都直接被所有对象实例共享。
- 原型:类比css中的class
- 普通方法:类比css中的style
var arr = [1,2,3,4,5];
var arr2 = [2,2,2,2,2]; Array.prototype.sum = function(){//原型prototype : 要写在构造函数的下面
var result = 0;
for(var i=0;i<this.length;i++){
result += this[i];
}
return result;
}; alert( arr.sum() ); //15
alert( arr2.sum() ); //10
原型优先级:如果在实例中添加了一个属性,而该属性与实例原型中的一个属性同名,该属性将会屏蔽原型中的那个属性
例子1:
var arr = [];
arr.number = 10;
Array.prototype.number = 20; alert(arr.number);//10
例子2:
Array.prototype.a=12;//原型属性
var arr=[1,2,3];
alert(arr.a);//12
arr.a=5;//实例属性
alert(arr.a);//5
工厂方式之原型
function CreatePerson(name){//普通方法
this.name=name;
}
CreatePerson.prototype.showName=function(){//原型
alert(this.name);
}
var p1=new CreatePerson('小明');
p1.showName();
var p2=new CreatePerson('小强');
p2.showName();
alert( p1.showName== p2.showName);//true
由上述例子中:p1.showName== p2.showName弹出的结果是true,可见原型解决了构造函数中“每定义一个函数都实例化了一个对象”的问题
原型的运用
选项卡实例:
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title>选项卡</title>
<style>
#div1 div{
width:400px;
height:300px;
border:1px solid #ccc;
overflow: hidden;
display: none;
margin: 15px 0;
}
#div1 input{
color: #fff;
width:100px;
height:40px;
background: darkseagreen;
border:none;
font-size: 14px;
letter-spacing: 5px;
}
#div1 p{
font-size: 20px;
line-height: 24px;
text-align: center;
color:darkgreen;
}
#div1 .title{
padding: 0;
font-weight: bold;
}
#div1 .active{
background:sandybrown;
color:#fff;
}
</style>
<script>
window.onload=function(){
var oDiv=document.getElementById('div1');
var aInput=oDiv.getElementsByTagName('input');
var aDiv=oDiv.getElementsByTagName('div');
var i=0; for(i=0;i<aInput.length;i++){
aInput[i].index=i;
aInput[i].onmousemove=function(){
for(var i=0;i<aInput.length;i++){
aInput[i].className='';
aDiv[i].style.display='none';
}
aInput[this.index].className='active';
aDiv[this.index].style.display='block';
}
}
} </script>
</head>
<body>
<div id="div1">
<input class="active" type="button" value="五言律诗">
<input type="button" value="七言律诗">
<input type="button" value="五言绝句">
<input type="button" value="七言绝句">
<div style="display: block;">
<p class="title">落 花</p>
<p class="author">李商隐</p>
<p>高阁客竟去,小园花乱飞。</p>
<p>参差连曲陌,迢递送斜晖。</p>
<p>肠断未忍扫,眼穿仍欲归。</p>
<p>芳心向春尽,所得是沾衣。</p>
</div>
<div>
<p class="title">蜀 相</p>
<p class="author">杜甫</p>
<p>丞相祠堂何处寻,锦官城外柏森森。</p>
<p>映阶碧草自春色,隔叶黄鹂空好音。</p>
<p>三顾频烦天下计,两朝开济老臣心。</p>
<p>出师未捷身先死,长使英雄泪满襟。</p>
</div>
<div>
<p class="title">八阵图</p>
<p class="author">杜甫</p>
<p>功盖三分国,名成八阵图。</p>
<p>江流石不转,遗恨失吞吴。</p>
</div>
<div>
<p class="title">泊秦淮</p>
<p class="author">杜牧</p>
<p>烟笼寒水月笼沙,夜泊秦淮近酒家。</p>
<p>商女不知亡国恨,隔江犹唱后庭花。</p>
</div>
</div>
</body>
</html>
效果(鼠标经过按钮时选项卡切换):效果图弄不上(技术欠缺。。。)
面向对象选项卡:
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title>选项卡</title>
<style>
#div1 div,#div2 div{
width:400px;
height:300px;
border:1px solid #ccc;
overflow: hidden;
display: none;
margin: 15px 0;
}
#div1 input,#div2 input{
color: #fff;
width:100px;
height:40px;
background: darkseagreen;
border:none;
font-size: 14px;
letter-spacing: 5px;
}
#div1 p,#div2 p{
font-size: 20px;
line-height: 24px;
text-align: center;
color:darkgreen;
}
#div1 .title,#div2 .title{
padding: 0;
font-weight: bold;
}
#div1 .active,#div2 .active{
background:sandybrown;
color:#fff;
}
</style>
<script>
window.onload=function(){
var t1=new TabSwitch('div1');
t1.switch();
var t2=new TabSwitch('div2');//面向对象的复用性
t2.switch();
t2.autoPlay();
/*alert(t2.switch==t1.switch);//ture*/
}
function TabSwitch(id){
this.oDiv=document.getElementById(id);
this.aInput=this.oDiv.getElementsByTagName('input');
this.aDiv=this.oDiv.getElementsByTagName('div');
this.iNow=0;//自定义属性 }
TabSwitch.prototype.switch=function(){//原型
for(var i=0;i<this.aInput.length;i++){
var This=this;//将指向面向对象的this保存下来
this.aInput[i].index=i;
this.aInput[i].onmousemove=function(){
This.tab(this);//This指向面向对象 this指向this.aInput[i]
}
}
}
TabSwitch.prototype.tab=function(obj){//原型
for(var i=0;i<this.aInput.length;i++){
this.aInput[i].className='';
this.aDiv[i].style.display='none';
}
this.aInput[obj.index].className='active';
this.aDiv[obj.index].style.display='block';
} //自动播放
TabSwitch.prototype.autoPlay=function(){
var This=this;
setInterval(function(){
if(This.iNow==This.aInput.length-1){
This.iNow=0;
}
else{
This.iNow++;
}
for(var i=0;i<This.aInput.length;i++){
This.aInput[i].className='';
This.aDiv[i].style.display='none';
}
This.aInput[This.iNow].className='active';
This.aDiv[This.iNow].style.display='block';
},1000);
}
</script>
</head>
<body>
<div id="div1">
<input class="active" type="button" value="五言律诗">
<input type="button" value="七言律诗">
<input type="button" value="五言绝句">
<input type="button" value="七言绝句">
<div style="display: block;">
<p class="title">落 花</p>
<p class="author">李商隐</p>
<p>高阁客竟去,小园花乱飞。</p>
<p>参差连曲陌,迢递送斜晖。</p>
<p>肠断未忍扫,眼穿仍欲归。</p>
<p>芳心向春尽,所得是沾衣。</p>
</div>
<div>
<p class="title">蜀 相</p>
<p class="author">杜甫</p>
<p>丞相祠堂何处寻,锦官城外柏森森。</p>
<p>映阶碧草自春色,隔叶黄鹂空好音。</p>
<p>三顾频烦天下计,两朝开济老臣心。</p>
<p>出师未捷身先死,长使英雄泪满襟。</p>
</div>
<div>
<p class="title">八阵图</p>
<p class="author">杜甫</p>
<p>功盖三分国,名成八阵图。</p>
<p>江流石不转,遗恨失吞吴。</p>
</div>
<div>
<p class="title">泊秦淮</p>
<p class="author">杜牧</p>
<p>烟笼寒水月笼沙,夜泊秦淮近酒家。</p>
<p>商女不知亡国恨,隔江犹唱后庭花。</p>
</div>
</div>
<div id="div2">
<input class="active" type="button" value="五言律诗">
<input type="button" value="七言律诗">
<input type="button" value="五言绝句">
<input type="button" value="七言绝句">
<div style="display: block;">
<p class="title">落 花</p>
<p class="author">李商隐</p>
<p>高阁客竟去,小园花乱飞。</p>
<p>参差连曲陌,迢递送斜晖。</p>
<p>肠断未忍扫,眼穿仍欲归。</p>
<p>芳心向春尽,所得是沾衣。</p>
</div>
<div>
<p class="title">蜀 相</p>
<p class="author">杜甫</p>
<p>丞相祠堂何处寻,锦官城外柏森森。</p>
<p>映阶碧草自春色,隔叶黄鹂空好音。</p>
<p>三顾频烦天下计,两朝开济老臣心。</p>
<p>出师未捷身先死,长使英雄泪满襟。</p>
</div>
<div>
<p class="title">八阵图</p>
<p class="author">杜甫</p>
<p>功盖三分国,名成八阵图。</p>
<p>江流石不转,遗恨失吞吴。</p>
</div>
<div>
<p class="title">泊秦淮</p>
<p class="author">杜牧</p>
<p>烟笼寒水月笼沙,夜泊秦淮近酒家。</p>
<p>商女不知亡国恨,隔江犹唱后庭花。</p>
</div>
</div>
</body>
</html>
效果(第二个选项卡加了一个自动切换功能):效果图弄不上(技术欠缺。。。)
面向对象中this的问题
一般会出现问题的情况有两种:
- 定时器
- 事件
例子1:
//定时器
function Aaa(){
var _this=this;//将当前this值保存
this.a=12;
setInterval(function(){//定时器中this指向window
_this.show();
},1000);
}
Aaa.prototype.show=function(){
alert(this.a);
}
var obj=new Aaa();//12
例子2:
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title>面向对象中this的问题-----事件</title>
<script>
function Bbb(){
var _this=this;
this.b=5;
document.getElementById('btn1').onclick=function(){//点击事件
_this.show();
}
}
Bbb.prototype.show=function(){ alert(this.b); }
window.onload=function(){
var p2=new Bbb();
}
</script>
</head>
<body>
<input id="btn1" type="button" value="按钮">
</body>
</html>
上面两个是分别对定时器和事件中this问题的解决方法,即将指向对象的this保存到了_this中,在嵌套函数中调用对象的方法或属性时用 _this.属性 或 _this.方法
再来个实例:
拖拽效果:
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title>最初写的拖拽效果</title>
<style>
#div1{
width:100px;
height:100px;
background: red;
position: absolute;
}
</style>
<script>
window.onload=function(){
var oDiv=document.getElementById('div1');
oDiv.onmousedown=function(ev){
var oEvent=ev||event;
var disX=0;
var disY=0;
var disX=oEvent.clientX-oDiv.offsetLeft;
var disY=oEvent.clientY-oDiv.offsetTop;
document.onmousemove=function(ev){
var oEvent=ev||event;
oDiv.style.left=oEvent.clientX-disX+'px';
oDiv.style.top=oEvent.clientY-disY+'px';
};
document.onmouseup=function(){
document.onmousemove=null;
document.onmouseup=null;
};
return false;
}
}
</script>
</head>
<body>
<div id="div1"></div>
</body>
</html>
面向对象的拖拽
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title>面向对象写的拖拽效果</title>
<style>
#div1{
width:100px;
height:100px;
background: red;
position: absolute;
}
</style>
<script>
window.onload=function(){
var p=new Darg('div1');
p.init(); }
function Darg(id){
this.oDiv=document.getElementById(id); //属性
this.disX=0;//属性
this.disY=0;//属性 }
Darg.prototype.init=function(){//原型 方法
var This=this;
this.oDiv.onmousedown=function(ev){
var oEvent=ev||event;
This.fnDown(oEvent);
return false;
}
}
Darg.prototype.fnDown=function(ev){//原型 方法
var This=this;
this.disX=ev.clientX-this.oDiv.offsetLeft;
this.disY=ev.clientY-this.oDiv.offsetTop;
document.onmousemove=function(ev){
var oEvent=ev||event;
This.fnMove(oEvent);
};
document.onmouseup=function(){
This.fnUp();
};
}
Darg.prototype.fnMove=function(ev){//原型
this.oDiv.style.left=ev.clientX-this.disX+'px';
this.oDiv.style.top=ev.clientY-this.disY+'px';
}
Darg.prototype.fnUp=function(){//原型
document.onmousemove=null;
document.onmouseup=null;
}
</script>
</head>
<body>
<div id="div1"></div>
</body>
</html>
效果(拖动红色方块可以移到任何位置): 效果图弄不上(技术欠缺。。。)
https://www.cnblogs.com/jnslove/p/7028487.html
上边是原网址
下面说说,目前对面向对象的理解:
自己有点感觉,js面向对象有点像 模块化思想,将一个通用方法封装到对象的通用方法内,谁想用就能用。如果做同类型的事,只是极个别属性不同,而且需要做大量这样同类型的事,那么用面向对象的方式写代码会比较省代码,因为不需要每一个细节代码都要重写一遍,只需要用对象里封装好的方法即可。占时是这样理解的。
下面说说,工厂模式、构造函数模式、原型链模式的异同,以及为什么诞生
我们创建对象时,里面的属性名相同,就是值有点差异,如果一个一个创建,显得有点耗时又费力,于是,我们把创建同类对象的方法封装起来,不同的值用参数传给这个封装方法,这样创建起来同类对象就非常方便快捷,这样的方式成为(工厂模式);
很明显,这样创建出来的对象,看不出来是属于什么类型的,为了解决这个问题,(构造函数模式)诞生了。构造函数的 函数名一眼就可以看出是什么类型的对象,但是它一样存在缺点,就是在创建对象时,每个对象都有一套自己的方法,每定义一个函数都实例化了一个对象,导致共用的方法和属性,在内存中存在很多份,比较占用内存,性能也可能随之降低。那么为了解决这个缺点,在构造函数的基础上,就诞生了(原型模式),我们将共用的方法和属性,在prototype原型上添加,让公用的属性或方法在内存中只存在一份(提高性能)。注意(如果在实例中添加了一个属性,而该属性与实例原型中的一个属性同名,该属性将会屏蔽原型中的那个属性)。
总之,按现在的理解,工厂模式、构造函数模式、原型链模式都是为了创建同类型对象而生。后面关于对象的继承以及多肽后面再介绍。
js面向对象、创建对象的工厂模式、构造函数模式、原型链模式的更多相关文章
-
JavaScript (JS) 面向对象编程 浅析 (含对象、函数原型链、闭包解析)
1. 构造函数原型对象:prototype ① 构造函数独立创建对象,消耗性能 function Person(name) { this.name = name; this.sayHello = fu ...
-
JavaScript提高篇之面向对象之单利模式工厂模型构造函数原型链模式
1.单例模式 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UT ...
-
前端开发:面向对象与javascript中的面向对象实现(二)构造函数与原型
前端开发:面向对象与javascript中的面向对象实现(二)构造函数与原型 前言(题外话): 有人说拖延症是一个绝症,哎呀治不好了.先不说这是一个每个人都多多少少会有的,也不管它究竟对生活有多么大的 ...
-
javascript基础学习系列-原型链模式
1.demo代码如下: 2.画图如下: 3.规则: 1)每一个函数数据类型(普通函数/类)都有一个天生自带的属性:prototype(原型),并且这个属性是一个对象数据类型的值 2)并且prototy ...
-
设计模式《JAVA与模式》之责任链模式
在阎宏博士的<JAVA与模式>一书中开头是这样描述责任链(Chain of Responsibility)模式的: 责任链模式是一种对象的行为模式.在责任链模式里,很多对象由每一个对象对其 ...
-
Java模式开发之责任链模式
Java模式开发之责任链模式 从击鼓传花谈起 击鼓传花是一种热闹而又紧张的饮酒游戏.在酒宴上宾客依次坐定位置,由一人击鼓.击鼓的地方与传花的地方是分开的.以示公正. 開始击鼓时,花束就開始依次传递,鼓 ...
-
【转】《JAVA与模式》之责任链模式
<JAVA与模式>之责任链模式 在阎宏博士的<JAVA与模式>一书中开头是这样描述责任链(Chain of Responsibility)模式的: 责任链模式是一种对象的行为模 ...
-
《JAVA与模式》之责任链模式
责任链模式是一种对象的行为模式.在责任链模式里,很多对象由每一个对象对其下家的引用而连接起来形成一条链.请求在这个链上传递,直到链上的某一个对象决定处理此请求.发出这个请求的客户端并不知道链上的哪一个 ...
-
《JAVA与模式》之责任链模式 【转载】
转载自java_my_life的博客 原文地址:http://www.cnblogs.com/java-my-life/archive/2012/05/28/2516865.html 在阎宏博士的&l ...
随机推荐
-
shell实现ping命令查看哪些主机在线
#!/bin/bash .{..};do -i 0.5 $a >/dev/null && echo "$a 在线" || echo "$a 离线&q ...
-
Shiro启用注解方式
shiro验证权限方式一种是基于url配置文件: 例如: <bean id="shiroFilter" class="org.apache.shiro.spring ...
-
微信公共服务平台开发(.Net 的实现)8-------处理图片(上传下载发送)
举个例子,有人对着我们的公共微信号拍个照片发送过来,然后我们处理这个照片,比如进行ocr识别字(随后就会降到这个例子),或者人脸识别,或者拍照取证等,这些功能都是相当有用的.那么我们现在就要分析一下这 ...
-
String中的Indexof,LastIndexOf, Indexofany,LastIndexOfAny 的区别
本文转载自 http://www.cnblogs.com/qinying/archive/2008/09/22/1295730.html 定位子串是指在一个字符串中寻找其中包含的子串或者某个字符.在S ...
-
java 反射 动态代理
在上一篇文章中介绍Java注解的时候,多次提到了Java的反射API.与javax.lang.model不同的是,通过反射API可以获取程序在运行时刻的内部结构.反射API中提供的动态代理也是非常强大 ...
-
MySQL视图,触发器,事务,存储过程,函数
create triggr triafterinsertcmdlog after insert on cmd_log FOR EACH ROW trigger_body .#NEW : 代表新的记录 ...
-
使用selenium时提示:ImportError:No module named selenium
问题分析: 用的是mac系统,已经通过sudo pip install -U selenium安装好了selenium, 但是无论用命令行还是用sublime导入selenium都会提示错误. 于是查 ...
-
安卓开发:UI组件-RadioButton和复选框CheckBox
2.5RadioButton 为用户提供由两个及以上互斥的选项组成的选项集. 2.5.1精简代码 在按钮变多之后,多次重复书写点击事件有些繁琐,我们在这里创建一个事件OnClick,每次点击时调用该事 ...
-
ThreadLocal详解,ThreadLocal源码分析,ThreadLocal图解
本文脉路: 概念阐释 ----> 原理图解 ------> 源码分析 ------> 思路整理 ----> 其他补充. 一.概念阐述. ThreadLocal 是一个为 ...
-
[译] 理解 LSTM(Long Short-Term Memory, LSTM) 网络
本文译自 Christopher Olah 的博文 Recurrent Neural Networks 人类并不是每时每刻都从一片空白的大脑开始他们的思考.在你阅读这篇文章时候,你都是基于自己已经拥有 ...