1)回顧JavaScript 數據類型
2)對象是什麼
1.對象是包含相關屬性和方法的集合體
1-1:屬性
1-2:方法
2.什麼是面向對象
2-1:面向對象僅僅是一個概念或者編程思想
2-2:通過一種叫做原型的方式來實現面向對象編程
3)創建對象
1.自定義對象
基於Object 對象的方式創建對象
語法:
var 對象名稱 = new Object();
栗子一: 基於Object 對象的方式創建對象
<script>
var flowe=new Object();
//添加屬性
flowe.name="長春花";
flowe.genera="長春花園";
flowe.areas="ssabvbvhvdhv";
flowe.uses="觀賞";
//添加方法
flowe.showName=function()
{
alert(flowe.name);
}
flowe.showName();
</script>
栗子二: 使用字面量賦值方式創建對象
var flowe1=
{
name:"長春花",
genera:"長春花園",
areas:"ssabvbvhvdhv",
uses:"觀賞",
showName:function()
{
alert(this.name);
}
}
flowe1.showName();
2)內置對象
+常見的內置對象
1. String (字符串)對象
2. Date (日期)對象
3. Array (數組)對象
4. Boolean (邏輯)對象
5. Math (算數)對象
6. RegExp 對象
---String(字符串)對象
1.length 屬性
2.indexOf()方法 replace()方法
---Date(日期)對象
var time = new Date();//獲取系統時間 var hh = time.getHours();//獲取系統小時 var mm = time.getMinutes();//獲取系統分鐘 var ss = time.getSeconds();//獲取系統秒數
---Array(數組)對象
1. length屬性
2.sort()、concat()、join()方法
---Boolean(邏輯)對象
1.true 或者 false
2.toString()方法
---Math(算數)對象
1.round()、max()、min()方法
....................
---RegExp對象
RegExp是正則表達式的縮寫
3)構造函數
小栗子:
<script>
function Flowe(name,genera,areas,uses)
{
this.name=name;
this.genera=genera;
this.areas=areas;
this.uses=uses;
this.showName=function()
{
alert(this.name);
};
}
var Flowe1=new Flowe("長春花","長春花園","ssabvbvhvdhv","觀賞");
Flowe1.showName();
var Flowe2=new Flowe("野蠻書","長春花園","ssabvbvhvdhv","觀賞");
Flowe2.showName();
var Flowe3=new Flowe("也漫畫","長春花園","ssabvbvhvdhv","觀賞");
Flowe3.showName();
</script>
使用構造函數創建新實例:調用構造函數的4個步驟
1.創建一個新對象
2.將構造函數的作用域賦給新對象(this就指向了這個新對象)
3.執行構造函數中的代碼
4.返回新對象
constructor屬性 檢測對象類型
constructor屬性指向Flower
alert(Flowe1.constructor == Flowe);
alert(Flowe2.constructor == Flowe);
alert(Flowe3.constructor == Flowe);
instanceof操作符檢測對象類型
alert(Flowe1 instanceof Object); alert(Flowe1 instanceof Object); alert(Flowe2 instanceof Object); alert(Flowe2 instanceof Flowe); alert(Flowe3 instanceof Flowe); alert(Flowe3 instanceof Flowe);
栗子修改代碼如下:
把方法寫成全局方法:調用
<script>
function Flowe(name,genera,areas,uses)
{
this.name=name;
this.genera=genera;
this.areas=areas;
this.uses=uses;
this.showName=showName;
}
function showName()
{
alert(this.name);
}
var Flowe1=new Flowe("長春花","長春花園","ssabvbvhvdhv","觀賞");
Flowe1.showName();
var Flowe2=new Flowe("野蠻書","長春花園","ssabvbvhvdhv","觀賞");
Flowe2.showName();
var Flowe3=new Flowe("也漫畫","長春花園","ssabvbvhvdhv","觀賞");
Flowe3.showName();
alert(Flowe1.showName==Flowe2.showName)//判斷函數是否相等
同樣也可以實現效果,但是這樣的寫法就沒有了 封裝性可言 不安全
那怎麼解決那 , 那就耐心點接着往下看
3-1)原型對象
1. 每個函數都有一個prototype屬性,這個屬性是一個指針,指向一個對象。
2. prototype就是通過調用構造函數而創建的那個對象實例的原型對象
小栗子:
原型對象的代碼 小栗子:
<script>
function Flowe()
{
}
Flowe.prototype.name='長春花';
Flowe.prototype.genera="長春花園";
Flowe.prototype.areas="ssabvbvhvdhv";
Flowe.prototype.uses="觀賞";
Flowe.prototype.showName=function()
{
alert(this.name);
};
var Flowe1=new Flowe();
Flowe1.name='曼陀羅花';//註釋掉 可以看到 兩個對象是一樣的值,這裏是更改 Flowe1的值
Flowe1.showName();
var Flowe2=new Flowe();
Flowe2.showName();
alert(Flowe1.showName==Flowe2.showName);
</script>
提示:原型對象的創建 解決了構造函數當中的一個減少方法實例的創建,實現了封裝
原型對象的結構圖:
4)JavaScript 繼承
1.原型鏈 2.對象繼承
原型鏈圖:
1. 一個原型對象是另一個原型對象的實例
2. 相關的原型對象層層遞進,就構成了實例與原型的鏈條,就是原型鏈
原型鏈小栗子:
原型鏈代碼小栗子:
<script>
function Humans()
{
this.foot=2;
}
Humans.prototype.getFoot=function()
{//原型對象添加方法
return this.foot;
}
function Man()
{
this.head=1;
}
//Man繼承Humans
Man.prototype=new Humans();
Man.prototype.getHead=function()
{//原型對象添加方法
return this.head;
}
var man1=new Man();
alert(man1.getFoot());//2
alert(man1.getHead());//1
alert(man1 instanceof Object);//true
alert(man1 instanceof Humans);//true
alert(man1 instanceof Man);true
</script>
調用man1.getFoot() 經歷的三個步驟
1.搜索實例
2.搜索Man.prototype
2.搜索Humans.prototype
如果沒有搜索到則產生下列圖:完整原型鏈
4-2)對象繼承
<script>
function Humans()
{
this.clothing=["aaa","bbb","ccc"];
}
function Man()
{
}
//Man繼承Humans
Man.prototype=new Humans();
var man1=new Man();
man1.clothing.push("ddd");//數組添加信息
alert(man1.clothing);
var man2=new Man();
alert(man2.clothing);
</script>
打印結果爲:兩次都是一樣的
爲什麼是一樣的那?
創建子類型的實例時,不能向父類型的結構函數中傳遞參數
解決方案:使用借用構造函數
思想:
借用構造函數的基本思想。就是在子類構造函數當中 調用父類構造函數。
其子類構造的內部通過 apply() 或 call()去調用父類型的構造函數,來實現屬性和方法的繼承。
修改代碼如下的 小栗子:實現 實現屬性 和 方法的繼承。進行私有化
<script>
function Humans()
{
this.clothing=["aaa","bbb","ccc"];
}
function Man()
{
Humans.call(this);
}
//Man繼承Humans
// Man.prototype=new Humans();
var man1=new Man();
man1.clothing.push("ddd");//數組添加信息
alert(man1.clothing);
var man2=new Man();
alert(man2.clothing);
</script>
借用構造函數 的一個大的優勢:
1.可以在子類型構造函數中向父類型構造函數傳遞參數
小實例:
代碼小栗子:
<script>
function Humans(name)
{
this.name=name;
}
Humans.prototype.showName="sss";
function Man()
{
Humans.call(this,"mary");
this.age=38;
}
var man1=new Man();
alert(man1.name);
alert(man1.age);
</script>
運行結果:沒有問題。
那麼我們現在有個新的問題:如果我 通過原型鏈給 父類添加一個屬性,那麼又會怎麼樣那?
稍作修改代碼如下:
<script>
function Humans(name)
{
this.name=name;
}
//原型鏈方式添加屬性
Humans.prototype.showName="sss";
function Man()
{
Humans.call(this,"mary");
this.age=38;
}
var man1=new Man();
alert(man1.name);
alert(man1.age);
alert(man1.showName);
</script>
運行結果如下:showName,undefined 沒有值。爲什麼會這樣那? 又該如何使用 或者 複用父類的方法 或 屬性那那?
接着往下看一種方式
組合繼承:
組合繼承:有時也叫做僞經典繼承
1.將原型鏈和借用構造函數的技術組合到一塊,發揮二者之長的一種繼承模式。
2.使用原型鏈實現對原型屬性和方法的繼承,而通過借用構造函數來實現對實例屬性的繼承
修改後的代碼:
<script>
function Humans(name)
{
this.name=name;
}
//原型鏈方式添加屬性
Humans.prototype.showName="sss";
function Man()
{
//調用構造函數實現實例屬性的繼承
Humans.call(this,"mary");
this.age=38;
}
//繼承Humans
Man.prototype=new Humans();
Man.prototype.getAge=function()
{
return this.age;
}
var man1=new Man();
alert(man1.name);
alert(man1.getAge());
alert(man1.showName);
</script>
運行結果:補充一點:
如果兩個函數的名稱一樣,則會執行最後一個函數,覆蓋之前的函數。
從上到下執行