浅谈ES6中的Class
转载地址:https://www.cnblogs.com/sghy/p/8005857.html
一、定义类(ES6的类,完全可以看做是构造函数的另一种写法)
class Greet {
constructor(x, y) {
this.x = x;
this.y = y;
}
sayHello() {
console.log(this.x + " " + this.y)
}
}
let a = new Greet("hello", "everybody");
a.sayHello() //hello everybody
《注》:
- 以上定义的类如果用ES5的构造函数实现如下:
function Greet(x, y) {
this.x = x;
this.y = y;
this.sayHello = function () {
console.log(this.x + " " + this.y)
}
} let a = new Greet("hello", "everybody");
a.sayHello() //hello everybody
- 类的数据类型就是函数,类本身就指向构造函数
typeof Greet; //function
Greet === Greet.prototype.constructor //true
- 类的所有方法都定义在类的
prototype
属性上面
class Greet {
constructor() {...}
sayHello() {...}
sayHi(){...}
}
等同于
Greet
Greet.prototype = {
constructor() {},
sayHello() {},
sayHi() {},
};
constructor方法:
- 是类的默认方法,通过
new
命令生成对象实例时,自动调用该方法。一个类必须有constructor
方法,如果没有显式定义,一个空的constructor
方法会被默认添加。
class Greet {
}
// 等同于
class Greet {
constructor() {}
}
constructor
方法默认返回实例对象(即this
),完全可以指定返回另外一个对象。
class Foo {
constructor() {
return Object.create(null);
}
} new Foo() instanceof Foo
// false
类的实例对象:
- 实例的属性除非显式定义在其本身(即定义在
this
对象上),否则都是定义在原型上(即定义在class
上)。
class Greet {
constructor(x, y) {
this.x = x;
this.y = y;
}
sayHello() {
console.log(this.x + " " + this.y)
}
}
let a = new Greet("hello", "everybody");
// x,y都是实例对象a自身的属性,因为定义在this上
a.hasOwnProperty('x') // true
a.hasOwnProperty('y') // true
//sayHello是原型对象的属性,因为定义在Greet上
a.hasOwnProperty('sayHello') // false
a.__proto__.hasOwnProperty('sayHello') // true
- 类的所有实例共享一个原型对象
let a = new Greet("hello", "everybody");
let b = new Greet("hello", "everybody"); a.__proto__ === b.__proto__ //true
Class表达式:
const MyClass = class Me {
getClassName() {
return Me.name;
}
}; //类的名字是MyClass而不是Me,Me只在 Class 的内部代码可用,指代当前类。
//如果类的内部没用到的话,可以省略Me
const MyClass = class {
...
};
不存在变量提升:必须先定义类,再使用
私有方法:
- 利用
Symbol
值的唯一性
const bar = Symbol('bar');
const snaf = Symbol('snaf'); export default class myClass{ // 公有方法
foo(baz) {
this[bar](baz);
} // 私有方法
[bar](baz) {
return this[snaf] = baz;
} // ...
};
- 利用#标识:
class Greet {
constructor(x, y) {
this.x = x;
this.y = y;
}
#sayHello() {
console.log(this.x + " " + this.y)
}
}
Class 的取值函数(getter)和存值函数(setter):在“类”的内部可以使用get
和set
关键字,对某个属性设置存值函数和取值函数,拦截该属性的存取行为。
class MyClass {
constructor() {
// ...
}
get prop() {
return 'getter';
}
set prop(value) {
console.log('setter: '+value);
}
} let inst = new MyClass(); inst.prop = 123;
// setter: 123 inst.prop
// 'getter'
Class 的静态方法:加上static
关键字,表示该方法不会被实例继承,而是直接通过类来调用
class Foo {
static classMethod() {
return 'hello';
}
} Foo.classMethod() // 'hello' var foo = new Foo();
foo.classMethod()
// TypeError: foo.classMethod is not a function
- 如果静态方法包含
this
关键字,这个this
指的是类,而不是实例 - 父类的静态方法,可以被子类继承
- 静态方法也是可以从
super
对象上调用的
Class 的静态属性和实例属性
- 静态属性指的是 Class 本身的属性,即
Class.propName
,而不是定义在实例对象(this
)上的属性,定义方法如下:
class MyClass {
static myStaticProp = 42; constructor() {
console.log(MyClass.myStaticProp); // 42
}
}
- 类的实例属性可以用等式,写入类的定义之中
class MyClass {
myProp = 42; constructor() {
console.log(this.myProp); // 42
}
}
new.target 属性:如果构造函数不是通过new
命令调用的,new.target
会返回undefined
用来确定构造函数是怎么调用的。
function Person(name) {
if (new.target !== undefined) {
this.name = name;
} else {
throw new Error('必须使用 new 命令生成实例');
}
}
二、Class继承:通过extends
关键字实现继承
class Point {
} class ColorPoint extends Point {
}
supper:
- 子类必须在
constructor
方法中调用super
方法(子类没有自己的this
对象,而是继承父类的this
对象,然后对其进行加工)
class Point { /* ... */ } class ColorPoint extends Point {
constructor() {
}
} let cp = new ColorPoint(); // ReferenceError
- 如果子类没有定义
constructor
方法,这个方法会被默认添加
class ColorPoint extends Point {
} // 等同于
class ColorPoint extends Point {
constructor(...args) {
super(...args);
}
}
- 在子类的构造函数中,只有调用
super
之后,才可以使用this
关键字(子类实例的构建,是基于对父类实例加工,只有super
方法才能返回父类实例)
class Point {
constructor(x, y) {
this.x = x;
this.y = y;
}
} class ColorPoint extends Point {
constructor(x, y, color) {
this.color = color; // ReferenceError
super(x, y);
this.color = color; // 正确
}
}
super
作为函数调用时,代表父类的构造函数。ES6 要求,子类的构造函数必须执行一次super
函数。且只能用在子类的构造函数之中,用在其他地方就会报错
class A {} class B extends A {
constructor() {
super();
}
} //super
虽然代表了父类A
的构造函数,但是返回的是子类B
的实例
super
作为对象时,在普通方法中,指向父类的原型对象;在静态方法中,指向父类。
a)普通方法中:
class A {
p() {
return 2;
}
} class B extends A {
constructor() {
super();
console.log(super.p()); // 2
}
} //指向父类的原型对象 let b = new B();
b) 静态方法中:
class Parent {
static myMethod(msg) {
console.log('static', msg);
} myMethod(msg) {
console.log('instance', msg);
}
} class Child extends Parent {
static myMethod(msg) {
super.myMethod(msg);
} myMethod(msg) {
super.myMethod(msg);
}
} Child.myMethod(1); // static 1 var child = new Child();
child.myMethod(2); // instance 2
浅谈ES6中的Class的更多相关文章
- 浅谈ES6中super关键字
作用: super 关键字用于访问父对象上的函数. 语法: super([arguments]); // 访问父对象上的构造函数 super.functionOnParent([arguments]) ...
- 浅谈ES6中的Async函数
转载地址:https://www.cnblogs.com/sghy/p/7987640.html 定义:Async函数是一个异步操作函数,本质上,Async函数是Generator函数的语法糖.asy ...
- 浅谈ES6中的Proxy
Proxy是一个很有趣的对象,它能够修改某些操作的默认行为,等同于在语言层面做出修改,属于一种‘元编程’,即对编程语言进行编程. Proxy其实很好理解,就是在目标对象之前架设一层拦截,外界的访问都得 ...
- 浅谈ES6原生Promise
浅谈ES6原生Promise 转载 作者:samchowgo 链接:https://segmentfault.com/a/1190000006708151 ES6标准出炉之前,一个幽灵,回调的幽灵,游 ...
- 浅谈JS中 var let const 变量声明
浅谈JS中 var let const 变量声明 用var来声明变量会出现的问题: 1. 允许重复的变量声明:导致数据被覆盖 2. 变量提升:怪异的数据访问.闭包问题 3. 全局变量挂载到全局对象:全 ...
- 浅谈Java中的equals和==(转)
浅谈Java中的equals和== 在初学Java时,可能会经常碰到下面的代码: 1 String str1 = new String("hello"); 2 String str ...
- 浅谈Linux中的信号处理机制(二)
首先谢谢 @小尧弟 这位朋友对我昨天夜里写的一篇<浅谈Linux中的信号处理机制(一)>的指正,之前的题目我用的“浅析”一词,给人一种要剖析内核的感觉.本人自知功力不够,尚且不能对着Lin ...
- 浅谈Java中的对象和引用
浅谈Java中的对象和对象引用 在Java中,有一组名词经常一起出现,它们就是“对象和对象引用”,很多朋友在初学Java的时候可能经常会混淆这2个概念,觉得它们是一回事,事实上则不然.今天我们就来一起 ...
- 浅谈Java中的equals和==
浅谈Java中的equals和== 在初学Java时,可能会经常碰到下面的代码: String str1 = new String("hello"); String str2 = ...
随机推荐
- Spring Cloud Gateway 不小心换了个 Web 容器就不能用了,我 TM 人傻了
个人创作公约:本人声明创作的所有文章皆为自己原创,如果有参考任何文章的地方,会标注出来,如果有疏漏,欢迎大家批判.如果大家发现网上有抄袭本文章的,欢迎举报,并且积极向这个 github 仓库 提交 i ...
- Lua中如何实现类似gdb的断点调试--05优化断点信息数据结构
在上一篇04优化钩子事件处理中,我们在钩子函数中引入了call和return事件的处理,对性能进行了优化. 细心的同学可能已经发现了,我们的hook函数中call事件和line都需要对整个断点表进行遍 ...
- 微信小程序+laravel 7+ Redis +短信宝 实现手机号验证码登录
以下代码可以进行优化和封装:这里我实现功能为主,就不封装啦.小伙伴可以自己试着封装一下. 1:书写登录表单 <view class="container"> <v ...
- RISC / CISC
RISC(精简指令集计算机)和CISC(复杂指令集计算机)是当前CPU的两种架构.它们的区别在于不同的CPU设计理念和方法. CPU架构是厂商给属于同一系列的CPU产品定的一个规范,主要目的是为了区分 ...
- Activemq持久化之kahadb特性
介绍数据的持久化是很多系统都会涉及到的一个问题,尤其是redis,activemq这些数据主要是存储在内存中的.既然存在内存中,就会面临宕机时数据丢失的风险.这一问题的解决方案就是通过某种方式将数据写 ...
- MySQL—存储引擎
主要包括两大引擎 MyISAM,InnoDB 1.MyISAM与InnoDB的区别 2.常规的使用操作 1.MyISAM 节约空间,速度快 2.InnoDB 安全性高,事务的处理,多表操作.Inno ...
- windows配置jdk环境变量、mysql环境变量、tomcat环境变量、maven环境变量、git环境变量、node环境变量
一.windows配置各种环境变量后 path 路径下的目录: 二.windows 配置各种环境变量的目的: 为windows系统添加上各种环境对应的命令 举例,为什么要添加jdk的bin目录,是因为 ...
- position 的值absolute、fixed、relative和static的定位原点是什么
position 的值absolute.fixed.relative和static的定位原点是什么 absolute 成绝对定位的元素,相对于值不为static的第一个父元素进行定位,也可以理解为离自 ...
- synchronized和 synchronized 了解偏向锁、轻量级锁、重量级锁的概念以及升级机制、以及和ReentrantLock的区别。
并发 synchronized 了解偏向锁.轻量级锁.重量级锁的概念以及升级机制.以及和ReentrantLock的区别. https://www.cnblogs.com/deltadeb ...
- super.getClass()方法调用?
下面程序的输出结果是多少? import java.util.Date; public class Test extends Date{ public static void main(String[ ...