[ESNext]现在就学起来:class

2024-02-21 15:18

本文主要是介绍[ESNext]现在就学起来:class,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

ES5 及之前

定义

在 ES5 中,并没有类的概念,但是已经有了类型的概念。

那时,我们想创建一个类型,是这样做的:

function MyClass() {alert(this instanceof MyClass);
}

如此,我们定义了一个类型,但同时,他也是一个函数。

我们看看不同调用方法所得到的结果:

MyClass(); // false
new MyClass(); // true

第一句直接调用会输出 false ,因为函数内上下文 (context) 会指向 window ,因此会去检测 window 的 prototype 是否存在 MyClass 的原型(即,是否从 MyClass 继承而来)。答案是显而易见的。

而使用 new 去创建一个对象并链接到 MyClass 的时候,new 出来的对象 prototype 是存在 MyClass 的原型的。而且在执行时他的上下文会指向用 new 创建出的这个对象,所以 this 指向 (new MyClass 创建出的对象) instanceof MyClass 则是成立的。

 

继承

上文中我们提到了继承,但是在没有类的情况下如何进行继承呢?

这个时候会有人想到,既然有原型的概念,那么是不是可以在原型上去累加原型形成一个原型链来实现这个效果?

于是,出现了这样一种写法:

function A() {this.text = "father";
}A.prototype.Print = function () {alert(this.text);
};function B() {this.text = "son";
}B.prototype = new A();
B.prototype.constructor = B;var a = new A();
a.Print();var b = new B();
b.Print();

初看是不是一头雾水?谁是父类?谁是子类? this.text 到底指向谁?B.prototype = new A(); 是什么鬼?直接 = A 为什么不行?

B.prototype.constructor 为什么要等于 B?不等于不行吗?等等等等问题~

我们一步一步解析看看~

首先,A 是父类,B是子类。

this.text 主要看 new 出来的对象指向的是由 A 创建的还是 B 创建的。

B.prototype 如果直接等于 A ,那么如果修改 B.prototype 下的内容,就相当于直接修改了 A 的内容,而我们其实想修改的是 A 创建出来的副本对象。

B.prototype.constructor 默认指向 B 的构造器,但是由于 B.prototype 被修改,所以需要重新指向,否则会造成构造器相关操作错误的指向 A 进而出错。

哇~看到这里你发现,怎么这么麻烦啊,我只是单纯的想让 B 继承一下 A 的东西而已啊。

没错,就是这么一个简单的事情在 ES5 及之前并做不到很简单的去写和去理解。

 

私有函数、私有变量

这两个真的做不到,没办法。不论是从语法、解析、可能的写法,都做不到。

什么?你说在函数和变量前加一个 _ 下划线代表私有?

那是不是意味着我可以随意对你的库进行注入修改逻辑或者截取秘密数据?

 

 ES6 时代

定义

在 ES6 时代,已经有了 class 关键字及其概念。

这时,想定义一个类型就非常简单了:

class MyClass {constructor() {console.dir(this);}
}

注意:constructor 不是必须的,只有当你在 new 的时候想传入一些参数或者做一些事的时候才需要。这里为了演示。

为什么这个演示代码中我不再写 this instanceof MyClass 了呢?

因为这个时候我们直接调用 MyClass() 已经会报错了。这种写法在检查上已经和函数有了一定的区别。

Uncaught TypeError: Class constructor MyClass cannot be invoked without 'new',

但是请注意, typeof MyClass 依然输出的是 function 。

虽然如此,给我们带来的好处还是很多的,上面这条算一个。

另外,this 上下文已经不会因为误调用而产生指向问题。这里特别指出,我着重了“误调用”,因为你如果使用 .call 或者 .apply 调用对象内函数强制改变上下文还是可以做到的。

 

继承

既然定义有了改变,那么继承方式是否有改变呢?答案是肯定的,这次改动隐藏了绝大部分的概念和复杂逻辑。

写法如下:

class A {constructor() {this.text = "father";}Print() {alert(`father's ${this.text}`);}
}class B extends A {constructor() {super();this.text = "son";}Print() {alert(`son's ${this.text}`);}PrintA() {super.Print();}
}const a = new A();
a.Print();const b = new B();
b.Print();
b.PrintA();

在此例子中,我们定义了一个 class A,赋值了一个 text 为 father ,然后定义了一个函数 Print 。在这里为了区别子类,特意加上了 father's 前缀进行输出。

然后定义了一个 class B,并赋值了 text 为 son,注意!constructor 的第一行必须是 super(); 也就是说,子类必须在构造自身前先对父类进行构造,否则在操作 this 时会报错。

我们同时对 class B 中定义一个函数 Print 和 PrintA。

然后对 A 和 B 分别用 new 运算符创建对象。

调用 a.Print() 输出 father's father

调用 b.Print() 输出 son's son

从开始到现在我们都没有问题,需要留意的是下一句:

b.PrintA()

之类需要注意一下,我们内部是怎么写的呢?

super.Print();

也就是说,我们调用了继承的父类的 Print 函数,此时输出 father's son

在这个例子中,我们没有因为语法写法而感到迷惑,也不会造成,哦天啊!他们两个混为一谈了这样的问题。

可以说是十分简洁了。

最后需要注意一下! ES6 的 class 语法只支持单继承,也就是说, B 不能同时继承 A、C、....等等更多的类,该语法只支持继承一个。当然,有其他方式可以解决,这是后话了。

 

私有函数、私有变量

虽然在语法上有了革新,但是因底层限制,依然没有私有函数于私有变量。

 

EXNext

从 ES6 开始,EcmaScript 不再以版本号作为升级标识而是改成了年份标识。

也就是说,一年会升级一次或更多次。我们统称其为 ESNext。

定义

class A {#text = "nivk";age = 52;get Text() {return this.#text;}Print() {alert(`我叫 ${this.Text},我今年 ${this.age} 岁。`);}
}class B extends A {#text = "dog";age = 26;
}const a = new A();
a.Print();const b = new B();
b.Print();

我们定义了 A ,并写了一个私有变量 #text ,写了一个公共变量 age,一个 get 访问器 Text 还有一个函数 Print。

再定义一个 B,覆写了 #text 私有变量和公共变量 age。

输出结果令人惊奇:

我叫 nivk,我今年 52 岁。

我叫 nivk,我今年 26 岁。

毕竟,我不是 dog 不是么~(题外话)

为什么 age 被覆写了而 #text 没有呢?这里并不是这个 get 访问器起了作用,而是 #text 本身被定义成了私有的,那么他的可访问性就受到了限制,#text 只能被自身读写,而不能被子类、外部任何代码中访问和写入。

私有属性或私有函数使用前缀 # 井号来标识,为何使用此符号标识呢?这涉及到了一些性能问题,如有兴趣请至 TC39 委员会的 Github 仓库查阅。

这就是私有变量。同样我们也可以在 class 中定义私有变量如下所示(仅关键代码):

#TestFunction() {// balabala....
}Print() {this.#TestFunction();
}

如此一来,我们便可安心将类库发布出去也不怕别人误用或可规避一些隐性安全风险。

 

结尾

EcmaScript 标准一直在更新,所以此文仅代表发表此文时的最新状态,如果后续有语法、功能的更新则我也会在这里进行更新。

素质二连!!~~~关注、点赞~~~撒花!~

 

这篇关于[ESNext]现在就学起来:class的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/732221

相关文章

Java编译生成多个.class文件的原理和作用

《Java编译生成多个.class文件的原理和作用》作为一名经验丰富的开发者,在Java项目中执行编译后,可能会发现一个.java源文件有时会产生多个.class文件,从技术实现层面详细剖析这一现象... 目录一、内部类机制与.class文件生成成员内部类(常规内部类)局部内部类(方法内部类)匿名内部类二、

前端 CSS 动态设置样式::class、:style 等技巧(推荐)

《前端CSS动态设置样式::class、:style等技巧(推荐)》:本文主要介绍了Vue.js中动态绑定类名和内联样式的两种方法:对象语法和数组语法,通过对象语法,可以根据条件动态切换类名或样式;通过数组语法,可以同时绑定多个类名或样式,此外,还可以结合计算属性来生成复杂的类名或样式对象,详细内容请阅读本文,希望能对你有所帮助...

VUE动态绑定class类的三种常用方式及适用场景详解

《VUE动态绑定class类的三种常用方式及适用场景详解》文章介绍了在实际开发中动态绑定class的三种常见情况及其解决方案,包括根据不同的返回值渲染不同的class样式、给模块添加基础样式以及根据设... 目录前言1.动态选择class样式(对象添加:情景一)2.动态添加一个class样式(字符串添加:情

提示:Decompiled.class file,bytecode version如何解决

《提示:Decompiled.classfile,bytecodeversion如何解决》在处理Decompiled.classfile和bytecodeversion问题时,通过修改Maven配... 目录问题原因总结问题1、提示:Decompiled .class file,China编程 bytecode

MySQL数据库宕机,启动不起来,教你一招搞定!

作者介绍:老苏,10余年DBA工作运维经验,擅长Oracle、MySQL、PG、Mongodb数据库运维(如安装迁移,性能优化、故障应急处理等)公众号:老苏畅谈运维欢迎关注本人公众号,更多精彩与您分享。 MySQL数据库宕机,数据页损坏问题,启动不起来,该如何排查和解决,本文将为你说明具体的排查过程。 查看MySQL error日志 查看 MySQL error日志,排查哪个表(表空间

用Unity2D制作一个人物,实现移动、跳起、人物静止和动起来时的动画:中(人物移动、跳起、静止动作)

上回我们学到创建一个地形和一个人物,今天我们实现一下人物实现移动和跳起,依次点击,我们准备创建一个C#文件 创建好我们点击进去,就会跳转到我们的Vision Studio,然后输入这些代码 using UnityEngine;public class Move : MonoBehaviour // 定义一个名为Move的类,继承自MonoBehaviour{private Rigidbo

为什么现在很多人愿意选择做债务重组?债重组真的就这么好吗?

债务重组,起初作为面向优质企业客户的定制化大额融资策略,以其高效周期著称,一个月便显成效。然而,随着时代的车轮滚滚向前,它已悄然转变为负债累累、深陷网贷泥潭者的救赎之道。在此路径下,个人可先借助专业机构暂代月供,经一段时间养护征信之后,转向银行获取低成本贷款,用以替换高昂网贷,实现利息减负与成本优化的双重目标。 尽管债务重组的代价不菲,远超传统贷款成本,但其吸引力依旧强劲,背后逻辑深刻。其一

类型信息:反射-Class

在说反射前提一个概念:RTTI(在运行时,识别一个对象的类型) public class Shapes {public static void main(String[] args) {List<Shape> shapes = Arrays.asList(new Circle(), new Square(), new Triangle());for (Shape shape : shapes

react笔记 8-17 属性绑定 class绑定 引入图片 循环遍历

1、绑定属性 constructor(){super()this.state={name:"张三",title:'我是一个title'}}render() {return (<div><div>aaaaaaa{this.state.name}<div title={this.state.title}>我是一个title</div></div></div>)} 绑定属性直接使用花括号{}   注

神经网络训练不起来怎么办(零)| General Guidance

摘要:模型性能不理想时,如何判断 Model Bias, Optimization, Overfitting 等问题,并以此着手优化模型。在这个分析过程中,我们可以对Function Set,模型弹性有直观的理解。关键词:模型性能,Model Bias, Optimization, Overfitting。 零,领域背景 如果我们的模型表现较差,那么我们往往需要根据 Training l