JS中的类

158 阅读3分钟

「这是我参与2022首次更文挑战的第9天,活动详情查看:2022首次更文挑战

ES5中的类

先在这介绍一下ES5中的类。在ES6中,class (类)作为对象的模板被引入,可以通过 class 关键字定义类。 class 的本质是 function。 它可以看作一个语法糖,让对象原型的写法更加清晰、更像面向对象编程的语法。这里简单说一下用法就不多讲述,参考阅读JavaScript 类(class)

function PersonOne() {
    this.name = "张三"
    this.age = 20
}
let per1 = new PersonOne();
console.log(per1.name);

这里用的就是函数来表达类,结果如下
image.png

class ClassName {   
    constructor() { ... } 
}

构造函数和原型链里面增加方法

prototype 属性允许您向对象添加属性和方法 注意: Prototype 是全局属性,适用于所有的 Javascript 对象。这里我们用 className.prototype.属性名来修改类。
原型链上面的属性会被多个实例共享,构造函数不会。

function PersonTwo() {
    this.name = "张三"
    this.age = 20
    this.run = function () {
        console.log('run');
    }
}
PersonTwo.prototype.sex = "男"
PersonTwo.prototype.work = function () {
    console.log(this.name + ":work");
}
let per2 = new PersonTwo();
per2.work();
console.log(per2.sex);

image.png

类里面的静态方法

ES5中类的静态方法和静态属性可以像如下代码一样写,这里静态的意思是这些不会被实例继承,不需要实例化类,就可以直接拿来用。ES6中关于类的讲述很多,这里就不详细展开,仅仅对静态方法与静态属性进行讨论。我们通常在属性前面加上static关键字,这样就成为静态方法或静态属性。

function PersonThree() {
    this.name = "张三"
    this.age = 20
    this.run = function () {
        console.log(':run');
    }
}
PersonThree.getIofo = function () {
    console.log("我是静态方法!");
}
PersonThree.getIofo()

image.png

我们来看看ES6中如何定义使用静态类与静态方法:

 class ClassStaticMethod {
    static staticProperty = 'someValue';
    static staticMethod() {
        return 'static method has been called.';
    }            
}
console.log(ClassStaticMethod.staticProperty);
console.log(ClassStaticMethod.staticMethod());

image.png

ES5 里面的继承

对象冒充继承

对象冒充可以继承构造函数里面的属性和方法.但是没法继承原型链上面的属性和方法。
PersonTwo 在前面有提到,这里直接进行引用,run()函数是PersonTwo类里面有的,work()函数是通过原型链加上去的。

function StudentOne() {
    PersonTwo.call(this);
}
let stu1 = new StudentOne();
stu1.run()
// stu1.work()//报错

image.png image.png

左图是继承构造函数里面方法运行的结果,右图是报错。

原型链继承

继承我们也可以用原型链进行实现,代码如下:

function StudentTwo() {}
StudentTwo.prototype = new PersonTwo()
let stu2 = new StudentTwo();
stu2.work()

image.png

这种方法虽然克服了上面说的对象冒充继承的缺点,但是他有自己的缺点,实例化子类的时候没办法给父类传参,比如下面代码:

function PersonPro(name, age) {
    this.name = name
    this.age = age
    this.run = function () {
        console.log(this.name + ':run');
    }
}
PersonPro.prototype.sex = "男"
PersonPro.prototype.work = function () {
    console.log(this.name + ":work");
}
let per3 = new PersonPro("李四",25)
per3.run()
function StudentPro(name, age) {}
StudentPro.prototype = new PersonPro()
// 运行的work是  undefined:work
let stu3 = new StudentPro("小六", 29);
stu3.work()

image.png

原型链 + 对象冒充组合

如果我们把这两种方法结合起来效果会好很多。这时可以继承构造函数里面的属性和方法、实例化子类可以给父类传参。

function StudentGroup(name, age) {
    PersonPro.call(this, name, age)
}
StudentGroup.prototype = new PersonPro()
// 实例化子类的时候没办法给父类传参,这里运行的work是  undefined:work
let stuGroup = new StudentGroup("小六", 29);
stuGroup.work()

image.png