跟着艾文一起学前端-第18篇-JavaScript-原型与继承

1、背景

函数的相关知识

构造函数和实例对象的关系

实例对象由构造函数创建,使用构造函数创建实例对象的过程叫做对象的实例化。

查看某个对象的结构,可以通过console.dir(对象);

通过查看对象的结构,可以看到每个对象都有一个特殊的属性叫作原型(prototype)

判断一个对象的类型的方式:
  1. instanceof - - datObj instanceof CustomObject ; true 是该类型,false 不是;- - 推荐使用该方式。
  2. 对象的构造器,可以通过对象的原型属性获取构造器 - - datObj.constructor == CustomObject; true是, false 不是

如果给一个构造器函数添加一个函数方法,实例化对象时,每个对象在调用该方法时都会创建一个新的同名的方法,势必会浪费内存空间。而通过原型可以解决这种内存的开销。

constructor 属性

每个实例对象都从原型中继承了一个constructor属性,该属性指向了用于构造此实例对象的构造函数

2、原型 prototype

JavaScript 常被描述为一种基于原型的语言 (prototype-based language)——每个对象拥有一个原型对象,对象以其原型为模板、从原型继承方法和属性。原型对象也可能拥有原型,并从中继承方法和属性,一层一层、以此类推。这种关系常被称为原型链 (prototype chain),它解释了为何一个对象会拥有定义在其他对象中的属性和方法。
准确地说,这些属性和方法定义在Object的构造器函数(constructor functions)之上的prototype属性上,而非对象实例本身。
在传统的 OOP 中,首先定义“类”,此后创建对象实例时,类中定义的所有属性和方法都被复制到实例中。在 JavaScript 中并不如此复制——而是在对象实例和它的构造器之间建立一个链接(它是__proto__属性,是从构造函数的prototype属性派生的),之后通过上溯原型链,在构造器中找到这些属性和方法。

注意: 理解对象的原型(可以通过Object.getPrototypeOf(obj)或者已被弃用的__proto__属性获得)与构造函数的prototype属性之间的区别是很重要的。前者是每个实例上都有的属性,后者是构造函数的属性。也就是说,Object.getPrototypeOf(new Foobar())和Foobar.prototype指向着同一个对象。

构造函数、原型对象与实例对象的关系

通过构造函数的构造器可以实例化一个实例对象;
实例对象中的原型对象(proto)指向的是该实例对象的构造函数中的原型对象,这种实例对象通过原型关联到了原型对象的方式叫做原型链;
构造函数有一个属性prototype,也就是构造函数的原型对象,构造函数的原型对象中有一个constructor构造器,这个构造器指向的当前构造函数
构造函数的原型对象即prototype中的方法是可以被实例对象直接访问调用的,且需要共享的数据可以写在原型对象中。

在这里插入图片描述

原型作用

  1. 用构造函数通过原型prototype来添加方法,可以实现数据共享,节省内存空间;
  2. 实现继承,下文会讲到,它也是为了节省内存的空间。

给原型添加属性和方法

语法格式:

ConstructorFun.prototype = {
	constructor: Constructor,//需要给constructor对象手动添加指向该构造函数
	属性1:"属性1的值",...,//一系列需要共享的属性
	函数1名称: function() {// 一些需要共享的方法
		//函数处理逻辑
	},...
};

原型链

实例对象的原型__proto__指向的是该对象的构造函数的原型对象(prototype),构造函数的原型对象(prototype)的指向如果改变了,那么实例对象的原型(proto)指向也会跟着改变。所以说原型的指向是可以改变的。我们把实例对象和原型对象之间通过__proto__来联系起来的这种关系叫做原型链。
注意:如果原型指向改变了,想调用改变之前的原型方法,要在原型改变之后再添加原型方法。

继承

JavaScript中是没有类的概念的,但是JavaScript中可以模拟面向对象的思想编程,可以通过JavaScript中的构造函数来进行替代类。所以JavaScript中的继承和其他面向对象的继承是有差别的。
只需要通过将原型对象的指向改变,就可以使用某个对象的原型对象的属性和方法,这种通过改变原型对象,来使用原型对象的属性和方法的这种方式被称为继承。

扫描二维码关注公众号,回复: 11119297 查看本文章

其他方式的继承使用:

1. 使用构造函数实现继承属性值

需要使用:被继承的构造函数.call(this, 属性1,…);
局限性:通过构造函数仅仅只能继承属性,去不能继承其方法;

2. 组合继承(原型+构造函数)

通过原型继承的话,数据是共享的,所以如果想给每个对象的属性设置不同的值就不能用原型的属性方式来实现。上面的构造函数方式能够继承属性,实现属性值的不同,但是却不能继承父对象的方法。
解决方法:通过构造函数继承属性,原型用于继承方法,这样就实现了方法和属性的继承。

3. 拷贝继承

所谓拷贝继承从字面上理解就是将一个对象的属性、方法通过循环遍历的方式赋值给另一个对象,这个对象就像是复制了一个与它一样的对象一样。

发布了37 篇原创文章 · 获赞 15 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/u012764358/article/details/105706163
今日推荐