本人之前对Class一直不够重视。平时对原型的使用,也仅限于在构造函数的prototype上挂属性。原型尚且用不着,更何况你Class只是原型的一颗语法糖?

直到公司开始了一个webgis项目,使用openlayers。看了下openlayers的代码,整个api都是用Class构建的。我才意识到,对Class的使用已经很普遍了,很多库都在基于Class构建的,所以必须把它研究明白了。

我是这么想的,先把原型搞明白,再把Class搞明白,最后实践一下,把Class的各项语法,用原型还原出来。这样,一定能很好的掌握JS的面向对象思想。

一、回顾一下对象的原型

对于一门编程语言来说,把同一类事物抽象出一个数据结构,并以此为模板创建实例,是一个基本的需求,这也就是面向对象的思想。

JS从一开始就被设计成一门面向对象的语言,它是通过构造函数来作为“模板”,来生成对象的。比如这样:

function Student(name, age) {
this.name = name;
this.age = age;
this.say = function(intro) {
console.log(intro);
}
}
let xiaohong = new Student('小红', 14);
let xiaoming = new Student('小明', 15);
xiaohong.say('我是小红,我喜欢看电影'); //我是小红,我喜欢看电影
xiaoming.say('我是小明,我喜欢小红'); //我是小明,我喜欢小红

JS中的构造函数和普通函数有什么不同呢?

其实,任何一个普通函数通过new运算符调用,都可以称作构造函数。构造函数的特别之处,就是里面多了一个this。这个this就是构造函数所返回的对象。普通函数里面没有this,通过new调用得到的是一个空对象,没有任何意义。

现在,可以通过构造函数轻松生成同一类事物——学生了。他们都有姓名和年龄,却又各不相同。

然而,还有一些东西,是他们都一样的,是他们共同分享的。比如他们的班级都是三年二班,班主任都是周杰伦。怎么表示这种关系呢?

这就是prototype,也就是原型。

在JS中,所有函数都有一个prototype属性。这是一个对象,默认只有一个属性:constructor,指向构造函数自身。也就是说,构造函数和原型,通过prototype和construcotr,相互引用。

通过构造函数生成的所有对象,共同分享这个prototype对象。

function Student(name, age) {
this.name = name;
this.age = age;
}
Student.prototype.className = '三年二班';
Student.prototype.teacher = '周杰伦';
let xiaohong = new Student('小红', 14);
let xiaoming = new Student('小明', 15);
console.log(xiaohong.className, xiaohong.teacher); //三年二班 周杰伦
console.log(xiaoming.className, xiaoming.teacher); //三年二班 周杰伦

现在,我们有了构造函数、原型、对象。它们是什么关系呢?

构造函数就是原型和对象之间的纽带,负责为原型这个“妈妈”生“孩子”,也就是对象。原型上的东西,是所有孩子都一样的,比如国家、肤色。构造函数上的东西,是孩子们可以个性化的,比如相貌、身高。

也许你还听说过constructor和__proto__,它们又是做什么的?很简单,它们的存在,只是为了:让构造函数、原型、对象三者之间可以相互引用。

function Student(name, age) {
this.name = name;
this.age = age;
}
let xiaohong = new Student('小红', 14);
console.log(Student.prototype); //{constructor: Student}
console.log(Student.prototype.constructor === Student); //true
console.log(xiaohong.__proto__ === Student.prototype); //true
console.log(xiaohong.constructor === Student); //true

通过===我们可以得知,它们之间确实是相互引用关系,而不是只是值想等的关系。

二、用原型实现Class的各项语法

接下来,我们用原型的写法,把Class的各项语法还原出来。

(1)构造函数(实例属性和方法)

//Class语法
class Student {
constructor(name, age) {
this.name = name;
this.age = age;
}
}
//原型语法
function Student(name, age) {
this.name = name;
this.age = age;
}

(2)原型的属性和方法

//Class语法
class Student {
teacher = '周杰伦';
say() {
console.log('认真听讲!');
}
}
//原型语法
function Student() {}
Student.prototype.teacher = '周杰伦';
Student.prototype.say = function() {
console.log('认真听讲!');
}; let xiaohong = new Student();
console.log(xiaohong.teacher); //周杰伦
xiaohong.say(); //认真听讲!

(3)静态属性和方法

//Class语法
class Student {
static teacher = '周杰伦';
static say() {
console.log('认真听讲!');
}
}
//原型语法
function Student() {}
Student.teacher = '周杰伦';
Student.say = function() {
console.log('认真听讲!');
}; console.log(Student.teacher); //周杰伦
Student.say(); //认真听讲!

(4)继承

// Class语法
class Person {
constructor(name) {
this.name = name;
}
say() {
console.log('我会说话');
}
static think() {
console.log('人类会思考');
}
}
class Student extends Person {
constructor(name, school) {
super(name);
this.school = school;
}
study() {
console.log('我要上学');
}
}
let xiaohong = new Student('小红', '十一学校'); // 原型语法
function Person(name) {
this.name = name;
}
Person.prototype.say = function() {
console.log('我会说话');
}
Person.think = function() {
console.log('人类会思考');
} function Student(school) {
this.school = school;
}
Student.prototype = new Person('小红');
Student.prototype.constructor = Student;
Student.prototype.study = function() {
console.log('我要上学');
};
Object.setPrototypeOf(Student, Person);
let xiaohong = new Student('十一学校'); console.log(xiaohong.name); //小红
console.log(xiaohong.school); //十一学校
xiaohong.say(); //我会说话
xiaohong.study(); //我要上学
Student.think(); //人类会思考

由此可见,特别在继承的语法上,Class要比原型简单的多。

总的来说,作为原型的语法糖,Class不仅语义更明确,更好理解,写法上也更简单。所以,以后就愉快的使用Class吧!

本人水平非常有限,写作主要是为了把自己学过的东西捋清楚。如有错误,还请指正,感激不尽。

用原型实现Class的各项语法的更多相关文章

  1. JS高级---原型的简单的语法

    原型的简单的语法 构造函数,通过原型添加方法,以下语法,手动修改构造器的指向 实例化对象,并初始化,调用方法 <!DOCTYPE html> <html lang="en& ...

  2. JavaScript原型之路

    简介 最近我在学习Frontend Masters 上的高级JavaScript系列教程,Kyle 带来了他的“OLOO”(对象链接其他对象)概念.这让我想起了Keith Peters 几年前发表的一 ...

  3. Thymeleaf常用语法:模板注释

    Thymeleaf模板注释分为标准HTML/XML注释.解析层注释.原型注释三种. 一.注释说明 1.标准HTML/XML注释 直接通过浏览器打开,不显示,Thymeleaf模板引擎解析也不处理,但查 ...

  4. 理解Javascript的原型和原型链

    前言 本文2088字,阅读大约需要13分钟. 总括: 结合实例阐述了原型和原型链的概念并总结了几种创建对象的方法,扩展原型链的方法. 参考文章:The Secret Life of Objects,继 ...

  5. ES6笔记(一):ES6所改良的javascript“缺陷”

    块级作用域 ES5没有块级作用域,只有全局作用域和函数作用域,由于这一点,变量的作用域甚广,所以一进入函数就要马上将它创建出来.这就造成了所谓的变量提升. ES5的"变量提升"这一 ...

  6. [转载]Web前端开发工程师编程能力飞升之路

    [背景] 如果你是刚进入web前端研发领域,想试试这潭水有多深,看这篇文章吧:如果你是做了两三年web产品前端研发,迷茫找不着提高之路,看这篇文章吧:如果你是四五年的前端开发高手,没有难题能难得住你的 ...

  7. 【转】Web前端研发工程师编程能力飞升之路

    分类: Javascript | 出自 海玉的博客 今天看到这篇文章.写的非常有意思.发现自己还有很长的一段路要走. [背景] 如果你是刚进入WEB前端研发领域,想试试这潭水有多深,看这篇文章吧: 如 ...

  8. 笔记(一):ES6所改良的javascript“缺陷”

    ES6笔记(一):ES6所改良的javascript“缺陷”   块级作用域 ES5没有块级作用域,只有全局作用域和函数作用域,由于这一点,变量的作用域甚广,所以一进入函数就要马上将它创建出来.这就造 ...

  9. Web前端研发工程师编程能力飞升之路

    今天看到这篇文章.写的非常有意思,于是转载了.看看我们都处于什么的阶段. [背景] 如果你是刚进入web前端研发领域,想试试这潭水有多深,看这篇文章吧:如果你是做了两三年web产品前端研发,迷茫找不着 ...

  10. Web前端开发工程师编程能力飞升之路

    [背景] 如果你是刚进入web前端研发领域,想试试这潭水有多深,看这篇文章吧:如果你是做了两三年web产品前端研发,迷茫找不着提高之路,看这篇文章吧:如果你是四五年的前端开发高手,没有难题能难得住你的 ...

随机推荐

  1. Oracle批量处理SQL

    批量更新且更新字段数字需要递增 示例: DECLARE n int; -- 定义变量 BEGIN n:=1000010; --为n 赋值 FOR i IN (SELECT AGENCY.ID FROM ...

  2. PerfView 洞察C#托管堆内存 "黑洞现象"

    一:背景 1. 讲故事 首先声明的是这个 黑洞 是我定义的术语,它是用来表示 内存吞噬 的一种现象,何为 内存吞噬,我们来看一张图. 从上面的 卦象图 来看,GCHeap 的 Allocated=85 ...

  3. Vue: 在vscode中添加vue的代码片段

    创建vue文件模板 打开vscode,文件–>首选项->用户代码片段,在弹出的搜索框中输入vue,回车 删除原内容,将如下内容粘贴 { "Print to console&quo ...

  4. 熟悉又陌生的package.json

    前言 随着前端的不断发展,package.json可谓是在前端项目中无处不在,它不仅在项目根目录会有,而且在 node_modules 中也存在.那么这个文件到底是干嘛的,又有什么作用?很多人对它的认 ...

  5. nlp入门(三)基于贝叶斯算法的拼写错误检测器

    源码请到:自然语言处理练习: 学习自然语言处理时候写的一些代码 (gitee.com) 数据来源:norvig.com/big.txt 贝叶斯原理可看这里:机器学习算法学习笔记 - 过客匆匆,沉沉浮浮 ...

  6. 一文搞明白STM32芯片存储结构

    一.前言 本篇介绍STM32芯片的存储结构,ARM公司负责提供设计内核,而其他外设则为芯片商设计并使用,ARM收取其专利费用而不参与其他经济活动,半导体芯片厂商拿到内核授权后,根据产品需求,添加各类组 ...

  7. 知识图谱(Knowledge Graph)- Neo4j 5.10.0 Docker 安装

    知识图谱(Knowledge Graph)- Neo4j 5.10.0 Docker 安装 知识图谱(Knowledge Graph)- Neo4j 5.10.0 CentOS 安装 https:// ...

  8. 【opencv】传统目标检测:Haar检测器实现人脸检测

    传统目标分类器主要包括Viola Jones Detector.HOG Detector.DPM Detector,本文主要介绍VJ检测器,在VJ检测器基础上发展出了Haar检测器,Haar检测器也是 ...

  9. 【RocketMQ】消息的存储总结

    当Broker收到生产者的消息发送请求时,会对请求进行处理,从请求中解析发送的消息数据,接下来以单个消息的接收为例,看一下消息的接收过程. 数据校验 封装消息 首先Broker会创建一个Message ...

  10. 三维模型OSGB格式轻量化技术在大规模场景的加载和渲染的作用分析

    三维模型OSGB格式轻量化技术在大规模场景的加载和渲染的作用分析 在移动设备上,大规模场景的加载和渲染是一个不容忽视的问题.对于OSGB格式轻量化处理来说,大规模场景的加载和渲染也是其中一项重要的任务 ...