ACwing学习——JavaScript(6)

98 阅读4分钟

8. 函数

函数是用对象来实现的(早期js中没有class概念,会用一个函数当做类;js有了ES6以后,ES6中定义好了class,一般就用class了。)

//  定义方式1  其中function是修饰符   add的类型是function    js中函数名可以任意赋值
function add(a, b) {
    return a + b;
}

let add = function (a, b) {
    return a + b;
}

//  定义方式2(简写方法,可以不写function)
let add = (a, b) => {
    return a + b;
}

let main = function() {
	console.log(add(3, 4)  // 这里的3, 4是参数,定义add函数的时候写了a, b两个参数,此处书写两个或两个以上参数都是可以正常执行的(多传的参数没有意义只执行有意义的部分),如果只定义一个参数或者一个参数都不定义则会得到undefined结果。
}
返回值

如果未定义返回值,则返回undefined。

9. 类

与C++中的Class类似。但是不存在私有成员,全部都是公开的。

类可以理解为前端的每一个组件,每一个组件还可以进行细分,每个细分的组件都是又一个新的class。

this指向类的实例
class Point {          // 定义一个类名为point
    constructor(x, y) {  // 构造函数名称固定(constructor)  该构造函数有两个参数(x, y)
        this.x = x;  // 成员变量   定义类的成员变量(使用this.   class中的this表示当前对象中的当前实例(实例就是第20行的参数,一个类可以生成多个实例),类似Python中的self)名称为x
        this.y = y;

        this.init();
    }

    init() {     // 定义一个成员函数 (此处不需要书写function)
        this.sum = this.x + this.y;  // 成员变量可以在任意的成员函数中定义
    }

    toString() {  // 成员函数
        return '(' + this.x + ', ' + this.y + ')';
// 14行的格式化写法如下
// return `(${this.x}, ${this.y})`;
    }
}

let p = new Point(3, 4);  // 定义一个对象
console.log(p.toString());

类名一般使用驼峰命名法(每个单词首字母大写)

继承
class ColorPoint extends Point {   // 表示ColorPoint继承自Point
    constructor(x, y, color) {
        super(x, y); // 这里的super表示父类的构造函数  这里的super(指代父类的构造函数)就是Point中的constructor(改行必须书写且应该书写至第一行)
        this.color = color;  // 这一行的this.属性需要在super之后调用,否则会报错
    }

    toString() {
        return `this.color + ' ' + super.toString()`; // 调用父类的toString()  该行中的super不同与第3行的super,第3行的super只能用于构造函数中。本行的super指的是子类这个对象(除了在第三行的位置是指代父类的构造函数以外,均为该含义),此处super类似于this,表示指向当前实例的父类的实例(this指向当前对象的实例) 
    }
}

注意:

  1. super这个关键字,既可以当作函数使用,也可以当作对象使用。

作为函数调用时,代表父类的构造函数,且只能用在子类的构造函数之中。

super作为对象时,指向父类的原型对象。

  1. 在子类的构造函数中,只有调用super之后,才可以使用this关键字。(与js的底层实现有关)
  1. 成员重名时,子类的成员会覆盖父类的成员。类似于C++中的多态(同一个函数表现出来多个状态的功能)
静态方法

在成员函数前添加static关键字即可。静态方法不会被类的实例继承,只能通过类来调用。例如:

class Point {
    constructor(x, y) {
        this.x = x;
        this.y = y;
    }

    toString() {
        return '(' + this.x + ', ' + this.y + ')';
    }

    static print_class_name() {
        console.log("Point");  // 打印当前类名
    }
}

let p = new Point(1, 2);  // 初始化一个实例
Point.print_class_name();   // 正确访问方法,通过类名(此处为Point)识别
p.print_class_name();  // 会报错 因为没有把 print_class_name()继承过来
静态变量

静态变量:变量是与类绑定的并不是与实例绑定的(普通的变量是和每一个实例绑定的)

可以尽量少的避免重名变量的发生

在ES6中,只能通过class.propname定义和访问。例如:

class Point {
    constructor(x, y) {
        this.x = x;
        this.y = y;

        Point.cnt++;  // 每调用一次函数,就让静态变量进行++运算
    }

    toString() {
        return '(' + this.x + ', ' + this.y + ')';
    }
}

Point.cnt = 0;   // 定义了一个Point的静态变量

let p = new Point(1, 2);
let q = new Point(3, 4);

console.log(Point.cnt);

静态函数可以理解为所有实例公共的函数;

静态变量可以理解为所有实例共有的变量;

静态变量可以理解为全局变量。

静态函数用得少,静态变量会用得到。

静态成员函数是可以被继承的