原型是什么?原型和原型链的一些心得体会

最近在复习原型,感觉有很多要重点对待的,对面向对象的理解很有帮助。遂记。

我的理解:

原型的主要作用:共享数据,节省空间!

一、为什么要用原型?

例如:有一个构造函数  Person :

function Person(name)  { 
    
    this.name = name;

    this.eat= function () {
        console.log("eat");
    }
    
}

var per1 = new Person( 'zs' );

对于这个构造函数的实例对象 per1 来说,可以调用方法 eat 。由此看来是没有任何问题。但由于函数也是对象,会在内存中单独开辟一个空间,因此,当实例对象多的时候,就会出现内存空间被很多重复的函数占用。

如:有100个 Person 的实例对象,那么在内存空间里就会有100个eat方法占用的空间,这些方法分别指向不同的实例对象。但是他们的执行结果却都是一样的。这就造成了内存空间的浪费!

为解决这个问题,我们需要一个共享的空间,在里面存放一些公共的方法,属性,这就是原型。

二、什么是原型?

1、对于构造函数Person 来说,他有一个prototype的属性,prototype是一个对象,他叫显式原型。

prototype是给程序员使用的,是标准的属性,且只有函数有这个属性。

在prototype中有默认的几个属性,如constructor构造器等

2、对于一个实例对象per1来说,他有一个__proto__的属性,__proto__是一个对象,他叫隐式原型。

__proto__是给浏览器使用的,不是标准的属性,且IE8不支持。

当我们在构造函数的 prototype 中添加属性或者方法的时候,其实例对象均可以使用这些属性或者方法且不会单独的开辟空间。这就完成了数据的共享!

如代码:

function Person(name) {
    this.name = name;
}
Person.prototype.eat = function () {
    console.log("eat");
}

var per1 = new Person( 'zs' );

对于实例对象per1来说,他有一个属性name,且有一个方法 eat ,由于eat方法是写在其构造函数的原型里面的,因此他在实例化的时候,不会单独为eat再开一个空间,而是直接使用eat方法。

这样如果有100个实例对象的话,大家使用的都是同一个eat方法,不会单独为eat开辟空间,大大节省了内存空间。

那么,为什么 实例对象per1可以调用写在构造函数(person) 的 prototype 中的 方法或者 属性呢?

因为Person 创建了per1,因此,per1中的 __proto__ 指向了  Person中的prototype,所以prototype中的属性和方法,per1都可以通过__proto__调用。

即使用per1.__proto__.eat();就可以调用了,通常情况下我们省略__proto__不写--->  写 per1.eat() 即可

三、原型中的this指向?

原型中的this指向  为  调用这个方法的实例对象。就是哪个实例对象调用这个方法,this就指向哪个实例对象!

四、原型的指向可以改变吗?

原型是一个构造函数中的一个属性,同时他也是一个对象!对象中存放的是地址,他指向一块内存空间。在这个内存空间中存放着公共的属性和方法。

例如:

1  function Person(name) {
2     this.name = name;
3  }
4
5  Person.prototype.eat = function () {
6     console.log("eat");
7  }
8
9  Person.prototype = {
10     sayHi : function () {
11         console.log("Hello");
12     }
13 }

我们可以看到在代码的第5行时,我们在构造函数的原型中添加了一个方法,而当第9行的时候,我们重新声明一个对象,并把对象给了原型,且新的对象里面有一个方法sayHi。

当我们再次调用eat的时候,会发现无法调用,因为eat 在以前指向的那块内存空间里面,而原型指向已经发生了改变,不再指向之前的那块空间了,现在指向的是有sayHi的那块内存空间。

因此原型的指向是可以改变的。

五、原型链是什么?

在了解原型链之前。我们要知道,任何对象中都有__proto__属性,其指向某个构造函数的prototype对象。

构造函数的prototype属性,也是对象,因此他也有__proto__属性。

而我们知道,实例对象的__proto__指向的是其构造函数的 prototype对象。那么,我们是不是可以推出--->prototype对象因为有__proto__属性,所以,他也是一个实例对象,其__proto__属性的指向为某个构造函数的prototype对象。同样某个构造函数的prototype对象也有__proto__属性,他也有指向的prototype对象,因此就会形成一条原型链!

如图:

猜你喜欢

转载自blog.csdn.net/qq_31906983/article/details/82906122