11-原型對象

11-原型對象

我們在學習構造函數那一節的時候遇到了一個問題。

 1 <script type="text/javascript">
 2         function Person(age, name, sex){
 3             this.name = name;
 4             this.sex = sex;
 5             this.age = age;
 6             this.sayName = SayName;
 7         }
 8         function SayName(){
 9             alert("大家好!" + "我是" + this.name + ",我" + this.age + "歲," + "我是" + this.sex + "生");
10         }
11 
12         p1 = new Person(18, "沙僧", "男");
13         p2 = new Person(18, "孫悟空", "男");
14         p3 = new Person(18, "白骨精", "女");
15         p1.sayName();
16         p2.sayName();
17         p3.sayName();
18     </script>

View Code

大家看這個,咱們可以發現雖然可以達到創建多個對象,只調用一次函數的效果,但是也有許多弊端。

將函數定義在全局作用域,污染全局作用域的命名空間,而且定義在全局作用域中也很不安全。因為一個程序一般都是多個人參與開發的,另外一個開發人員可能會用到和你一樣的函數名,這樣就會污染變量。
下面就為大家介紹另外一種方法:原型對象法

首先為大家解釋什麼是原型對象?

在每一個構造函數對象中都有一個隱藏的屬性prototype,而這個屬性是一個對象,我們把這個對象稱作原型對象。

大家可以看下面這段代碼:

1         function Dog(){
2             console.log("一隻小狗");
3         }
4         console.log(Dog.prototype);

這段代碼運行效果如下:

既然prototype是一個對象那他就可以擁有自己的屬性和方法,大家可以看下面這張圖:

 

 

 

 另外,這個屬性在同一個構造函數中創建的對象中是一樣的:

1         function Dog(){
2             console.log("一隻小狗");
3         }
4         // console.log(Dog.prototype);
5         d1 = new Dog();
6         d2 = new Dog();
7         console.log(d1.__proto__ === d2.__proto__);
8         console.log(d1.__proto__ === Dog.prototype);

這段代碼運行效果如下:

 

 基於以上特性我們可以將需要在構造函數中使用的屬性、方法,全部放到原型屬性裏面:

(原型對象就像是一個公共的區域,所有同一類的實例都可以訪問到這個原型對象。)

 1         function Person(name, age, sex){
 2             this.name = name;
 3             this.age = age;
 4             this.sex = sex;
 5         }
 6         Person.prototype.sayName = function(){
 7             console.log(`大家好,我是${this.name},我是${this.sex}生,我${this.age}歲`);
 8         }
 9         obj1 = new Person("孫悟空", 10000, "男");
10         obj1.sayName();

下圖是上面代碼執行效果:

 

 在JS中當我們訪問對象的一個屬性或者方法時,他會現在對象自身中尋找,如果有則直接使用,如果沒有就向原型對象中找。

另外原型對象也是一個對象,是一個對象就有原型對象,那麼是不是沒有盡頭呢?我們來看下面的代碼:

1         console.log(d1.__proto__);
2         console.log(d1.__proto__.__proto__);
3         console.log(d1.__proto__.__proto__.__proto__);  // 返回空

下圖是代碼執行效果:

 

 通過上面代碼我們發現並不是所有對象都有原型對象,那麼哪一類對象沒有原型對象呢?

Object對象沒有原型對象,如果在Object中依然沒有找到,則返回null或undefined