资讯专栏INFORMATION COLUMN

es6之js的类

libin19890520 / 378人阅读

摘要:生成的类的原型会被自动调整,而你还能调用方法来访问基类的构造器。唯一能避免调用的办法,是从类构造器中返回一个对象。

起源

JS 从创建之初就不支持类,也没有把类继承作为定义相似对象以及关联对象的主要方式,这让不少开发者感到困惑。而从 ES1 诞生之前直到ES5 时期,很多库都创建了一些工具,让 JS 显得貌似能支持类。尽管一些 JS 开发者强烈认为这门语言不需要类,但为处理类而创建的代码库如此之多,导致 ES6 最终引入了类。

ES5 中的仿类结构

JS 在 ES5 及更早版本中都不存在类。与类最接近的是:创建一个构造器,然后将方法指派到
该构造器的原型上。这种方式通常被称为创建一个自定义类型。例如:

function PersonType(name) {
this.name = name;
}
PersonType.prototype.sayName = function() {
console.log(this.name);
};
let person = new PersonType("Nicholas");
person.sayName(); // 输出 "Nicholas"
console.log(person instanceof PersonType); // true
console.log(person instanceof Object); // true

此代码中的 PersonType 是一个构造器函数,并创建了单个属性 name 。 sayName() 方法被
指派到原型上,因此在 PersonType 对象的所有实例上都共享了此方法。接下来,使用 new
运算符创建了 PersonType 的一个新实例 person ,此对象会被认为是一个通过原型继承了
PersonType 与 Object 的实例。
这种基本模式在许多对类进行模拟的 JS 库中都存在,而这也是 ES6 类的出发点。

es6基本的类的声明

类声明以 class 关键字开始,其后是类的名称;剩余部分的语法看起来就像对象字面量中的
方法简写,并且在方法之间不需要使用逗号。作为范例,此处有个简单的类声明:

class PersonClass {
// 等价于 PersonType 构造器
constructor(name) {
this.name = name;
}
// 等价于 PersonType.prototype.sayName
sayName() {
console.log(this.name);
}
}
let person = new PersonClass("Nicholas");
person.sayName(); // 输出 "Nicholas"
console.log(person instanceof PersonClass); // true
console.log(person instanceof Object); // true
console.log(typeof PersonClass); // "function"
console.log(typeof PersonClass.prototype.sayName); // "function"

es6中类关键字class本质是一种语法糖,而使用类实现的继承其本质上就是原型的继承.

为何要使用类的语法

类声明不会被提升,这与函数定义不同。类声明的行为与 let 相似,因此在程序的执行到达声明处之前,类会存在于暂时性死区内。

类声明中的所有代码会自动运行在严格模式下,并且也无法退出严格模式。

调用类构造器时不使用 new ,会抛出错误。

试图在类的方法内部重写类名,会抛出错误。

作为一级公民的类

在编程中,能被当作值来使用的就称为一级公民( first-class citizen ),意味着它能作为参
数传给函数、能作为函数返回值、能用来给变量赋值。 JS的函数就是一级公民(它们有时又
被称为一级函数),此特性让 JS 独一无二
ES6 延续了传统,让类同样成为一级公民。这就使得类可以被多种方式所使用。例如,它能
作为参数传入函数:

function createObject(classDef) {
return new classDef();
}
let obj = createObject(class {
sayHi() {
console.log("Hi!");
}
});
obj.sayHi(); // "Hi!
使用派生类进行继承

ES6 之前,实现自定义类型的继承是个繁琐的过程。严格的继承要求有多个步骤。例如,研
究以下范例:

function Rectangle(length, width) {
this.length = length;
this.width = width;
}
Rectangle.prototype.getArea = function() {
return this.length * this.width;
};
function Square(length) {
Rectangle.call(this, length, length);
}
Square.prototype = Object.create(Rectangle.prototype, {
constructor: {
value:Square,
enumerable: true,
writable: true,
configurable: true
}
});
var square = new Square(3);
console.log(square.getArea()); // 9
console.log(square instanceof Square); // true
console.log(square instanceof Rectangle); // true

Square 继承了 Rectangle ,为此它必须使用 Rectangle.prototype 所创建的一个新对象来
重写 Square.prototype ,并且还要调用 Rectangle.call() 方法。这些步骤常常会搞晕 JS
的新手,并会成为有经验开发者出错的根源之一。

类让继承工作变得更轻易,使用熟悉的 extends 关键字来指定当前类所需要继承的函数,即
可。生成的类的原型会被自动调整,而你还能调用 super() 方法来访问基类的构造器。此处
是与上个例子等价的 ES6 代码:

class Rectangle {
constructor(length, width) {
this.length = length;
this.width = width;
}
getArea() {
return this.length * this.width;
}
}
class Square extends Rectangle {
constructor(length) {
// 与 Rectangle.call(this, length, length) 相同
super(length, length);
}
}
var square = new Square(3);
console.log(square.getArea()); // 9
console.log(square instanceof Square); // true
console.log(square instanceof Rectangle); // true
使用 super() 时需牢记以下几点:

你只能在派生类中使用 super() 。若尝试在非派生的类(即:没有使用 extends关键字的类)或函数中使用它,就会抛出错误。

在构造器中,你必须在访问 this 之前调用 super() 。由于 super() 负责初始化this ,因此试图先访问 this 自然就会造成错误。

唯一能避免调用 super() 的办法,是从类构造器中返回一个对象。

总结

ES6 的类让 JS 中的继承变得更简单,因此对于你已从其他语言学习到的类知识,你无须将其
丢弃。 ES6 的类起初是作为 ES5 传统继承模型的语法糖,但添加了许多特性来减少错误。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/43515.html

相关文章

  • javascript模拟类继承

    摘要:欢迎关注我的博客正文让我来构造函数其实,模拟一个类的方式非常的简单构造函数。我们先来看一个例子这里通过构造函数模拟出来的类,其实和其他语言的类行为上是基本一致的,唯一的区别就是它不具备私有方法。 前言 ES6时代的来临,使得类继承变得如此的圆滑。但是,你有思考过ES6的类继承模式吗?如何去实现它呢? 类继承对于JavaScript来说,实现方式与Java等类语言大不相同。熟悉JavaS...

    Jochen 评论0 收藏0
  • es6 - 类

    摘要:创建自定义类型看下面一段代码上面代码使用创建了一个自定义类型,是这个类的构造器,是类的公共方法。注意事项在使用类继承的实现中,需要注意的点是如果子类没有重写方法,默认会调用父类的构造器方法。 es6 类-class 与大多正规的面向对象编程语言不同(比如java),js在创建之初就不支持类。js的面向对象编程实现方式是通过构造函数和原型来实现的。 我之前以为es6引入类的概念将会带给这...

    notebin 评论0 收藏0
  • JavaScript => TypeScript 类入门

    摘要:静态属性静态方法目前支持静态方法表示,类属性及静态属性目前作为提案还未正式成为标准。在中,抽象类不能用来实例化对象,主要做为其它派生类的基类使用。不同于接口,抽象类可以包含成员的实现细节。中也是这样规定的抽象类不允许直接被实例化。 尝试重写 在此之前,通过《JavaScript => TypeScript 入门》已经掌握了类型声明的写法。原以为凭着那一条无往不利的规则,就可以开开心心的...

    geekidentity 评论0 收藏0
  • 深入理解ES6笔记(九)JS的类(class)

    摘要:主要知识点类声明类表达式类的重要要点以及类继承深入理解笔记目录中的仿类结构在及更早版本中都不存在类。与类最接近的是创建一个构造器,然后将方法指派到该构造器的原型上。调用类构造器时不使用,会抛出错误。 主要知识点:类声明、类表达式、类的重要要点以及类继承showImg(https://segmentfault.com/img/bVbfWnV?w=933&h=662); 《深入理解ES6...

    xinhaip 评论0 收藏0
  • ES6学习笔记箭头函数

    摘要:特性介绍箭头函数是新增的特性之一,它为这门语言提供了一种全新的书写函数的语法。用生成的函数会定义一个自己的,而箭头函数没有自己的,而是会和上一层的作用域共享。 本文同步自我得博客:http://www.joeray61.com JS中的箭头 箭头在JS里并不算是个新鲜的玩意儿,一直以来,JS都支持-->这样的箭头。 很早的时候有些浏览器还不支持JS,当时的人们为了兼容这些浏览器,需要这...

    Vultr 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<