JS原型对象和对象原型的区别

1,126 阅读2分钟

先抛去此文章的标题(有点晕有木有?),来看下面这段程序

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <script>
         function Star(name,age) {
            this.name = name;
            this.age = age;
            this.sing = function() {
                console.log("我会唱歌");
            }
        }
        var ldh = new Star("刘德华",18);
        var zxy = new Star("张学友",19);
        console.log(ldh.sing === zxy.sing);//false
    </script>
</body>
</html>

我们通过打印两者的sing方法可以发现这两个sing指向不同的内存地址。 但是我们不需要修改这个方法啊,每创建个对象就会开辟个内存空间,大大浪费了内存。我们可以让它的对象都共享这个方法,那么就可以节省空间。


prototype原型对象

为此,我们引入了prototype实现对象对该方法的共享

  • 每个构造函数都有一个prototype属性
  • 我们可以把那些不变的方法,直接定义在prototype对象上,这样所有对象的实例就可以共享这些方法
  • 一般情况,我们把公共属性定义到构造函数里面,公共的方法我们放到原型对象身上

修改上面的程序:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <script>
         function Star(name,age) {
            this.name = name;
            this.age = age;
            this.sing = function() {
                console.log("我会唱歌");
            }
        }
        var ldh = new Star("刘德华",18);
        var zxy = new Star("张学友",19);
         Star.prototype.sing = function() {
            console.log("我会唱歌");
        }
         console.log(ldh.sing === zxy.sing);//true
     </script>
</body>
</html>

bingo! 这样就实现了方法的共享!


__proto__对象原型

我们来看下面一段程序

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <script>
         function Star(name,age) {
            this.name = name;
            this.age = age;
        }
        Star.prototype.sing = function() {
            console.log("我会唱歌");
        }
        var ldh = new Star("刘德华",18);
        var zxy = new Star("张学友",19);
        console.log(ldh.sing);
     </script>
</body>
</html>

在这里插入图片描述 诶,我们发现,明明没有给对象添加这个sing方法呀,为啥我们能直接用呢?

其实啊,对象都会有一个属性__proto__指向构造函数的prototype原型对象,之所以我们对象可以使用构造函数的prototype原型对象的属性和方法,就是因为有__proto__原型的存在

通过打印如下代码

console.log(ldh.__proto__ === Star.prototype);//true

说明它们是指向同一块地址空间的,也就是说它们指向的是同一个sing方法

关系图: 在这里插入图片描述 __proto__的查找原理

  • 首先先看ldh 对象身上有没有sing方法,如果有就执行这个对象上的sing
  • 如果没有,因为有__proto__的存在,就去构造函数原型对象prototype身上去查找有没有sing这个方法