借用作者的图片,镇博

js面向对象(深度总结)_面向对象

 

 

Everything is object (一切皆对象)

什么是面向对象

面向对象不是新的东西,它只是过程式代码的一种高度封装,目的在于提高代码的开发效率和可维护性。

 

对于面向对象的理解,在这里就不多说了,关键说一下这篇文章带来的新感受;

对象其实就是拥有属性和方法,可以有特定功能区完成一定的功能,我们可以把很多面向过程的代码封装起来,成为一个对象,那么这个对象可以完成指定的一些功能,就不用重复的去写一些代码,每次写都需要取想过程,只需要用这个对象去完成就行,这就是面向对象的优势。

我们可以用字面量的简单方式创建对象,包含属性和方法;

但是要创建好多类似对象时就显得比较麻烦,所以就有了工厂模式,工厂模式就是建立一个函数,这个函数执行完就可以创建出我们想要的对象。

工厂模式区别不出来,对象属于那个类,就是没有抽象出类的概念,于是就出现了构造函数,

构造函数为什么就能区别出是属于哪个类呢?

首先我没来说一下,今天收益最大的知识点:

1、每个函数都有一个prototype属性,这个属性是一个对象

2、构造函数的 ​​prototype​​ 对象默认都有一个 ​​constructor​​ 属性,指向 ​​prototype​​ 对象所在函数。

3、通过构造函数得到的实例对象内部会包含一个指向构造函数的 ​​prototype​​ 对象的指针 ​​__proto__。​

4、所有实例都直接或间接继承了原型对象的成员。

 

那么这样就知道,为什么构造函数创建的对象可以区分是哪个类了:

js面向对象(深度总结)_工厂模式_02

 

 js面向对象(深度总结)_创建对象_03

 

 js面向对象(深度总结)_构造函数_04

 

 我们可以根据constructor 知道,是哪个类,也可以用instanceof判断是不是属于某一个类,这样区分属于某一个类就很明显了;

上面的构造函数方式创建对象有一个很大的隐患,就是一些公共的静态属性和公共的方法,每次创建一个实例都会从新创建,重新分配内存,这样,实例多了,就会非常占用内存。

那么用构造函数和原型链结合起来,就能避免这样的问题:

对于这种问题我们可以把需要共享的函数定义到构造函数外部:

js面向对象(深度总结)_工厂模式_05

 

 但是如果有多个需要共享的函数的话就会造成全局命名空间冲突的问题。如何解决这个问题呢?你肯定想到了可以把多个函数放到一个对象中用来避免全局命名空间冲突的问题:

js面向对象(深度总结)_构造函数_06

 

 至此,我们利用自己的方式基本上解决了构造函数的内存浪费问题。 但是代码看起来还是那么的格格不入,那有没有更好的方式呢?

更好的解决方案: ​​prototype​

Javascript 规定,每一个构造函数都有一个 ​​prototype​​ 属性,指向另一个对象。 这个对象的所有属性和方法,都会被构造函数的实例继承。

这也就意味着,我们可以把所有对象实例需要共享的属性和方法直接定义在 ​​prototype​​ 对象上。

js面向对象(深度总结)_原型对象_07

 

 

 更简单的原型语法

我们注意到,前面例子中每添加一个属性和方法就要敲一遍 ​​Person.prototype​​ 。 为减少不必要的输入,更常见的做法是用一个包含所有属性和方法的对象字面量来重写整个原型对象:

js面向对象(深度总结)_构造函数_08

 

 

在该示例中,我们将 ​​Person.prototype​​ 重置到了一个新的对象。 这样做的好处就是为 ​​Person.prototype​​ 添加成员简单了,但是也会带来一个问题,那就是原型对象丢失了 ​​constructor​​ 成员。

所以,我们为了保持 ​​constructor​​ 的指向正确,建议的写法是:

js面向对象(深度总结)_原型对象_09

 

 

原型对象的一些问题

 

  • 共享数组
  • 共享对象

 

 

原型对象使用建议:

  1. 私有成员(一般就是非函数成员)放到构造函数中。
  2. 共享成员(一般就是函数)放到原型对象中。
  3. 如果重置了 prototype 记得修正 constructor 的指向。

 

时间有点琐碎,匆忙记录一下,加深一下记忆,谢谢博主的文章,将的很透彻,很实用