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