JavaScript-原型对象、原型链

JavaScript-原型对象、原型链

  在构造函数的例子中,我们想要为Person类构造函数内部创建一个sayName方法是通过外部定义全局函数,内部引用来防止多次创建占用空间,损耗性能。

 // 创建一个Person构造函数
 function Person(name, age) {
     this.name = name;
     this.age = age;
     /*
      * 在构造函数内部创建的sayName方法
      *  -每执行一次就会创建一个新的方法
      *  -这样对于同样的方法多次创建占用空间,损耗性能
      */
     // this.sayName = function () {
     //     console.log("我的名字:", this.name);
     // }
     // 将sayName放在全局作用域中定义就不会多次创建
     this.sayName = fun;
 }
 function fun() {
     console.log("我的名字:", this.name);
 }

  但这也并不是最好的方法,因为方法定义在全局中定义会污染命名空间,不利于复杂功能开发和不利于协同开发。那通过prototype就可以很好的解决这个问题。

一、原型对象

   我们所创建的每一个函数,解析器都会向函数中添加一个属性prototype,这个属性对应着一个对象,这个对象就是我们所谓的原型对象。 如果函数作为普通函数调用prototype没有任何作用。当函数以构造函数的形式调用时,它所创建的对象中都会有一个隐含的属性__proto__指向该构造函数的原型对象,我们可以通过__proto__来访问。
  原型对象就相当于一个公共的区域所有同一个类的实例都可以访问到这个原型对象。我们可以将对象中共有的内容,统一设置到原型对象中。
  构造函数、实例对象、原型对象三者关系如何?以上的文字描述并不直观,通过关系图的加持会让我们的认识更加清晰,看一下吧!
在这里插入图片描述

  到这里想必已经对原型有所了解了,那尝试一下解决解决开头所说的问题,其实不难想到把公共方法添加在原型上就得以解决了,如下:

function Person(name, age) {
    this.name = name;
    this.age = age;
}
// 原型上添加一个公共方法sayName
Person.prototype.sayName = function(){
    console.log("我的名字:", this.name);
};

  通过以上示例是可以的,那更深一层思考,它又是如何查找某个属性或是方法的呢?那这就涉及到原型链的问题了。

二、原型链

访问对象的一个属性或方法便是在原型链上的查找流程如下:

  • 它会先在对象自身中寻找,如果有则直接使用
  • 如果没有则会去原型对象中寻找,如果找到则直接使用
  • 如果还没有就去原型的原型中寻找,直到找到Object对象的原型。
  • Object对象的原型没有原型,如果在Object的原型中依然没有则返回undefined。

原型链解析视图如下:
原型链解析图

三、完整示例

运行一下以下例子理解更清晰。
1、原型示例

<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8">
    <title>原型对象示例一</title>
    <script>
        function Person(name, age) {
            this.name = name;
            this.age = age;
        }
        // 原型上添加一个公共属性
        Person.prototype.type = '人类';
        // 原型上添加一个公共方法
        Person.prototype.sayName = function(){
            console.log("我的名字:", this.name);
        };
        let shier = new Person('shier', 12);
        // 判断实例对象和构造函数访问到的是否是同一个原型对象
        console.log(shier.__proto__ == Person.prototype);
        console.log(shier.type);
        shier.sayName();
    </script>
</head>

<body>

</body>

</html>

2、关于原型链示例

  这个示例中涉及检查对象中是否有某个属性的两种方法,简单介绍一下:

  • in:如果对象自身没有该属性,原型链中有也会返回true,否则返回false。
  • hasOwnProperty():只会检查对象自身是否有该属性,如果有返回true,否则返回false。
<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8">
    <title>原型对象示例二</title>
    <script>
        // 创建一个构造函数
        function Person() {

        }
        Person.prototype.type = '人类';
        let shier = new Person();
        // in检查对象中是否有某个属性,如果对象中没有原型中有也会返回true
        console.log("type" in shier);
        // hasOwnProperty()
        console.log(shier.hasOwnProperty('type'));
        // 原型对象也是对象,所以它也有原型
        console.log(Person.prototype)
        console.log(shier.__proto__.__proto__);
    </script>
</head>

<body>

</body>

</html>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值