面向對象的語言有一個標志,那就是它們都有類的概念,而通過類可 以創建任意多個具有相同屬性和方法的對象。前面提到過,ECMAScript 中沒有類的概念,因此它的對象也與基于類的語言中的對象有所不同。
ECMA把對象定義為:“無序屬性的集合,其屬性可以包含基本值、對象或者函數。對象的每個屬性或方法都有一個名字,而每個名字都映射到一個值。
我們之前在學習創建對象時,使用字面量方式和Object構造函數的方式都可以進行創建對象,但是我們也發現了這兩種方式只適合用來創建單個對象,想要創建大量對象時,一份代碼就要書寫多次,顯然的產生了代碼冗余。接下來來介紹幾種其他創建對象的方式。
工廠模式創建對象:
上面我們說使用Object構造函數的方式進行創建多個對象時,會產生大量重復代碼,那自然而然我們就會想到將重復性的代碼封裝成為一個函數,這個函數就是工廠函數。
- // 工廠模式實際上就是封裝函數
- function createStar(name, age, sex){
- // 1.創建一個空對象(原材料)
- var obj = {};
- // 2.添加屬性和方法(加工)
- obj.name = name;
- obj.age = age;
- obj.sex = sex;
- obj.skill = function(){
- console.log('sing dance');
- }
- // 3.返回出對象(出廠)
- return obj
- }
- // 創建對象
- var star1 = createStar('何美男',25,'boy');
- console.log(star1);
- star1.skill(); // sing dance
使用工廠模式創建對象雖然可以實現批量創建對象,但是卻出現了新的問題,即創建出的對象指向不明確。使用instanceof操作符檢測對象類型時,都是屬于object。
- var star2 = createStar('大黃', 3, 'boy');
- console.log(star2);
- star2.skill();
- console.log(typeof star1, typeof star2); // object object
- console.log(star2 instanceof Object); // true
構造函數創建對象:
構造函數實際上就是一個函數,只是這個函數是專門用來創建對象的,他的特點:
1.構造函數首字母大寫,為了區分普通函數;
2.不需要創建對象,屬性和方法直接添加在this上,不需要return返回
3.構造函數調用時,一定要使用new;
- // 1.聲明構造函數
- function Teacher(name, age, sex){
- // 添加屬性
- this.name = name;
- this.age = age;
- this.sex = sex;
- // 添加方法
- this.skill = function(){
- console.log('布置作業');
- }
- }
- // 2.實例化對象
- var t1 = new Teacher('小王',20,'girl');
- console.log(t1);
- t1.skill(); // 布置作業
- var t2 = new Teacher('小李', 25, 'boy');
- console.log(t2);
- t2.skill(); // 布置作業
我們需要明確 new操作符做了什么?
1.隱式的創建了一個對象;
2.讓this指向這個空對象;
3.讓實例對象的__ proto __指向構造函數的prototype;
4.執行代碼,給this添加屬性和方法;
5.隱式的返回創建好的對象;
所以在使用構造函數創建對象時一定要使用new操作符。
使用構造函數創建對象解決了創建出的對象指向不明確,構造函數的主要問題就是每個方法都要在每個實例上重新創建一遍。在前面的例子中,t1 和 person2 都有一個名為 skill()的方法,但那兩個方法不是同一個 Function 的實例。創建兩個完成同樣任務的 Function 實例的確沒有必要,我們可以通過代碼證實:
- console.log(t1.skill() == t2.skill()); // false-比較的是地址
原型創建對象:
我們創建的每個函數都有一個 prototype(原型)屬性,這個屬性是一個指針,指向一個對象, 而這個對象的用途是包含可以由特定類型的所有實例共享的屬性和方法。使用原型對象的好處是可以 讓所有對象實例共享它所包含的屬性和方法。換句話說,不必在構造函數中定義對象實例的信息,而是 可以將這些信息直接添加到原型對象中,如下面的例子所示。
- function Stu(){}
- // 2.添加屬性和方法
- Stu.prototype.name = '小明';
- Stu.prototype.age = 18;
- Stu.prototype.skill = function(){
- console.log('沉迷敲代碼');
- }
- // 3.實例化對象
- var s1 = new Stu();
發現對象里邊是空的,打開可以看到所有的屬性和方法都在__proto__原型屬性上
理解原型對象
無論什么時候,只要創建了一個新函數,就會根據一組特定的規則為該函數創建一個prototype 屬性,這個屬性指向函數的原型對象。在默認情況下,所有原型對象都會自動獲得一個 constructor (構造函數)屬性,這個屬性包含一個指向 prototype 屬性所在函數的指針。
創建了自定義的構造函數之后,其原型對象默認只會取得 constructor 屬性;當調用構造函數創建一個新實例后,該實例的內部將包含一個指針(內部 屬性),指向構造函數的原型對象。__proto__這個連接存在于實例與構造函數的原型對象之間,而不是存在于實例與構造函數之間。
針對上述原型模式創建對象的代碼,我們可以畫出它的圖例關系:
更多內容
>>本文地址:http://www.jecan.cn/zhuanye/2021/69434.html
聲明:本站稿件版權均屬中公教育優就業所有,未經許可不得擅自轉載。
1 您的年齡
2 您的學歷
3 您更想做哪個方向的工作?