class类
-
语法糖
-
构造函数的另一种写法,相比于ES5更加简洁 更符合面向对象的编程的写法
-
不存在提升问题
-
类相当于实例的原型,所有在类中定义的方法,都会被实例继承
ES5构造函数
function IsNum (x, y) {
this.x = x;
this.y = y;
}
IsNum.prototype = {
setNum: function(x, y) {
return x - y
}
}
let a1 = new IsNum();
let a2 = a1.setNum(10, 5);
console.log('ES5: ', a2)
class的基本语法
class NumFun {
constructor (x, y) {
this.x = x; // this关键字则代表实例对象
this.y = y;
}
setNum (x, y) {
return Number(x) + Number(y)
}
}
let a1 = new NumFun();
let a2 = a1.setNum(5,10)
console.log(all)
constructor
- constructor 就是
构造方法
默认有且必须有一个
, 没有的话会自动生成一个空的- constructor方法是类的默认方法,通过new命令生成对象实例时,自动调用该方法
- constructor方法
默认返回实例对象(即this)
- constructor 就是
- 不需要function关键字,不需要 ,相隔 加了会报错
- 类的所有方法都定义在类的prototype属性上面
静态方法 & 静态属性
class NumFun {
constructor (x, y) {
this.x = x;
this.y = y;
}
static foo () {
this.baz()
return '静态方法'
}
static baz() {
console.log('hello');
}
static name = '静态属性'
setNum (x, y) {
return Number(x) + Number(y)
}
}
class children extends NumFun {
constructor () {
super()
}
}
let f = new NumFun();
console.log(children.foo())
- 类中的方法加上static关键字,只能被类调用,实例对象调用会报错,静态属性同理
- 静态方法包含this关键字,这个this指的是类,而不是实例
- 父类的静态方法,可以被子类继承
补充
取值函数(getter)和存值函数(setter)
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'
name属性
- name属性总是返回紧跟在class关键字后面的类名
class Point {}
Point.name // "Point"
class继承
class NumFun {}
class children extends NumFun {
constructor () {
super()
}
}
-
extends
- Class 可以通过extends关键字实现继承,这比ES5通过修改原型链实现继承,要清晰和方便很多
- 通过extends可以继承父类全部属性和方法,包括静态方法,属性
-
super
- 必须在子类的constructor()进行调用
- super代表调用父类的构造函数,用来新建父类的this对象。 只有super方法才能调用父类实例
- 在子类中只有在constructor调用super之后,才可以使用this关键字
-
this
- 在子类中使用this,必须先调用super(),否则保错
- 子类的this必须先通过父类的构造函数来完成塑造
子类必须在constructor方法中调用super方法,否则新建实例时会报错。这是因为子类自己的this对象,必须先通过父类的构造函数完成塑造,得到与父类同样的实例属性和方法,然后再对其进行加工,加上子类自己的实例属性和方法。如果不调用super方法,子类就得不到this对象。
class与ES5构造函数有什么区别?
-
写法不同
-
不存在提升
// es5
var bar = new Bar(); // 可行
function Bar() {
this.bar = 42;
}
//es6
const foo = new Foo(); // Uncaught ReferenceError
class Foo {
constructor() {
this.foo = 42;
}
}
默认是严格模式
// es5
function Bar() {
// 引用一个未声明的变量
baz = 42; // it's ok
}
var bar = new Bar();
// es6
class Foo {
constructor(){
// 引入一个未声明的变量
fol = 42;// Uncaught ReferenceError: fol is not defined
}
}
let foo = new Foo();
class必须使用new调用
// ES5
function Bar () {
console.log('ES5构造函数')
}
var aaa = Bar()
console.log('aaa: ', aaa)
// ES6
class A {
constructor () {
console.log('ES6构造函数')
}
}
let ccc = A()
console.log('ccc: ', ccc)
- Class 作为构造函数的语法糖,
同时有prototype属性和__proto__属性,因此同时存在两条继承链
- 子类的__proto__属性,表示构造函数的继承,总是指向父类
- 子类prototype属性的__proto__属性,表示方法的继承,总是指向父类的prototype属性
class A {} class B extends A { } B.__proto__ === A // true B.prototype.__proto__ === A.prototype // true
async函数
Proxy(拦截器,代理器)
含义:
在目标对象之前架设一层拦截,外界访问该目标对象都要先访问这层拦截,可以对外界的操作做过滤和修改
let obj = {}; // 所要拦截的目标对象
let isGet = { // 拦截行为
get: function () {
let text = '拦截操作'
return text
}
}
let pro = new Proxy(obj, isGet)
pro.foo = '123';
console.log(pro.foo) // 拦截操作
- Proxy是一个构造函数,用来生成Proxy实例
-
接受两个参数
- 所要拦截的目标对象
- 拦截行为
- 如果没有设置拦截行为,就等于正常访问拦截对象
- 可设置多个拦截操作,共13种
-
拦截操作
- get
- set
- has
- apply:拦截函数的调用、call和apply操作
let fun = function () {}
let handler = {
apply: function () {
console.log('修改函数调用时的操作');
}
};
let proxy = new Proxy(fun, handler)
console.log(proxy());
暂定