ES6中类的概念
Class
在JavaScript中,是通过构造函数来生成实例对象。
function A(a){
this.a=a
}
A.prototype.sayA=function(){
console.log(this.a)
}
var a=new A('a')
a.sayA()
在ES6中引入了class(类)的概念,通过class
关键字可以定义类。这种写法使得对象原型的写法更加清晰、更像面对对象编程的语法了。
class A{
constructor(a){
this.a=a
}
sayA(){
console.log(this.a)
}
}
var a=new A('a')
a.sayA()
在定义类的方法时,不需要加上function关键字,使用的时候也是直接对类进行new
命令,跟构造函数是一样的。
构造函数的prototype
属性,在 ES6 的类中继续存在,类的所有方法都定义在类的prototype
属性上面。
class A{
constructor(){
}
sayA(){}
sayB(){}
}
相当于
A.prototype={
sayA(){},
sayB(){}
}
因此在类的实例中调用方法,其实调用的是原型上的方法。而且,类的内部定义的所有方法都是不可枚举的,而es5中的是可枚举的。
class A{
constructor(){
}
sayA(){}
sayB(){}
}
Object.keys(A.prototype) //[]
function A(){}
A.prototype.sayA=function(){}
A.prototype.sayB=function(){}
Object.keys(A.prototype) //['sayA','sayB]
constructor
constructor
方法是类的默认方法,通过new
命令生成对象实例时,自动调用该方法。一个类必须有constructor
方法,如果没有显式定义,一个空的constructor
方法会被默认添加。
class A(){}
//等同
class A(){
constructor(){}
}
类的实例
实例的属性除非显式定义在其本身(即定义在this
对象上),否则都是定义在原型上(即定义在class
上)。
class A{
constructor(a){
this.a=a
}
sayA(){
console.log(this.a)
}
}
var a=new A('a')
console.log(a.hasOwnProperty('a')) //true
console.log(a.hasOwnProperty('sayA')) //false
console.log(a.__proto__.hasOwnProperty('sayA')) //true
类的所有实例共享一个原型对象。
var a=new A('a')
var b=new A('b')
console.log(a.__proto__===b.__proto__) //true
可以通过__proto__
属性对类添加方法。
getter、setter
在类的内部可以使用get
和set
关键字,对某个属性设置存取函数,拦截属性的存取行为。
class A{
constructor(a){
this.a=a
}
get value(){
return this.a
}
set value(val){
this.a=val
}
}
var a=new A()
a.value=3
console.log(a.value) //3
属性表达式
类的属性名,可以通过表达式设置
let methodsName1='sayA'
class A{
constructor(){}
[methodsName1](){}
}
class表达式
与函数一样,类也可以用表达式的形式进行定义。
const Aclass= class A{
sayA(){
return A.value
}
}
这个类的名字是A
,A
只在 Class 的内部可用,指代当前类。在 Class 外部,这个类只能用AClass
引用。如果类的内部没有用到的话,可以直接写成
const Aclass=class{}
采用class表达式的写法,可以写出立即执行的class
const Aclass=new class A{
constructor(value){
this.value=value
}
sayA(){
console.log(this.value)
}
}('a')
Aclass.sayA() //a
静态方法
在方法前面加上static
关键字,就表示该方法不会被实例继承,而是直接通过类来调用,这就称为“静态方法”。
class A{
static aMethod(){
console.log('hi')
}
}
A.aMethod() //hi
var a=new A()
a.aMethod() //TypeError: a.aMethod is not a function
如果静态方法包含this
关键字,这个this
指的是类,而不是实例。静态方法可以与非静态方法重名。
class A{
static aMethod1(){
this.aMethod2() //this指向了类A,而不是实例
}
static aMethod2(){
console.log('hi2')
}
aMethod1(){ //与静态方法重名了
console.log('sup?')
}
}
A.aMethod1() //hi2
var a=new A()
a.aMethod1() //sup?
父类的静态方法,可以被子类继承。
class A{
static aMethod(){
console.log('hi')
}
}
class AA extends A{
}
AA.aMethod() //hi
静态方法可以从super
对象上调用的。
class A{
static aMethod(){
return `hi`
}
}
class AA extends A{
static aMethod(){
console.log(`${super.aMethod()} , sup?`)
}
}
AA.aMethod() // hi , sup?
私有属性
私有属性只能在类的内部调用,在类的外部调用就会报错。引入一个新的前缀#
表示私有属性。
class A{
#val='value',
sayValue(){
console.log(this.#val)
}
}
var a=new A()
console.log(a.#val) //Private field '#val' must be declared in an enclosing class
console.log(a.sayValue()) //value
注意点
1、不存在变量提升
new A(); // ReferenceError
class A {}
2、es6默认就是严格模式
3、generator方法
在某个方法之前加上星号(*
),就表示该方法是一个 Generator 函数。
class A {
constructor(...args) {
this.val = args;
}
* [Symbol.iterator]() {
for (let arg of this.val) {
yield arg;
}
}
}
for (let x of new A('a', 'b')) {
console.log(x);
}
// a
// b
Symbol.iterator
方法返回类的默认遍历器,for...of
循环会自动调用这个遍历器。
4、this指向
类的方法内部如果含有this
,它默认指向类的实例,但是类的内部采用的是严格模式,很容易报错。
class A{
sayA(a='a'){
this.log(a)
}
log(val){
console.log(val)
}
}
const a=new A()
const {sayA}=a;
sayA() //Uncaught TypeError: Cannot read property 'log' of undefined
将方法提取出来单独使用,this
会指向该方法运行时所在的环境(由于 class 内部是严格模式,所以 this 实际指向的是undefined
),从而导致找不到方法而报错。
一个比较简单的解决方法是,在构造方法中绑定this
,就不会找不到方法了。
class A{
constructor(){
this.sayA=this.sayA.bind(this) //对方法进行绑定
//this.sayA=()=>this //通过箭头函数也可以实现。
}
sayA(a='a'){
this.log(a)
}
log(val){
console.log(val)
}
}
const a=new A()
const {sayA}=a;
sayA()
推荐阅读
-
读取数据库中数据到数组的类
-
Python3中类、模块、错误与异常、文件的简易教程
-
AngularJS中$injector、$rootScope和$scope的概念和关联关系深入分析
-
Java中Date()类 日期转字符串、字符串转日期的问题
-
PHP中抽象类和接口的区别
-
windows 中 \r\n 区别于 类unix中的\n 疑问理解(crlf回车换行)
-
【转载】 C#中ArrayList集合类的使用
-
Java日期时间API系列8-----Jdk8中java.time包中的新的日期时间API类的LocalDate源码分析
-
Java中数组操作 java.util.Arrays 类常用方法的使用
-
详解ES6中的 Set Map 数据结构学习总结