前端基础(三十五):你不知道的JavaScript - 混合对象“类”

类理论

面向对象编程强调的是数据和操作数据的行为本质上是互相关联的,因此最好的设计就是把数据和它相关的行为封装起来。

例如:字符和字符串的关系,字符串是一串字符连接在一起,字符相当于数据,对字符串的操作是行为,通常会有计算字符串长度、添加、搜索等功能,所以被设计成了String类方法。

所有的字符串都是String类的一个实例,包含字符数据和可以应用到数据上的行为动作。

“类”设计模式 (编程风格)

面向对象的设计模式:迭代器模式观察者模式工厂模式单例模式

还有一种变成风格是 过程化变成

JavaScript中的“类”

js中的“类”与其他语言上的类是不一样的(虽然ES6添加了一个class关键字),可以说js机制似乎一直在阻止你使用类的设计模式,只能说js中的“类”是一种近似类的机制。

类的机制

  • 基本机制
    • 类中存放一些变量,提供一些共有的了访问方法
    • 使代码和数据(变量)进行交互(访问方法)
    • 操作的实际上是类的实例化上的数据和方法(静态类成员除外)

建造

类其实就是相当于建造,可以比作建筑中的蓝图类的实例可以比作工人通过蓝图构建的实际建筑

一个蓝图就一个),但可以有多个实例实际建筑可以根据蓝图构建出多个)。

构造函数

class Person {
    
    
    name = '';
    // 构造函数
    constructor(name) {
    
    
        this.name = name;
    }
    sayName() {
    
    
        console.log(this.name);
    }
}
var person = new Person('Lee');
person.sayName();

类的继承

B类继承A类B类为A类的子类A类为B类的父类

class Father {
    
    
    constructor(surname) {
    
    
        this.surname = surname;
    }
    saySurname() {
    
    
        console.log(this.surname);
    }
}

class Son extends Father {
    
    
    constructor(surname, name) {
    
    
        super(surname);
        this.name = name;
    }
    sayFullName() {
    
    
        console.log(`${
      
      this.name} - ${
      
      this.surname}`);
    }
}

var son = new Son('Lee', 'Prosper');

console.log(son.surname); // Lee
console.log(son.name); // Prosper

son.saySurname(); // Lee
son.sayFullName(); // Prosper - Lee

多态

多态的字面意思就是多种状态,同一操作作用于不同的对象上,可以产生不同的解释和不同的执行结果

class Animal {
    
    
    say() {
    
    
        console.log('Hello');
    }
    eat() {
    
    
        console.log('动物用嘴吃饭-狼吞虎咽!!!');
    }
}

class Person extends Animal {
    
    
    eat() {
    
    
        super.eat();
        console.log('人用嘴吃饭-斯文的可以了!!!');
    }
}

var person = new Person();

person.say(); // Hello

person.eat(); // 动物用嘴吃饭-狼吞虎咽!!! 人用嘴吃饭-斯文的可以了!!!

多重继承

js不支持多重继承,但可以借助别的手段实现(混入)
在这里插入图片描述

混入

混入模式(无论显式还是隐式)可以用来模拟类的复制行为,但是通常会产生丑陋并且脆 弱的语法,比如显式伪多态(OtherObj.methodName.call(this, …)),这会让代码更加难 懂并且难以维护。

显式混入

/**
 * 简单的显示混入(其中name被重写了)
 * source   要添加的对象
 * target   最终对象
 */
function mixin(source, target) {
    
    
    for (const key in source) {
    
    
        if (!(key in target)) {
    
    
            target[key] = source[key];
        }
    }
    return target;
}

var lee = {
    
    
    name: 'Tom',
    age: 25,
    say() {
    
    
        console.log('Tom');
    }
}

var person = mixin(lee, {
    
    
    name: 'Lee', // 重写了lee中的name
    hello() {
    
    
        console.log('hello');
    }
})

// {name: 'Lee', age: 25, say: ƒ(){Tom}, hello: ƒ(){hello}}
console.log(person);
  • 寄生继承
    function Father() {
          
          
        this.name = "Father";
    }
    
    Father.prototype.say = function () {
          
          
        return 'Father';
    }
    
    Father.prototype.hello = function () {
          
          
        return `Hello ${
            
            this.say()}`;
    }
    
    // 寄生类, 寄生自Father
    function Son() {
          
          
        var father = new Father();
        /**
         * Father { name: 'Father' }
         * Father.prototype { hello: ƒ (), say: ƒ () }
         */
        console.log(father);
        console.log(father.hello()); // Hello Father
    
        father.age = 36;
    
        var hello = father.hello; // ƒ () { return `Hello ${this.say()}`; }
        // console.log(hello()); // err ---> this.say is not a function
        father.hello = function () {
          
          
            return hello.call(this); // this ---> father
        }
        console.log(father.hello()); // Hello Father
    
        return father;
    }
    
    var son = new Son();
    
    /**
     * Father { name: 'Father', age: 36, hello: ƒ () { return hello.call(this); } }  
     * Father.prototype { hello: ƒ () { return hello.call(this); }, say: ƒ () }
     */ 
    console.log(son);
    
    console.log(son.say);       // ƒ () { return 'Father'; }
    
    console.log(son.hello);     // ƒ () { return hello.call(this); }
    console.log(son.hello());   // Hello Father
    

隐式混入

var Something = {
    
    
    cool: function () {
    
    
        this.greeting = "Hello World";
        this.count = this.count ? this.count + 1 : 1;
    }
};
Something.cool();
console.log(Something); // { cool: fun, greeting: "Hello World", count: 1 }

var Another = {
    
    
    count: 1, // 因为自身自带count所以执行 `this.count + 1` 这段代码
    cool: function () {
    
    
        // 隐式把 Something 混入 Another 
        Something.cool.call(this);
    }
};
Another.cool();
console.log(Another); // { cool: fun, greeting: "Hello World", count: 2 }

猜你喜欢

转载自blog.csdn.net/weixin_43526371/article/details/125220086