1. 类

  ES6 中新增加了类的概念,可以使用 class 关键字声明一个类,之后用这个类来实例化对象。即类的用途:实例化对象。

// 创建一个Person类
class Person { }
// 创建一个Person类的实例对象
const p1 = new Person()
console.log(p1)

打印结果如下:

注意,输出的p1是一个实例对象,而不是类!这里的输出结果有 Person,是为了说明这个实例对象是由谁new出来的,蓝框表示输出的确实是一个实例对象。

思考:为什么前面要带一个类呢?假设还有一个Dog类,同样new一个Dog类的实例对象p2,这时候必须通过类名来区分实例对象,否则就人畜不分了......

现在我们了解了类和实例对象,下面我们再来研究构造函数。

2. 构造函数

一般对实例对象都会有一些初始化操作,比如人有姓名和年龄,因此就出现了类的构造器方法constructor(),它的作用是给实例对象添加属性,语法如下:

//步骤1 在类中定义构造函数constructor,函数名固定
class Person {
constructor(name,age) {//定义形参
this.name = name;//将形参赋值给this对象的对应属性
this.age = age;
}
} //步骤2 在实例化对象的时候,传递实参
const p1 = new Person('bahg', 18); //这里的实参默认传递给Person类中的constructor
console.log(p1.name);//bahg

思考:

1、构造函数必须写吗?答:不是必须的,但是对于Person这个类而言,它没有继承任何类,如果不写构造方法也就没有任何意义。下面会讲到继承类,它可以不写构造函数,默认会调用父类的构造函数。

2、构造函数中的 this 是什么?答:是实例化对象,也就是p1

一个类除了有构造方法,还有一般方法,一般方法是用来定义行为的,比如人可以吃饭睡觉敲代码,这里我们定义一个speak方法:

 // 创建一个Person类
class Person {
constructor(name, age) {
this.name = name
this.age = age
}
speak() {
console.log(`名字为${this.name}的人年龄为${this.age}`)
}
}
// 创建一个Person类的实例对象
const p1 = new Person('bahg', 18)
const p2 = new Person('zzz', 21)
console.log(p1)
console.log(p2)
p1.speak()
p2.speak()

打印结果如下:

3. 原型对象

在JavaScript中,每当定义一个函数数据类型(普通函数、类)时候,都会天生自带一个prototype属性,这个属性指向函数的原型对象,并且这个属性是一个对象数据类型的值。

让我们用一张图表示构造函数和实例原型之间的关系:

原型对象就相当于一个公共的区域,所有同一个类的实例都可以访问到这个原型对象,我们可以将对象中共有的内容,统一设置到原型对象中。

思考:

1、p1和p2为什么没有出现speak方法呢?被放到了哪里?答:类的原型对象上,如下所示:

2、speak方法是给谁用的?答:给实例对象用的

3、speak的this指向谁?答:指向它的最后调用者。注意:“谁调用它就是谁”这种说法是不准确的,因为call、apply、bind都可以更改函数中的this指向,例如 p1.speak.call({a:1,b:2}) 此时this就是undefined。

4. 继承

继承是为了复用代码,下面我们再定义一个Student类,它继承于Person类:

class Person {
   constructor(name, age) {
      this.name = name
      this.age = age
}
   speak() {
     console.log(`名字为${this.name}的人年龄为${this.age}`)
   }
}
   
class Student extends Person{
}
const s1 = new Student('小明', 15)
console.log(s1)

这里我们没有在Student类中写构造方法,但是仍然可以打印s1,说明构造器方法不是非写不可。

思考:我们什么时候需要写构造器方法呢?

答:子类有自己特有的属性时,比如学生有年级这个属性,此时就需要重新写自己的构造器方法,但是注意:一旦写了构造器,就必须调用 super() 方法,并且要写在其他属性之前!super函数的作用是调用父类的构造器。

class Student extends Person {
constructor(name, age, grade) {
super(name, age)
this.grade = grade
}
}
const s1 = new Student('小明', 15, '高一')
console.log(s1)

思考:此时Student的原型对象上有方法吗?

答:除了构造器方法之外没有其它方法,因为Student类里面没有写自己的方法。

那么问题来了,学生能够说话吗?答案是肯定的,通过s1.speak()可以打印出结果,那么speak方法在哪呢?这里就要引出原型链了。

5.原型链

在JavaScript中万物都是对象,对象和对象之间也有关系,并不是孤立存在的。对象之间的继承关系,在JavaScript中是通过prototype对象指向父类对象,直到指向Object对象为止,这样就形成了一个原型指向的链条,专业术语称之为原型链。

举例说明:person → Person → Object ,普通人继承人类,人类继承对象类

当我们访问对象的一个属性或方法时,它会先在对象自身中寻找,如果有则直接使用,如果没有则会去原型对象中寻找,如果找到则直接使用。如果没有则去原型的原型中寻找,直到找到Object对象的原型,Object对象的原型没有原型,如果在Object原型中依然没有找到,则返回undefined。

对于实例对象s1,它在调用speak方法时,会先去原型对象上查找,发现没有这个方法,就继续去原型链上查找,找到了父类原型对象上的speak方法,如图所示:

从始至终都只有一个speak,沿着原型链一层层去找。我们还可以对speak方法进行重写,什么时候需要重写呢?当子类要对父类方法进行扩展时,就可以重写方法。

class Student extends Person {
constructor(name, age, grade) {
super(name, age)
this.grade = grade
}
speak() {
console.log(`名字为${this.name}的人年龄为${this.age},读${this.grade}`)
}
}
const s1 = new Student('小明', 15, '高一')
console.log(s1)

思考:此时Student原型对象上有speak方法吗?答:有,s1打印结果如下:

按照原型链查找规则,当它查找到蓝色箭头的时候就直接调用speak函数了,不会再往下查找。

假设现在学生类还有自己独有的study方法,思考:

1、study方法放在了哪里?供谁使用?答:放在了Student类的原型对象上,供实例使用。

2、通过Student实例调用study时,this指向谁?答:指向Student的实例。

以上就是对类的一个复习,并没有把类的所有知识都进行复习,只是重新梳理了比较重要也是比较难理解的部分。总结如下:

1、类中的构造器不是必须写的,要对实例进行一些初始化的操作时,如添加一些指定属性时才写。如果在Student的构造器中加一行 this.job = '程序员'也是可以的,参数列表不需要变,它表示Student缔造的实例对象的工作都是程序员

2、如果A类继承B类,且A类中写了构造器,那么A类构造器中super是必须要调用的

3、类中定义的方法都是放在了类的原型对象上,供实例使用

由于之前一直没能理解类、实例对象、原型链等具体概念以及相互之间的联系,故写下这篇博客来帮助理解,如有错误请指正。

博客中原型对象及原型链部分参考了https://www.jianshu.com/p/ddaa5179cda6这篇文章。

对ES6中类class以及实例对象、原型对象、原型链之间关系的详细总结的更多相关文章

  1. JS中构造函数与原型对象的同名属性,实例会取哪一个

    构造函数与原型对象的同名属性,实例会取哪一个? 看了下面的过程,再回忆JS高程3里关于这部分的示意图.实例my在new的时候,本身就获得了a属性,所以my.a是1,倘若在new的时候如果没有赋予a属性 ...

  2. 还在问什么是JavaScript构造函数、实例、原型对象以及原型链?看完这篇你就懂

    1概述 ES6, 全称 ECMAScript 6.0 ,2015.06 发版.在ES6之前,对象不是基于类创建的,而是用一种称为构造函数的特殊函数来定义对象和它们的特征. 2构造函数 构造函数是一种特 ...

  3. 关于Javascript中通过实例对象修改原型对象属性值的问题

    Javascript中的数据值有两大类:基本类型的数据值和引用类型的数据值. 基本类型的数据值有5种:null.undefined.number.boolean和string. 引用类型的数据值往大的 ...

  4. 5.Javascript 原型链之原型对象、实例和构造函数三者之间的关系

    前言:用了这么久js,对于它的原型链一直有种模糊的不确切感,很不爽,隧解析之. 本文主要解决的问题有以下三个: (1)constructor 和 prototype 以及实例之间啥关系? (2)pro ...

  5. javascript的构造函数和实例对象、prototype和__proto__的区别,原型对象及构造器的理解

    一.前言 我们先通过代码来分别打印出实例对象.构造函数,以及修改了原型对象的构造函数,通过对比内部结构来看看他们之间的区别. //定义构造函数 function Person(name, age){ ...

  6. js高级——构造函数,实例对象和原型对象——prototype、__proto__和constructor构造器

    一.前言 了解JavaScript面向对象,需要先了解三个名词: 构造函数,实例对象和原型对象. 注意:JavaScript中没有类(class)的概念,取而代之的是构造函数,两者类似却又有很大的差别 ...

  7. 构造函数、原型对象prototype、实例、隐式原型__proto__的理解

    (欢迎一起探讨,如果有什么地方写的不准确或是不正确也欢迎大家指出来~) PS: 内容中的__proto__可能会被markdown语法导致显示为proto. 建议将构造函数中的方法都定义到构造函数的原 ...

  8. Javascript 原型链之原型对象、实例和构造函数三者之间的关系

    前言:用了这么久js,对于它的原型链一直有种模糊的不确切感,很不爽,隧解析之. 本文主要解决的问题有以下三个: (1)constructor 和 prototype 以及实例之间啥关系? (2)pro ...

  9. JS高级---实例对象使用属性和方法层层的搜索 (实例对象-->原型对象-->报错)

    实例对象使用属性和方法层层的搜索:   实例对象使用的属性或者方法, 先在实例中查找, 找到了则直接使用: 找不到则, 再去实例对象的__proto__指向的原型对象prototype中找, 找到了则 ...

随机推荐

  1. 如何用Python画一个圣诞树呢?

    # ./sd.py * *** ***** ******* ********* |[root@bogon shengdan]# vim sd.py[root@bogon shengdan]# cat ...

  2. Ubuntu 获取升级信息失败。可能网络有问题

    升级Ubuntu系统时遇到的这个问题, 原因是默认的源不是国内的,而且还可能导致下载慢等问题. 1.备份源 cd /etc/apt/ sudo cp sources.list sources.list ...

  3. IT菜鸟之网站搭建(emlog)

    由多个网页组成的一种集合,叫做网站 网站分为:静态网站.动态网站  静态网站:不会因为时间.地点.用户角色等因素发生内容改变的网站 动态网站:会因为时间.地点.用户角色等因素发生内容改变的网站 注意: ...

  4. 重定向-管道技术-xargs命令详解

    重定向 什么是重定向? 将原本要输出在屏幕的内容,重新定向输出到指定的文件或设备中. 为什么要使用重定向? 1.备份的时候需要知道备份的结果. 2.屏幕上输出信息比较重要的时候需要保存下来. 3.定时 ...

  5. Centos 6.5 启动报错 "Kernel panic - not syncing: Attempted to kill init"解决办法

    某一天,开发同事突然告诉我服务器上自己的虚拟机连不上了,我登陆到服务器CAS管理界面,重启虚拟机后发现报错了 问题:Kernel panic - not syncing: Attempted to k ...

  6. 10.1 ifconfig:配置或显示网络接口信息

    ifconfig命令 用于配置网卡IP地址等网络参数或显示当前网络的接口状态,其类似于Windows下的ipconfig命令,这两个命令很容易混淆,读者需要区分一下.此外,ifconfig命令在配置网 ...

  7. 4.3 Python3进阶-函数嵌套和嵌套调用

    >>返回主目录 源码 # 函数嵌套 def func1(): print("这是外部函数") def func2(): print("这是内部函数1" ...

  8. DM8_Linux详细安装步骤

    (从虚拟机配置讲起,有基础的可以直接看二,谢谢) 一.虚拟机的安装和配置 软件:virtualbox 系统:centos7 工具:Xshell 官网下载centos7,使用virtualbox安装ce ...

  9. PyTorch 自动微分

    PyTorch 自动微分 autograd 包是 PyTorch 中所有神经网络的核心.首先简要地介绍,然后将会去训练的第一个神经网络.该 autograd 软件包为 Tensors 上的所有操作提供 ...

  10. TinyML-TVM是如何驯服Tiny的(下)

    TinyML-TVM是如何驯服Tiny的(下) Lazy Execution实际上,随着通信开销开始占主导地位,一旦用户请求,就执行算子的开销变得非常昂贵.可以通过延迟评估直到用户需要调用的结果来提高 ...