js--class类、super和estends关键词的学习笔记
前言
JavaScript 语言在ES6中引入了 class 这一个关键字,在学习面试的中,经常会遇到面试官问到谈一下你对 ES6 中class的认识,同时我们的代码中如何去使用这个关键字,使用这个关键字需要注意什么,这篇来总结一下相关知识点。
正文
1.es6之前创建对象
先来看下es6之前我们要想创建一个对象,只能通过构造函数的方式来创建,将静态方法添加在原型上面使得每一个实例能够调用该方法。
function Person(name, age) { this.name = name this.age = age Person.prototype.sayHello = function () { return "hello," + this.name + ",早上好" } } let person = new Person("serendipity", 18) console.log(person.sayHello())//hello,serendipity,早上好 console.log(person instanceof Person);//true console.log(person instanceof Object);//true
2.es6之后class的声明
类是用于创建对象的模板,他们用代码封装数据以处理该数据。js中的 class 类建立在原型之上,但也具有某些语法和语义与ES5类相似语义共享。
实际上,类是一种特殊的函数,就像定义函数声明和函数表达式一样,类的语法也有两个部分组成:类声明和类表达式。
class Person { constructor(name, age) {//自有属性,该属性出现在实例上,只能在类的构造器或者方法内部进行创建 this.name = name this.age = age } sayHello() {//等价于Perosn.prototype.sayHello return `hello,${this.name},早上好` } } let person = new Person("serendipity", 18) console.log(person.sayHello());//hello,serendipity,早上好 console.log(person instanceof Person);//true console.log(person instanceof Object);//true console.log(typeof Person);//function console.log(typeof Person.prototype.sayHello);//function
类声明允许在class中使用 constructor 方法定义一个构造器,而不需要定义专门的构造方法来当构造器使用。
class 类的语法与普通es5之前的函数语法相似,但是还存在一些特性需要注意:
(1)类的声明不会被提升,类的声明行为和 let 相似,因此执行时类会存在暂时性死区;
(2)类中所有代码自动运行在严格模式下,且改严格模式无法退出
(3) 类中所有方法都是不可枚举的,普通自定义方法只有通过 object.defineProperty() 才能将方法定义为不可枚举
(4)类中的所有方法内部都没有 [[construct]] ,因此使用new 来调用他们会抛出错误
(5)调用类构造器时不使用 new 会抛出错误
(6)试图在类的方法内部重写类名会抛出错误
将上面的代码转换为ES5之前的写法如下:
let PersonClass = (function () { "use strict" const PersonClass = function (name, age) { // 判断是否被new调用构造函数 if (typeof new.target === "undefined") { throw new Error("Constructor must be call with new.") } this.name = name this.age = age } Object.defineProperty(PersonClass.prototype, "sayHello", { value: function () { if (typeof new.target !== "undefined") {//保正调用时没有使用new throw new Error("Method cannot be called with new.") } return "hello," + this.name + ",早上好!" }, enumerable: false, configurable: true, writable: true }) return PersonClass })() var personClass = new PersonClass("serendipity", 18) console.log(personClass.name);//serendipity console.log(personClass.sayHello());///hello,serendipity,早上好!
两个PersonClass 声明,一个在外部作用域的 let 声明,另一个在立即执行函数内部的 const 声明,这就是为何类的方法不能对类名进行重写,而类的外部的代码则被允许。同时,只在类的内部类名才被视为使用了const声明,这意味着你可以在外部(相当于let)重写类名,但是不能在类的方法内部这么写。
3.类的继承
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, enumerble: true, writeable: 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
上面的代码通过构造函数和原型上面添加静态方法实现了 Rectangle 父类,然后子类 Square 通过 Rectangle.call(this,length,length) 调用了父类的构造函数,Object.create 会在内部创建一个空对象来连接两个原型对象,再手动将 constructor 指向自身。这种方法实现继承代码繁杂且不利用理解,于是ES6 class 类的创建让继承变得更加简单,使用extends 关键字来指定当前类所需要继承的父类,生成的类的原型会自动调整,还可以使用 super() 方法来访问基类的构造器。具体代码如下:
class Rectangle { constructor(length, width) { this.length = length this.width = width } getArea() { return this.length * this.width } } class Square extends Rectangle { constructor(length) { super(length, length) } getArea() { return this.length + this.length } } var square = new Square(3) console.log(square.getArea());//6 console.log(square instanceof Square);//true console.log(square instanceof Rectangle);//true
上面的代码中 Square 类重写了基类的 getArea() 方法,当派生的子类中函数名和基类中函数同名的时候,派生类的方法会屏蔽基类的方法,同时也可以再子类中getArea () { return super.getArea() }中调用基类的方法进行扩展。
4.继承类的静态成员
静态成员:直接在构造器上添加的额外的方法。例如ES5中在原型上添加的方法就属于静态成员,ES6 class类引入简化了静态成员的创建,只需要在方法与访问器属性的名称前添加 static关键字即可。例如下面的代码用于区分静态方法和实例方法。
function PersonType(name) { this.name = name; } // 静态方法 PersonType.create = function(name) { return new PersonType(name); }; // 实例方法 PersonType.prototype.sayName = function() { console.log(this.name); };
var person = PersonType.create("Nicholas");
在ES6中要想使用静态成员如下:
class Rectangle { constructor(length ,width) { this.length = length this.width = width } getArea() { return this.length * this.width } static create(length,width) { return new Rectangle(length , width) } } class Square extends Rectangle{ constructor (length){ super(length,length) } } var square =Square.create(3,4) console.log(square.getArea());//12 console.log(square instanceof Square);//false console.log(square instanceof Rectangle);//true
上面的代码中,一个新的静态方法 create() 被添加到 Rectangle 类中,通过继承,以Square.create() 的形式存在,并且其行为方式与Rectangle.create() 一样。需要注意静态成员不懂通过实例来访问,始终需要直接调用类自身来访问他们。
写在最后
以上就是本文的全部内容,希望给读者带来些许的帮助和进步,方便的话点个关注,小白的成长踩坑之路会持续更新一些工作中常见的问题和技术点。
原文地址:https://www.cnblogs.com/zaishiyu/p/15108932.html
- 学习SpringMVC——拦截器
- 学习SpringMVC——国际化+上传+下载
- 行业研究:大数据(一)
- 控制并发访问的三道屏障: WCF限流(Throttling)体系探秘[下篇]
- 如何通过VPC在本机搭建局域网
- 你常用的10个MySQL命令
- WCF技术剖析之三十一: WCF事务编程[下篇]
- WCF技术剖析之三十一:WCF事务编程[上篇]
- 学习SpringMVC——你们要的REST风格的CRUD来了
- 并发中的同步--WCF并发体系的同步机制实现
- WCF 技术剖析之三十三:你是否了解WCF事务框架体系内部的工作机制?[下篇]
- 学习SpringMVC——从HelloWorld开始
- 小程序年底重磅更新,小游戏上线,最强入口也来了!
- 学习SpringMVC——如何获取请求参数
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 机器学习模型评估指标总结!
- 地宫取宝 (第五届蓝桥杯省赛C++A/B组)
- codeforce 650A (数学)
- POJ3279 (二进制枚举)
- codeforces 1312C(思维)
- codeforces1369C(贪心)
- 新人赛《金融风控贷款违约》避坑指南!
- codeforces 911C (找规律)
- 4C - Registration System (Map)
- HDU5269 (字典树)
- Shaolin(map)
- 189A Cut Ribbon(dp)
- codeforces 1379A(暴力)
- codeforces 1374D(数学)
- Yet Another Walking Robot (Map)