JS筆記加強版3
阿新 • • 發佈:2017-07-22
基本類型 加工 定義 cal 類對象 都是 函數 首字母 sna JS 面向對象及組件開發
JS的面向對象:
1、什麽是面向對象編程
用對象的思想去寫代碼,就是面向對象編程
過程式寫法
面向對象寫法
我們一直都在使用對象
數組 Array 時間 Date
var date = new Date();
var arr = new Array(); //[] //我們把系統自帶的對象,叫做系統對象
面向對象編程(OOP)的特點
抽象:抓住核心問題
封裝:只能通過對象來訪問方法
繼承:從已有對象上繼承出新的對象
多態:多對象的不同形態
2、對象的組成
方法(行為、操作)——函數:過程、動態的
屬性——變量:狀態、靜態的
var arr = [];
arr.number = 10; //對象下面的變量:叫做對象的屬性
arr.test = function(){ //對象下面的函數 : 叫做對象的方法
alert(123);
};
arr.test(); //123
3、創建第一個面向對象程序
為對象添加屬性和方法
Object對象
this指向
創建兩個對象 : 重復代碼過多
//var obj = {};
var obj = new Object(); //創建了一個空的對象
obj.name = ‘小明‘; //屬性
obj.showName = function(){ //方法
//alert(obj.name);
alert(this.name); // this指向的就是obj
};
obj.showName(); //小明
4、工廠方式
//工廠方式 : 面向對象中的封裝函數
function createPerson(name){
首字母大寫、New 關鍵字提取、This指向為新創建的對象
當new去調用一個函數 : 這個時候函數中的this就是創建出來的對象,而且函數的的返回值直接就是this(隱式返回)
構造函數:new後面調用的函數,即用來創建對象的函數,叫做構造函數
// CreatePerson()構造函數:
function CreatePerson(name){
//省略new Object和最後的return obj
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 ,值雖然相同,但是引用的 內存地址不同
存在的問題:對象的引用、浪費內存
7、原型-prototype
原型 : 重寫對象方法,讓相同方法在內存中存在一份。就是去改寫對象下面公用的方法或者屬性 , 讓公用的方法或者屬性在內存中存在一份 ( 提高性能 )
原型 : CSS中的class,可以重用,但優先級沒style高
普通方法 : CSS中的style,不可以重用,優先級高
即原型可以重用,但優先級沒有普通方法高。
var arr = [];
arr.number = 10;
Array.prototype.number = 20;
alert(arr.number); //10
普通方法:
var arr = [1,2,3,4,5];
var arr2 = [2,2,2,2,2];
arr.sum = function(){
var result = 0;
for(var i=0;i<this.length;i++){
result += this[i];
}
return result;
};
arr2.sum = function(){
var result = 0;
for(var i=0;i<this.length;i++){
result += this[i];
}
return result;
};
alert( arr.sum() ); //15
alert( arr2.sum() ); //10
原型方法 :
var arr = [1,2,3,4,5];
var arr2 = [2,2,2,2,2];
Array.prototype.sum = function(){
var result = 0;
for(var i=0;i<this.length;i++){
result += this[i];
}
return result;
};
alert( arr.sum() ); //15
alert( arr2.sum() ); //10
8、工廠方式之原型:面向對象的寫法:
原型prototype : 要寫在構造函數的下面
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
總結面向對象寫法:構造函數加屬性,原型加方法
function 構造函數(參數){
this.屬性 = 參數;
}
構造函數.prototype.方法 = function(){ ... };
調用寫法:
var 對象1 = new 構造函數();
對象1.方法();
9、面向對象的例子:
原則:
1)先寫出普通的寫法,然後改成面向對象寫法
2)普通方法變型
3)盡量不要出現函數嵌套函數
4)可以有全局變量
5)把onload中不是賦值的語句放到單獨函數中
改成面向對象:
1)全局變量就是屬性
2)函數就是方法
3)Onload中創建對象
4)改this指向問題
5)事件ev要放到事件函數中:
var ev = ev || window.event;
return false;
例子:面向對象的選項卡:
第一步:普通方法:
<script>
window.onload = function(){
//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(); 5、對象的引用 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]; // b又重新占了一個內存地址,和原來的無關 alert(b); //[1,2,3,4] alert(a); //[1,2,3] var a = 5; var b = 5; alert(a == b); //基本類型 : 值相同就可以 var a = [1,2,3]; var b = [1,2,3]; alert( a == b ); //false //對象類型 : 值和引用都相同才行 var a = [1,2,3]; var b = a; alert( a==b ); //true 6、工廠方式,構造函數的寫法:
var oParent = document.getElementById(‘div1‘); var aInput = oParent.getElementsByTagName(‘input‘); var aDiv = oParent.getElementsByTagName(‘div‘); for(var i=0;i<aInput.length;i++){ aInput[i].index = i; aInput[i].onclick = function(){
for(var i=0;i<aInput.length;i++){aInput[i].className = ‘‘;aDiv[i].style.display = ‘none‘;}this.className = ‘active‘;aDiv[this.index].style.display = ‘block‘;
} }; </script> 第二步: 先變型: 盡量不要出現函數嵌套函數 可以有全局變量 把onload中不是賦值的語句放到單獨函數中 <script> var oParent = null; var aInput = null; var aDiv = null; window.onload = function(){ oParent = document.getElementById(‘div1‘); aInput = oParent.getElementsByTagName(‘input‘); aDiv = oParent.getElementsByTagName(‘div‘); init(); }; function init(){ for(var i=0;i<aInput.length;i++){ aInput[i].index = i; aInput[i].onclick = change; } } function change(){ for(var i=0;i<aInput.length;i++){ aInput[i].className = ‘‘; aDiv[i].style.display = ‘none‘; } this.className = ‘active‘; aDiv[this.index].style.display = ‘block‘; } </script> 第三步: 全局變量就是屬性 函數就是方法 Onload中創建對象 改this指向問題 <script> window.onload = function(){ var t1 = new Tab(‘div1‘); t1.init(); t1.autoPlay(); var t2 = new Tab(‘div2‘); t2.init(); t2.autoPlay(); }; function Tab(id){ this.oParent = document.getElementById(id); this.aInput = this.oParent.getElementsByTagName(‘input‘); this.aDiv = this.oParent.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.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); }; </script> 10、包裝對象 : JS基於原型的程序、系統對象也是基於原型的程序 盡量不要去修改或者添加系統對象下面的方法和屬性 基本類型都有自己對應的包裝對象 : String Number Boolean 基本類型會找到對應的包裝對象類型,然後包裝對象把所有的屬性和方法給了基本類型,然後包裝對象消失 var str = ‘hello‘; String.prototype.lastValue = function(){ return this.charAt(this.length-1); }; alert( str.lastValue() ); // o var str = ‘hello‘; str.number = 10; //創建對象後,包裝對象立即消失 alert( str.number ); //undefined 創建的新對象 11、原型鏈 原型鏈 : 實例對象與原型之間的連接,叫做原型鏈 原型鏈的最外層 : Object.prototype 對象調用的屬性在構造函數中沒有的話,會沿著原型鏈到該對象的prototype原型中查找,若還是沒有,則沿著最外層原型鏈到Object.prototype中查找 function Aaa(){ this.num = 10; // 優先級最高 } Aaa.prototype.num = 20; // 優先級第二 Object.prototype.num = 30; //優先級最後 var a1 = new Aaa(); alert(a1.num); 12、hasOwnProperty : 看是不是對象自身下面的屬性 var arr = []; arr.num = 10; Array.prototype.num2 = 20; alert( arr.hasOwnProperty(‘num‘) ); //true //只是arr中的屬性,其余的數組對象沒有 alert( arr.hasOwnProperty(‘num2‘) ); //false //數組對象原型中的屬性,所有數組都有這個屬性 alert( arr.hasOwnProperty == Object.prototype.hasOwnProperty ); //true // 這個屬性是在最外層的Object原型上 13、constructor : 查看對象的構造函數 function Aaa(){ } var a1 = new Aaa(); alert( a1.constructor ); //Aaa var arr = []; alert( arr.constructor == Array ); //true function Aaa(){ } Aaa.prototype.constructor = Aaa; //每一個函數都會有的,都是自動生成的 Aaa.prototype.constructor = Array; // 修改了對象的構造函數,避免這樣做 function Aaa(){ } Aaa.prototype.name = ‘小明‘; Aaa.prototype.age = 20; var a1 = new Aaa(); alert( a1.constructor ); //若用JSON形式寫Aaa的屬性,那麽a1的constructor不是Aaa了,而是JSON對象,即Object Aaa.prototype = { constructor : Aaa, name : ‘小明‘, age : 20 }; function Aaa(){ } Aaa.prototype.name = 10; Aaa.prototype.constructor = Aaa; for( var attr in Aaa.prototype ){ //遍歷不到JS內置屬性,只能遍歷到name alert(attr); } 14、instanceof : 對象與構造函數在原型鏈上是否有關系 //自定義對象 function Aaa(){ } var a1 = new Aaa(); alert( a1 instanceof Object ); //true //系統內置對象 var arr = []; alert( arr instanceof Array ); //true 15、toString() : toString() : 系統對象下面都是自帶的,不需要經過原型鏈尋。自己寫的對象都是通過原型鏈找Object下面的。 var arr = []; alert( arr.toString == Object.prototype.toString ); //false /function Aaa(){ } var a1 = new Aaa(); alert( a1.toString == Object.prototype.toString ); //true toString() : 把對象轉成字符串 var arr = [1,2,3]; Array.prototype.toString = function(){ return this.join(‘+‘); }; alert( arr.toString() ); //‘1+2+3‘ toString() : 進制轉換 var num = 255; alert( num.toString(16) ); //‘ff‘ //255轉成16進制 利用toString做類型的判斷 : (推薦) var arr = []; alert( Object.prototype.toString.call(arr) == ‘[object Array]‘ ); //‘[object Array]‘ 用constructor和instanceof判斷類型在iframe中判斷不出 alert( arr.constructor == Array ); //false alert( arr instanceof Array ); //false 16、繼承 繼承 :在原有對象的基礎上,略作修改,得到一個新的對象。不影響原有對象的功能。 子類不影響父類,子類可以繼承父類的一些功能 ( 代碼復用 ) 1)拷貝繼承: 屬性的繼承 : 調用父類的構造函數 call 方法的繼承 : for in : 拷貝繼承 (jquery也是采用拷貝繼承extend) 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){ //子類 CreatePerson.call(this,name,sex); //繼承 call改變this指向為對象 this.job = job; } //不能用對象的賦值,CreateStar.prototype = CreatePerson.prototype; 都指向同一內存地址,改變其中一個,另一個也會改變 extend( CreateStar.prototype , CreatePerson.prototype ); CreateStar.prototype.showJob = function(){ }; var p2 = new CreateStar(‘黃曉明‘,‘男‘,‘演員‘); p2.showName(); function extend(obj1,obj2){ //把父類所有的非對象屬性給子類 for(var attr in obj2){ obj1[attr] = obj2[attr]; } } 2)類式繼承: 類 : JS是沒有類的概念的 , 把JS中的構造函數看做的類 要做屬性和方法繼承的時候,要分開繼承,避免子類對象之間的修改相互影響屬性 屬性的繼承 : 調用父類的構造函數 call 方法的繼承 : 利用構造函數(類)繼承的方式 function Aaa(){ //父類 this.name = [1,2,3]; } Aaa.prototype.showName = function(){ alert( this.name ); }; function Bbb(){ //子類 ,屬性的繼承 Aaa.call(this); } //方法的繼承 var F = function(){}; F.prototype = Aaa.prototype; //只能繼承方法 Bbb.prototype = new F(); Bbb.prototype.constructor = Bbb; //修正指向問題 var b1 = new Bbb(); b1.name.push(4); alert( b1.name ); //[1,2,3,4] var b2 = new Bbb(); alert( b2.name );//[1,2,3] 3)原型繼承: 借助原型來實現對象繼承對象 var a = { name : ‘小明‘ }; var b = cloneObj(a); b.name = ‘小強‘; alert( b.name );//小強 alert( a.name );//小明 function cloneObj(obj){ var F = function(){}; F.prototype = obj; return new F(); } 拷貝繼承: 通用型的 有new或無new的時候都可以 類式繼承: new構造函數 原型繼承: 無new的對象 17、組件開發 : 多組對象,像兄弟之間的關系( 代碼復用的一種形式 ) 對面向對象的深入應用(UI組件,功能組件) 將 配置參數、方法、事件,三者進行分離 18、自定義事件 : 主要是跟函數有關系,就是讓函數能夠具備事件的某些特性 window.addEventListener(‘show‘,function(){ alert(1); },false); window.addEventListener(‘show‘,function(){ alert(2); },false); window.addEventListener(‘show‘,function(){ alert(3); },false); show(); //主動觸發自定義事件};
JS筆記加強版3