ES6 class关键字 ~ 非常详细
下面的对ES6中class关键字的整理,希望可以帮助到有需要的小伙伴~
文章目录
- 类的声明
- 构造函数
- getter与setter
- 不允许提前声明
- 不允许重复声明
- 静态方法
- 静态方法的语法
- 类的继承
- 实现类的继承
- 继承于内置对象
- Super关键字
- 类的实例
传统面向对象是基于类的面向对象,类的继承实际上是构造函数的继承
JSON是基于原型的面向对象
es6 给了JSON类的语法规则,但是底层没有提供类,底层是构造函数。类的继承实际上是构造函数的继承。
// 这个原型指向对象
Hero.prototype = {age : 18,myJob : function () {console.log("eat");}
}
var hero = new Hero();// ES6创建类
class Hero {// 构造器constructor() {this.name = "张无忌";this.sayMe = function () {console.log("this is 张无忌");}}
}
类的声明
声明类具有以下两种方式:
类的声明方式
class name [extends]{// class body }
name: 表示当前声明的类名。
extends:继承
但是不同于类表达式,类声明不允许再次声明已经存在的类,否则将会抛出一个类型错误。
类的表达式方式
const MyClass = class [className][extends]{// class body ); // 或者 let MyClass = class [className][extends]{// class body ); // 或者 var MyClass = class [className][extends]{// class body );
和函数表达式相同的一点是,类表达式可以是命名也可以是匿名的。如果是命名类表达式,这个名字只能在类体内部才能访问到。
实例:
/*1. 类的声明方式class className {内部结构}* class关键字 - 用于创建类* className - 创建的类名* 使用类的声明方式时–不允许重复声明的*/class Hero {}/*
2.类的表达式方式const/let/var className = class [className]{内部结构}* class关键字 – 用于创建类* myclass/className - 表示创建的类名* myClass -类名,用于后面的代码逻辑进行调用* className -类名,用于当前类的内部使用的
*/const myHero = class Hero {}// 使用var关键字可以重复声明一个类,其余声明类的方式都不允许重复声明
var myHero2 = class Hero2 {}
var myHero2 = class Hero2 {}
构造函数
构造函数(Constructor )是用于创建和初始化类中创建的一个对象的一种特殊方法。
constructor([arguments]) { ...}
- 在一个类中只能有一个名为“constructor”的特殊方法。一个类中出现多次构造函数(Constructor)方法将会抛出一个SyntaxError错误。
- 在一个构造方法中可以使用super关键字来调用一个父类的构造方法。
- 如果没有显式指定构造方法,则会添加默认的constructor方法。
- 如果不指定一个构造函数( constructor )方法,则使用一个默认的构造函数( constructor ) 。
/*创建类 - 结构* 外层的类的语法结构* 内层的构造器的语法结构
*/class Hero {// 构造器constructor() {this.name = "Jenny";this.sayMe = () => {console.log("this is Jenny");}}
}let hero = new Hero();
console.log(hero); // Hero { name: 'Jenny', sayMe: [Function] }
hero.sayMe(); // this is Jenny
getter与setter
与ECMAScript 5一样,在“类”的内部可以使用get和 set 关键字(不可以自己定义),对某个属性设置存值函数和取值函数,拦截该属性的存取行为。
在ES5中,et 和 set 是函数名,可以自己定义
/*// ES5 - get 和 set 是函数名,可以自己定义
function fn() {var v = 100; // 局部变量return {get : function () {return v;},set : function (value) {v = value;}}
}var obj = fn();
console.log(obj.get()); // 100
obj.set(99);
console.log(obj.get()); // 99*//*function fn() {var v = 100;this.get = function () {return v;}this.set = function (value) {v = value;}
}var obj = new fn();
obj.set(999);
console.log(obj.get()); // 999*/// ES6
// 创建对象的属性 可以 设置和获取
/*class Hero {constructor() {this.v = 100;}
}var hero = new Hero();
console.log(hero.v); // 100*/// get 和 set [关键字]
class Hero {constructor() {this.v = 100;}get getV() {return this.v;}set setV(value) {this.v = value;}
}var hero = new Hero();
console.log(hero); // Hero { v: 100 } 没有get和set方法
hero.getV(); // TypeError: hero.getV is not a function
console.log(hero.v);
console.log();// 可以设置一个属性 没有自带的 get和set Object.defineProperty
不允许提前声明
声明类时,是不存在声明提前的现象的。如下示例代码所示:
new Foo():// ReferenceError: Foo is not defined
class Foo {}
上述代码示例中,Foo类调用在前,声明在后。由于ECMAScript6不允许类的声明提前,结果为报错。
这种规定的原因与继承有关,必须保证子类在父类之后定义。
不允许重复声明
声明类时,是不存在重复声明的。如果一个类被重复声明的话,则引起解析错误。
如下示例代码所示:
class Foo {};
class Foo {}; // SyntaxError; ldentifier 'Foo' has already been declared
若之前使用类表达式定义了一个类,则再次声明这个类同样会引起解析错误。
let Foo = class {};
class Foo {}}; // SvntaxError; ldentifier 'Foo' has already been declared
静态方法
静态方法的语法
static关键字为一个类定义了一个静态方法。静态方法不会在类的实例(通过类生成的对象)上被调用,相反被类本身调用。
static methodName() {...}
methodName:表示指定类中的静态方法名称。
注意:
静态方法直接在类上进行调用,不能在类的实例上调用。
ES6 实例:
/*在类的声明中* 构造器和普通方法中的this -> 指代创建后的对象* 静态方法中的this -> 指代当前的类
*/class Hero {constructor() {this.name = "lucy";this.sayMe = ()=>{console.log("this is " + this.name); // this指向的是当前对象// 在构造器中调用静态方法,// 1.类名直接调用 即 类名.静态方法()Hero.sayYou(); // this is sayYou// 2. this.constructor.静态方法名()this.constructor.sayYou(); // this is sayYou}}// 对象的方法有2种 - 可枚举 / 不可枚举// 在构造器外面定义方法 - 不可枚举(存在但不能直接打印)toString () {console.log("name toString" + this.name);// this指向的是当前对象// return "name toString " + this.name}static sayYou() {console.log("this is sayYou"); // this指向的是当前类}static sayHe() {// 在当前静态方法中,调用另一个静态方法this.sayYou();}
}let hero = new Hero();
hero.sayMe(); // this is lucy
console.log(hero.toString()); // undefined toString()方法中没有return语句,是打印不出结果的
// console.log(hero.toString()); // name toString lucy// 调用sayYou()静态方法
Hero.sayYou(); // this is sayYou
// 调用sayHe()静态方法
Hero.sayHe(); // this is sayYou
类的继承
实现类的继承
类的继承在底层中实际上是 原型的继承
语法:
class ChildClass extends ParentClass {...}
- extends:使用class创建类的时候,用extends指出该类的父类
注意:
必须在子类的构造器中写入
super()
,该super()
指向父类的构造器,子类才能获取到父类构造器中的属性和方法继承的.prototype必须是一个Object或者null.
class Parent {constructor() {this.name = 'parent';this.sayMe = function() {console.log('this is sayme')}}sayYou() {console.log("这是父类的一个普通方法"); // 这是父类的一个普通方法 undefined}static staticMethod() {console.log("这是父类的静态方法");}
}// 声明Child类时,指定Child类作为Parent类的子类
class Child extends Parent {constructor() {super(); // super -> 指向当前子类的父类的构造器,否则获取不到父类构造器中的属性和方法this.age = 18;}}let child = new Child(); //
console.log(child); // Child { name: 'parent', sayMe: [Function], age: 18 }
console.log(child.sayYou()); //这是父类的一个普通方法
console.log(Parent.staticMethod()); // 这是父类的静态方法 undefined
继承于内置对象
写一个类继承于内置对象,基于内置对象扩充自己需要的方法,不会改变内置对象原型的内容。
之前使用原型方法的时候,把自己定义的方法加在了内置方法的原型上,改变了内置方法的原型,是不友好的
实例:
/*// myDate类继承于内置对象Date
class myDate extends Date{constructor() {super();}getFormattedDate(){}}let date = new Date();
console.log(date.getFullYear()); // 2020 只能单独返回年、月、日*/// 继承于Date内置对象// myDate类继承于内置对象Date
class myDate extends Date{constructor() {super();}// 自己定义方法 返回 年-月-日getFormattedDate(){var months = ["1月","2月","3月","4月","5月","6月","7月","8月","9月","10月","11月","12月"];// 日 - 月 - 年return this.getDate() + "-" + months[this.getMonth()] + "-" + this.getFullYear();}}/*
let date = new Date();
console.log(date.getFullYear()); // 2020 只能单独返回年、月、日*/let date = new myDate();
console.log(date.getFormattedDate()); // 25-12月-2020// 2.继承于数组
let arr = [1,2,3,4,5,4,3,2,1];
class MyArray extends Array {constructor() {super();}// Set数据结构中的值是唯一的,可以利用Set给数组中的值去重quchong(array) {return new Set(array);}
}var array = new MyArray();
console.log(array.quchong(arr)); // Set { 1, 2, 3, 4, 5 }
Super关键字
super关键字可以当作函数使用、当作对象使用。这两种情况是不同的。
super关键字当作函数调用 - 代表父类的构造函数
ES6要求子类的构造函数必须执行一次super函数
注意:
super虽然代表了父类A的构造函数,但是返回的是子类B的实例
即 super内部的 this指的是B,因此 super()在这里相当于A.prototype.constructor.call(this)。
super关键字作为对象
- 在普通方法中,指向父类的原型对象
- 在静态方法中,指向父类
注意:
由于super指向父类的原型对象,super()不能调用定义是父类实例上的方法和属性。
类的实例
注意:父类中方法的返回值 必须用 return , 否则会返回undefined
// 定义一个类
class Parent {// 当前的构造器(如果省略,JS会自动生成一个构造器)- 创建对象的初始化方法constructor(name) {this.name = name;}// 当前类的(实例对象的)方法,不是当前类的原型方法toString() {console.log("this is toString method");}// 静态方法 - 由当前类直接调用的方法static staticMethod() {return "this is static method";}}// super作为对象,在普通方法中指向父类的原型对象,所以父类中的toString()方法必须是原型中的方法// 在类的原型中添加方法Parent.prototype.sayMe = function () {return "this is parent method."}// 类也同样具有原型(类似于ES5中的构造函数)
// 对象中有一个隐式原型 - 指向类的原型
/*let parent = new Parent();
parent.toString(); // this is parent method.*/// 定义一个类作为另一个类的子类
class Child extends Parent {// 因为父类的构造函数中有一个name形参,所以子类的构造函数中也要有和父类一样是形参,否则子类就不能继承父类了// 别忘了 super()里面也要写上父类中构造函数的形参constructor(name,age) {super(name); // super指向父类的构造器this.age = age;// 以下用法:super -> 指向父类的实例对象(具有隐式原型)// 原型对象不能调用实例对象,实例对象能调用原型对象super.sayMe(); // super指向父类的原型对象// super.staticMethod(); // 报错 TypeError: (intermediate value).sayMe is not a functionsuper.toString(); // super指向父类实例化的对象 this is tostring method .// super的不同用法导致super的含义不同}sayMe() {// super 指向父类的原型对象console.log("this is child method. " + super.sayMe())}static staticMethod() {// super - 指向父类console.log("this is child static method. " + super.staticMethod())}
}// 因为子类的构造函数中有形参name 和 age , 所以实例化子类的时候也要给形参传值
let child = new Child("lucy",18);
// console.log(child); // Child { name: 'lucy', age: 18 }
// 父类和子类中有相同函数名toString(),当子类对象调用该方法的时候,子类和父类的相同方法会被同时调用
child.sayMe();
/*
this is parent method.
this is child method. undefined如果 super.staticMethod() 的返回值是 undefined
原因:super作为对象,在普通方法中指向父类的原型对象,而父类中的toString()方法不是原型中的方法把父类中的toString()方法改为原型中的方法后:
返回结果是:
this is child method. this is parent method.
*/// Child.staticMethod();
/*
this is static method
this is child static method. undefined
*/
end~
ES6 class关键字 ~ 非常详细相关推荐
- ES6 | let 关键字 + const关键字 + 箭头函数 + rest参数 + 扩展运算符 ... + Symbol + 迭代器 + 生成器 + 变量的解构赋值 + 模板字符串
目录 ECMASript 相关介绍 ECMASript 6 新特性 let 关键字 const关键字 变量的解构赋值 模板字符串 简化对象写法 箭头函数 => 参数默认值 rest参数 扩展运算 ...
- es6 super关键字
super关键字 super这个关键字,既可以当作函数使用,也可以当作对象使用.在这两种情况下,它的用法完全不同. 第一种情况,super作为函数调用时,代表父类的构造函数.ES6 要求,子类的构造函 ...
- es6 super 关键字
super 关键字 我们知道,this关键字总是指向函数所在的当前对象,ES6 又新增了另一个类似的关键字super,指向当前对象的原型对象. const proto = { foo: 'hello' ...
- ES6新增关键字:let和const及let的常用场景
1.ES6: ● 我们所说的ES5和ES6其实就是在js语法的发展过程中的一个版本而已 ● ECMAScript就是js的语法,ES6新增了一些功能 2.let和const关键字 和var的区别 ● ...
- ES6——super关键字
super关键字有两种使用场景 1.当用作方法时 在ES6的构造函数中,ES6的语法规定,在继承于父类的子类的构造函数中,必须使用super(),因为在子类中是不存在上下文指向(this)的,需要使用 ...
- ES6笔记(完整详细版)
第三阶段 企业级开发 第一章 环境搭建 一.Node介绍 Node也叫NodeJS,Node.js,由Ryan-Dahl于2009年5月在GitHub发布了第一版.Node是一个JavaScript运 ...
- c语言volatile关键字(详细)总结附示例讲解
目录 一.简介 二.示例代码解析 2.1 修饰变量 2.2 修饰硬件寄存器地址 三.其他相关链接 一.简介 volatile属于C语言的关键字.开发者告诉编译器该变量是易变的,无非就是希望编译器去注意 ...
- Oracle之comment关键字的详细讲解
一.comment是oracle数据库系统的关键字,所以不能用来命名表明或字段名 二.comment关键字用于对表,字段添加注释,有利于用户对表结构以及数据库对象含义的理解. 三.用户可以通过数据字典 ...
- 关于Java中final关键字的详细介绍
Java中的final关键字非常重要,它可以应用于类.方法以及变量.这篇文章中我将带你看看什么是final关键字?将变量,方法和类声明为final代表了什么?使用final的好处是什么?最后也有一些使 ...
最新文章
- [裴礼文数学分析中的典型问题与方法习题参考解答]4.3.13
- Python开发【第十一篇】:JavaScript
- vue路由守卫判断用户是否登录,如果没登陆就跳转到登录
- Java给定一个字符串数组,判断每个字符出现次数
- android怎么设置适配器,Android之自定义实现BaseAdapter(通用适配器三)
- 如何关闭MyEclipse自动更新
- Android趣味课程:超简单猜数游戏
- 如何提取差异脑区的灰质体积与临床量表算相关?——基于体素的形态学方法(VBM)
- Oracle --- 表空间
- 【爬虫实战】7基础Python网络爬虫——淘宝商品比价定向爬虫(MOOC学习笔记)
- 面试问遇到最难的事情_太难的事情
- Druid java.sql.SQLException: connection holder is null
- IOS收起键盘的几种办法(摘抄自唐巧《iOS开发进阶》)
- Apache atlas的UI界面如何修改密码
- Android手机AP模式下本机IP
- 智汀家庭云与Home Assistant如何接入HomeKit,并连接米家设备
- u盘安装浪潮服务器_安装linux操作系统--浪潮服务器
- 深入hotstuff与pbft协议的核心
- c++关键字virtual的用法(面试)
- 【我的OpenGL学习进阶之旅】介绍一下 图元的类型:三角形、直线和点精灵