一 类的初体验
// 以前没用类的时候。通过写构造函数,来创建对象
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);
console.log(p.x); // 1
//定义Point类
class Point {
constructor(x, y) {
this.x = x;
this.y = y;
}
toString() {
return '(' + this.x + ',' + this.y + ')';
}
}
var p = new Point(1, 2);
console.log(p.y); // 调用属性
console.log(p.toString()); // 调用方法
二 类的声明
// 类的声明
class Point {
// 类的构造方法
// 注意: 一个类只能有一个构造函数
constructor(x, y) {
this.x = x;
this.y = y;
}
// 类中定义的方法最终是挂在原型上的,实例化对象调用时
toString() {
return '(' + this.x + ',' + this.y + ')';
}
}
var p = new Point(1, 2);
console.log(p.y); // 调用属性
console.log(p.toString()); // 调用方法
当我们通过new关键字操作类的时候,会调用这个constructor函数,并且执行如下操作:
1.在内存中创建一个新的对象(空对象);
2.这个对象内部的[[prototype]]属性会被赋值为该类的prototype属性;
3.构造函数内部的this,会指向创建出来的新对象;
4.执行构造函数的内部代码(函数体代码);
5.如果构造函数没有返回非空对象,则返回创建出来的新对象;
三 类的方法
// 类中常见有三种方法:
// 1.实例方法
// 2.访问器方法
// 3.静态方法
class Person {
constructor(name, age) {
this.name = name
this.age = age
this.sex= "男"
}
//1 普通的实例方法,挂载在原型上。
eating() {
console.log(this.name + " eating~")
}
running() {
console.log(this.name + " running~")
}
//2 类的访问器方法。类访问前,或者赋值前的拦截
get getSex() {
console.log("拦截访问操作")
return this.sex
}
set setSex(newSex) {
console.log("拦截设置操作")
this.sex= newSex
}
//3 类的静态方法(类方法),一般来说,不需要访问类属性的方法都可以写成静态的。这类方法一般都是 Helper 方法,即对输入进行处理再得到一个输出,与对象的成员无关。这类方法也可以直接写为公共函数。
static systemOut() {
console.log("不需要访问成员变量")
}
}
var p = new Person("cxy", 18)
p.eating()//cxy eating~
p.running()//cxy running~
console.log(p.sex)//拦截访问操作, 男
p.sex= "女"
console.log(p.address)//拦截设置操作, 拦截访问操作, 女
四 ES6中的继承-extends
在子类的构造函数中使用this或者返回默认对象之前,
必须
先通过super调用父类的构造函数
class Person {
constructor(name, age) {
this.name = name
this.age = age
this.sex= "男"
}
//1 普通的实例方法,挂载在原型上。
eating() {
console.log(this.name + " eating~")
}
running() {
console.log(this.name + " running~")
}
//2 类的访问器方法。类访问前,或者赋值前的拦截
get getSex() {
console.log("拦截访问操作")
return this.sex
}
set setSex(newSex) {
console.log("拦截设置操作")
this.sex= newSex
}
//3 类的静态方法(类方法),一般来说,不需要访问类属性的方法都可以写成静态的。这类方法一般都是 Helper 方法,即对输入进行处理再得到一个输出,与对象的成员无关。这类方法也可以直接写为公共函数。
static systemOut() {
console.log("不需要访问成员变量")
}
}
// Flx称之为子类(派生类)
class Flx extends Person {
// JS引擎在解析子类的时候就有要求, 如果我们有实现继承
// 那么子类的构造方法中, 在this之前一定要用super
constructor(name, age, sno) {
super(name, age)//super的使用
this.email = email
}
singing() {
console.log(this.name + " singing~")
}
// 类对父类的方法的重写:命名相同即可重写
running() {
console.log("Flx " + this.name + " running----重写父类方法")
}
// 重写并拓展方法
eating() {
// 复用父类中的处理逻辑
//调用父类的方法,避免重复写父类的代码
super.eating()
//然后再写要新加入的代码逻辑
console.log("这是新增加的逻辑")
console.log("这是新增加的业务代码")
}
// 重写静态方法
static systemOut() {
// 复用父类中的处理逻辑
super.systemOut()
//然后再写要新加入的代码逻辑
console.log("这是新增加的业务代码")
}
}
super的使用位置有三个:子类的构造函数、实例方法、静态方法;
- 调用父类的构造函数
super([arguments]) - 调用父类上的方法
super.functionOnParent([arguments]) - 调用父类上的静态方法
super.functionOnParentStatic([arguments])
五 类的其他用法总结
// 属性表达式
let methodName = 'setSex';
class Person {
constructor(length) {
// ...
}
[methodName]() {
// ...
}
}
// 上面代码中,Person 类的方法名setSex,是从表达式得到的。
// Class 表达式,可以写出立即执行的 Class。
let person = new Person {
constructor(name) {
this.name = name;
}
sayName() {
console.log(this.name);
}
}('张三');
person.sayName(); // "张三"
// person是一个立即执行的类的实例
// 静态属性,只能通过静态方法才能访问。
class Person{
constructor(name="xf",age){
this.name = name;
this.age = age;
}
static say(){
console.log("这是静态方法");
}
}
// 静态属性
Person.type = "这是静态属性";
//访问静态属性
console.log(Person.type);
六 类的练习之封装一个小组件–tips
/**
* 提示与加载工具类
*/
export default class Tips {
constructor() {
this.isLoading = false;
}
/**
* 弹出提示框
*/
static success(title, duration = 1000) {
setTimeout(() => {
uni.showToast({
title: title,
icon: "success",
mask: true,
duration: duration
});
}, 300);
if (duration > 0) {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve();
}, duration);
});
}
}
/**
* 弹出确认窗口
*/
static confirm(text, showCancel, payload = {}, title = "提示") {
return new Promise((resolve, reject) => {
uni.showModal({
title: title,
content: text,
showCancel: showCancel,
success: res => {
if (res.confirm) {
resolve(payload);
} else if (res.cancel) {
reject(payload);
}
},
fail: res => {
reject(payload);
}
});
});
}
static toast(title, onHide, icon = "none") {
setTimeout(() => {
uni.showToast({
title: title,
icon: icon,
mask: true,
duration: 1000
});
}, 300);
// 隐藏结束回调
if (onHide) {
setTimeout(() => {
onHide();
}, 500);
}
}
/**
* 警告框
*/
static alert(title) {
uni.showToast({
title: title,
image: "../../static/common/alert.png",
mask: true,
duration: 1500
});
}
/**
* 错误框
*/
static error(title, onHide) {
uni.showToast({
title: title,
icon: 'none',
mask: true,
duration: 2000,
});
// 隐藏结束回调
if (onHide) {
setTimeout(() => {
onHide();
}, 500);
}
}
/**
* 弹出加载提示
*/
static loading(title = "加载中") {
if (Tips.isLoading) {
return;
}
Tips.isLoading = true;
uni.showLoading({
title: title,
mask: true
});
}
/**
* 加载完毕
*/
static loaded() {
if (Tips.isLoading) {
Tips.isLoading = false;
uni.hideLoading();
}
}
}
/**
* 静态变量,是否加载中
*/
Tips.isLoading = false;