面向对象
抽象:抓住核心问题
封装:只能通过对象来访问方法
继承:从已有对象上继承新的对象
多态:多对象的不同形态
对象的组成:方法和属性
//var obj = {};
var obj = new Object();
obj.name = '小明';
obj.showName = function(){
alert(this.name);
};
obj.showName();
优化上面的代码,工厂方式(封装函数)
function createPerson(name){
// 1.原料
var obj = new Object();
// 2.加工
obj.name = name;
obj.showName = function(){
alert(this.name);
};
// 3.出厂
return obj;
}
var p1 = createPerson('小明');
p1.showName();
var p2 = createPerson('小强');
p2.showName();
改成和系统对象一样
//原型:去改写对象下面公用的方法或属性,让其在内存中只存在一份(提高性能)
function CreatePerson(name){
this.name = name;
}
//之所以把方法加在原型上是为了解决p1.showName != p2.showName的问题
CreatePerson.prototype.showName = function(){
alert(this.name);
};
//当new去调用一个函数,这个时候函数中得this就是创建出来的对象,而且函数的返回值直接就是this
var p1 = new CreatePerson('小明');
p1.showName();
var p2 = new CreatePerson('小强');
p2.showName();
面向对象的选项卡
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> <style> #div1,#div2{ width: 200px; margin: 20px auto; } #div1 .active,#div2 .active{ background-color: yellow; } #div1 div,#div2 div{ width: 200px; height: 200px; background-color: pink; color: black; display: none } </style> </head> <body> <div id="div1"> <input class="active" type="button" value="1"> <input type="button" value="2"> <input type="button" value="3"> <div style="display:block;">111</div> <div>222</div> <div>333</div> </div> <div id="div2"> <input class="active" type="button" value="1"> <input type="button" value="2"> <input type="button" value="3"> <div style="display:block;">111</div> <div>222</div> <div>333</div> </div> <script> function Tab(id){ this.oDiv = document.getElementById(id); this.aInput = this.oDiv.getElementsByTagName('input'); this.aDiv = this.oDiv.getElementsByTagName('div'); this.iNow = 0; } Tab.prototype.init = function(){ var This = this; for(var i = 0;i<this.aInput.length;i++){ this.aInput[i].index = i; this.aInput[i].onclick = function(){ This.iNow = this.index; This.change(this); }; } }; Tab.prototype.change = function(obj){ for(var i = 0;i<this.aInput.length;i++){ this.aInput[i].className = ""; this.aDiv[i].style.display="none"; } obj.className = "active"; this.aDiv[obj.index].style.display = 'block'; }; Tab.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'; },2000); }; var tab1 = new Tab('div1'); tab1.init(); var tab2 = new Tab('div2'); tab2.init(); tab2.autoPlay(); </script> </body> </html>
面向对象的拖拽
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> <style> *{ margin: 0; padding: 0; } #div1,#div2{ width: 100px; height: 100px; position: absolute; top: 0; cursor: pointer; } #div1{ left: 0; background-color: red; } #div2{ left: 300px; background-color: yellow; } </style> </head> <body> <div id="div1"></div> <div id="div2"></div> <script> function Drag(id){ this.oDiv = document.getElementById(id); this.disX = 0; this.disY = 0; } Drag.prototype.init = function(){ var This = this; this.oDiv.onmousedown = function(ev){ var oEvent = ev||event; This.fnDowm(oEvent); return false; }; }; Drag.prototype.fnDowm = function(ev){ this.disX = ev.clientX - this.oDiv.offsetLeft; this.disY = ev.clientY - this.oDiv.offsetTop; var This = this; document.onmousemove = function(ev){ var oEvent = ev||event; This.fnMove(oEvent); }; document.onmouseup = this.fnUp;//这里有风险 }; Drag.prototype.fnMove = function(ev){ var x = ev.clientX - this.disX; var y = ev.clientY - this.disY; this.oDiv.style.left = x + "px"; this.oDiv.style.top = y + "px"; }; Drag.prototype.fnUp = function(){ document.onmousemove = document.onmouseup = null; }; var drag1 = new Drag('div1'); drag1.init(); var drag2 = new Drag('div2'); drag2.init(); </script> </body> </html>
.......................................................................
包装对象:基本类型都有自己对应的包装对象,例如String/Number/Boolean
原型链:实例对象与原型之间的链接
// hasOwnProperty()Object上的东西,看是不是对象自身下面的属性
var arr = [];
arr.num = 10;
Array.prototype.num2 = 20;
alert(arr.hasOwnProperty('num'));
alert(arr.hasOwnProperty('num2'));
alert(a1.hasOwnProperty == Object.prototype.hasOwnProperty); //证明是Obect上的,而非Array上的
关于constructor
// constructor查看实例对象的构造函数,每个对象会自动在原型上添加constructor指向对象
function Aaa(){
}
Aaa.prototype.constructor = Aaa; //程序自动生成
var a1 = new Aaa();
alert(a1.constructor);
alert(a1.hasOwnProperty == Object.prototype.hasOwnProperty); //Obect上的
var arr = [];
alert(arr.constructor == Array); //利用constructor判断是不是数组
function Aaa(){
}
//是添加,constructor是默认自带的Aaa
Aaa.prototype.name = '小明';
Aaa.prototype.age = 20;
//是赋值,会把Aaa.prototype.constructor覆盖掉,constructor是最顶端Object
Aaa.prototype = {
'constructor':Aaa, //解决办法
'name':'小明',
'age':20
};
var a1 = new Aaa();
alert(a1.constructor);
关于instanceof
// instanceof:对象与构造函数在原型链上是否有关系
function Aaa(){
}
var a1 = new Aaa();
alert(a1 instanceof Aaa);
var arr = [];
alert(arr instanceof Array); //利用instanceof做类型判断
类型判断最好的办法toString()
//toString:把对象转成字符串,系统对象下都是自带的,自己写的都是通过原型链找的
var arr = [];
alert(arr.toString == Object.prototype.toString);//系统对象false
function Aaa(){
}
var a1 = new Aaa();
alert(a1.toString == Object.prototype.toString);//自己写的true
var arr = [];
alert(Object.prototype.toString.call(arr) == '[object Array]');
继承:属性继承用call,方法用拷贝继承
//继承:在原有对象的基础上略作修改得到一个新的对象且不影响原有对象的功能
function CreatePerson(name,sex){ //父类
this.name = name;
this.sex = sex;
}
CreatePerson.prototype.showName = function(){
alert(this.name);
};
var p1 = new CreatePerson('小明','男');
p1.showName();
function CreateStar(name,sex,job){ //子类
//this实例对象
CreatePerson.call(this,name,sex);
this.job = job;
}
CreateStar.prototype = CreatePerson.prototype;
CreateStar.prototype.showJob = function(){}; //p1也会有,影响到父类了
var p2 = new CreateStar('黄晓明','男','演员');
p2.showName();
解决上面继承后影响父类的问题,拷贝继承
var a = {
'name':'小明'
};
var b = a;
b.name = '小强';
alert(a.name); //小强
// .........................
var a = {
'name':'小明'
};
var b = {};
for(var attr in a){
b[attr] = a[attr]; //基本类型的赋值
}
b.name = '小强';
alert(a.name); //小明
// .........................
function extend(obj1,obj2){ //封装一下
for(var attr in obj2){
obj1[attr] = obj2[attr];
}
}
var a = {
'name':'小明'
};
var b = {};
extend(b,a);
b.name = '小强';
alert(a.name); //小明
function CreatePerson(name,sex){ //父类
this.name = name;
this.sex = sex;
}
CreatePerson.prototype.showName = function(){
alert(this.name);
};
var p1 = new CreatePerson('小明','男');
p1.showName();
function CreateStar(name,sex,job){ //子类
//this实例对象
CreatePerson.call(this,name,sex);
this.job = job;
}
//CreateStar.prototype = CreatePerson.prototype;
extend(CreateStar.prototype,CreatePerson.prototype);
CreateStar.prototype.showJob = function(){}; //p1没有了,不会影响父类了
var p2 = new CreateStar('黄晓明','男','演员');
p2.showName();
继承的拖拽
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> <style> #div1,#div2{ width: 100px; height: 100px; cursor: pointer; position: absolute; } #div1{ left: 0; background-color: red; } #div2{ left: 100px; background-color: yellow; } </style> </head> <body> <div id="div1"></div> <div id="div2"></div> <script> function Drag(id){ this.oDiv = document.getElementById(id); this.disX = 0; this.disY = 0; } Drag.prototype.init = function(){ var This = this; this.oDiv.onmousedown = function(ev){ var oEvent = ev || event; This.fnDown(oEvent); document.onmousemove = function(ev){ var oEvent = ev || event; This.fnMove(oEvent); }; document.onmouseup = function(){ This.fnUp(); }; return false; }; }; Drag.prototype.fnDown = function(ev){ this.disX = ev.clientX - this.oDiv.offsetLeft; this.disY = ev.clientY - this.oDiv.offsetTop; }; Drag.prototype.fnMove = function(ev){ var x = ev.clientX - this.disX; var y = ev.clientY - this.disY; this.oDiv.style.left = x + "px"; this.oDiv.style.top = y+ "px"; }; Drag.prototype.fnUp = function(){ document.onmousemove = document.onmouseup = null; }; function ChildDrag(id){ Drag.call(this,id);//属性call } function extend(obj1,obj2){//方法拷贝继承 for(var attr in obj2){ obj1[attr] = obj2[attr]; } } extend(ChildDrag.prototype,Drag.prototype); ChildDrag.prototype.fnMove = function(ev){ var x = ev.clientX - this.disX; var y = ev.clientY - this.disY; if(x < 0){ x = 0; } else if(x > document.documentElement.clientWidth - this.oDiv.offsetWidth){ x = document.documentElement.clientWidth - this.oDiv.offsetWidth; } if(y < 0){ y = 0; } else if(y > document.documentElement.clientHeight - this.oDiv.offsetHeight){ y = document.documentElement.clientHeight - this.oDiv.offsetHeight; } this.oDiv.style.left = x + "px"; this.oDiv.style.top = y+ "px"; }; window.onload = function(){ var d1 = new Drag("div1"); d1.init(); var d2 = new ChildDrag("div2"); d2.init(); }; </script> </body> </html>
类式继承:利用构造函数继承的方式
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> </head> <body> <script> //类式继承:利用构造函数继承的方式 //原型继承:借助原型来实现对象继承对象 function Aaa(){ //父类 this.name = '小明'; } Aaa.prototype.showName = function(){ alert(this.name); }; function Bbb(){ //子类 Aaa.call(this); //属性还是需要call办法继承 } //避免属性继承,只继承showName,画画原型链就明白 var F = function(){}; //解决当Aaa中得属性为对象时的问题即避免属性继承 F.prototype = Aaa.prototype; Bbb.prototype = new F(); Bbb.prototype.constructor = Bbb; //修正指向 var b1 = new Bbb(); b1.showName(); </script> </body> </html>
原型继承:借助原型来实现对象继承对象
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> </head> <body> <script> var a = { 'name':'小明' }; var b = cloneObj(a); b.name = '小强'; alert(b.name); function cloneObj(obj){ var F = function(){}; F.prototype = obj; return new F(); } </script> </body> </html>