包教包会,ES6类class的基本入门
大家好,我是石小石!一个热爱技术分享的开源社区贡献者,小册《油猴脚本实战指南》作者、CSDN专栏《Vite极速入门通关教程》作者。
简介
类的由来
javaScript 语言中,生成实例对象的传统方法是通过构造函数。下面是一个例子。
function Point(x, y) {this.x = x;this.y = y;
}Point.prototype.toString = function () {return '(' + this.x + ', ' + this.y + ')';
};var p = new Point(1, 2);
这种写法跟传统的面向对象语言(比如 C++ 和 Java)差异很大,为了使对象原型的写法更加清晰、更像面向对象编程的语法,创造了新的class写法。
ES6 的class可以看作只是一个语法糖,它的绝大部分功能,ES5 都可以做到
上面的代码用 ES6 的class改写:
class Point {constructor(x, y) {this.x = x;this.y = y;}toString() {return '(' + this.x + ', ' + this.y + ')';}
}
类的方法定义位置
构造函数的prototype属性,在 ES6 的“类”上面继续存在。事实上,类的所有方法都定义在类的prototype属性上面。
class Point {constructor() {// ...}toString() {// ...}toValue() {// ...}
}// 等同于
//类的原型上增加了一个对象{},目前每一个对象都是函数。
Point.prototype = {constructor() {},toString() {},toValue() {},
};
由于类的方法都定义在prototype对象上面,所以类的新方法可以添加在prototype对象上面。Object.assign()方法可以很方便地一次向类添加多个方法。
class Point {constructor(){// ...}
}Object.assign(Point.prototype, {toString(){},toValue(){}
});
Object.assign(target,source1,source2,…)
该方法主要用于对象的合并,将源对象source的所有可枚举属性合并到目标对象target上,此方法只拷贝源对象的自身属性,不拷贝继承的属性。
constructor 方法
constructor()方法是类的默认方法(构造方法),通过new命令生成对象实例时,自动调用该方法。
class Person {constructor() {console.log("我进来啦")}}
const dema = new Person() //实例化时浏览器会直接打印‘我进来啦’
一个类必须有constructor()方法,如果没有显式定义,一个空的constructor()方法会被默认添加。
constructor()方法默认返回实例对象(即this),完全可以指定返回另外一个对象。
类的实例
生成类的实例的写法,与 ES5 完全一样,也是使用new命令。前面说过,如果忘记加上new,像函数那样调用Class(),将会报错。
class Point {// ...
}// 报错
var point = Point(2, 3);// 正确
var point = new Point(2, 3);
类的属性和方法,除非显式定义在其本身(即定义在this对象上),否则都是定义在原型上(即定义在class上)。
class Point {constructor(x, y) {this.x = x;this.y = y;}toString() {return '(' + this.x + ', ' + this.y + ')';}
}var point = new Point(2, 3);point.toString() // (2, 3)point.hasOwnProperty('x') // true
point.hasOwnProperty('y') // true
point.hasOwnProperty('toString') // false
point.__proto__.hasOwnProperty('toString') // true
上面代码中,x和y都是实例对象point自身的属性(因为定义在this对象上),所以hasOwnProperty()方法返回true,而toString()是原型对象的属性(因为定义在Point类上),所以hasOwnProperty()方法返回false。这些都与 ES5 的行为保持一致。
hasOwnProperty是用来判断一个对象是否有你给出的名称的属性或对象。有则返回true,没有返回false,不过需要注意的是,此方法无法检查该对象的原型链中是否具有该属性,该属性必须是对象本身的一个成员。
getter和setter
与 ES5 一样,在“类”的内部可以使用get和set关键字,对某个属性设置存值函数和取值函数,拦截该属性的存取行为。
class Person {constructor() {console.log("我进来啦")}get prop() {return "哎,我是写死的返回值"}set prop(value) {console.log("谁要修改我!")}
}
const dema = new Person()
console.log(dema) //Person {}
dema.prop = '修改属性' //谁要修改我!
console.log(dema.prop) //哎,我是写死的返回值
属性表达式
类的属性名,可以采用表达式。
let methodName = 'getArea';class Square {constructor(length) {// ...}[methodName]() {// ...}
}
上面代码中,Square类的方法名getArea,是从表达式得到的。
静态方法
类相当于实例的原型,所有在类中定义的方法,都会被实例继承。如果在一个方法前,加上static关键字,就表示该方法不会被实例继承,而是直接通过类来调用,这就称为“静态方法”。
class Foo {static classMethod() {return 'hello';}
}Foo.classMethod() // 'hello'var foo = new Foo();
foo.classMethod()
// TypeError: foo.classMethod is not a function
父类的静态方法,可以被子类继承。
class Foo {static classMethod() {return 'hello';}
}class Bar extends Foo {
}Bar.classMethod() // 'hello'
实例属性的新写法
实例属性除了定义在constructor()方法里面的this上面,也可以定义在类的最顶层。
class Person {age = 2constructor() {this.name = "222"}
}
const dema = new Person()
console.log(dema) //{ "age": 2, "name": "222"}
定义在外层,需要用等号。。。。。
关于我
最近在学习油猴脚本开发,写了很多有趣的脚本:
- 接口拦截工具:修改CSDN博客数据接口返回值
- Vue路由一键切换:开发效率起飞
- 任意元素双击实现画中画:摸鱼超级助手
- 掘金后台自动签到助手
- 解除文本复制、网页复制、一键下载为MD
- 主题切换助手
如果你对油猴脚本开发也感兴趣,可以参考我的油猴脚本开发教程