JavaScript设计模式(一):面向对象编程 - 继承

简介: / 利用闭包实现 let Book =(function() {// 静态私有变量 let bookNum = 0;// 静态私有方法 let checkBook = function(name) {};// 创建类 function _book(newId , newName , newPrice) {// 私有变量 let name , price;// 私有方法 function checkID(id) {} // 特权方法 this . getName =() => name;

灵活的语言-JavaScript

实现一个验证表单的功能,需要验证用户名、邮箱、密码

用对象收编变量

let CheckObject = {
   
   
    checkName: function () {
   
   
        // 验证姓名
    },
    checkEmail: function () {
   
   
        // 验证邮箱
    },
    checkPassword: function () {
   
   
        // 验证密码
    },
}

对象的另一种形式(函数对象)

  • 缺点:
    • 对象类不能复制一份(或者说这个对象类在用new关键字创建新的对象时,新创建的对象是不能继承这些方法的)
let CheckObject = function () {
   
   
};
CheckObject.checkName = function () {
   
   
    // 验证姓名
}
CheckObject.checkEmail = function () {
   
   
    // 验证邮箱
}
CheckObject.checkPassword = function () {
   
   
    // 验证密码
}

真假对象(闭包和类)

实现复制功能,人手一份

// 闭包 - 内部函数返回到外部
let CheckObject = function () {
   
   
    return {
   
   
        checkName: function () {
   
   
            // 验证姓名
        },
        checkEmail: function () {
   
   
            // 验证邮箱
        },
        checkPassword: function () {
   
   
            // 验证密码
        },
    }
}
let a = CheckObject();
a.checkName();
// 类 - 对象的实例化
let CheckObject = function () {
   
   
    this.checkName = function () {
   
   
        // 验证姓名
    }
    this.checkEmail = function () {
   
   
        // 验证邮箱
    }
    this.checkPassword = function () {
   
   
        // 验证密码
    }
}
let a = new CheckObject();
a.checkName();

一个检测类

  • 以上方法通过new关键字创建对象时,新创建额对象都会对类的this上的属性进行复制,所以这些新创建的对象都会有自己的一套方法,但缺点是消耗大,因为每次都需要复制一套方法

将方法创建在类的原型上,这样调用的方法就都会是同一个,减小消耗

let CheckObject = function () {
   
   
};
CheckObject.prototype.checkName = function () {
   
   
    // 验证姓名
    return this;
}
CheckObject.prototype.checkEmail = function () {
   
   
    // 验证邮箱
    return this;
}
CheckObject.prototype.checkPassword = function () {
   
   
    // 验证密码
    return this;
}
let a = new CheckObject();
a.checkName().checkEmail().checkPassword();

函数的祖先

抽象出一个可以添加方法功能的方法

Function.prototype.addMethod = function (name, fn) {
   
   
    this[name] = fn;
}

let methods = function () {
   
   
}; // 或者 let methods = new Function();

methods.addMethod('checkName', function () {
   
   
    // 验证姓名
});
methods.addMethod('checkEmail', function () {
   
   
    // 验证邮箱
});
methods.addMethod('checkPassword', function () {
   
   
    // 验证密码
});

链式添加方法功能并链式调用(以下两个方法只能为自身添加方法)

01.png

// 链式添加-方式一 (链式调用)
Function.prototype.addMethod = function (name, fn) {
   
   
    this[name] = fn;
}

let methods = function () {
   
   
}; // 或者 let methods = new Function();

methods.addMethod('checkName', function () {
   
   
    // 验证姓名
    console.log('验证姓名');
    return this;
});
methods.addMethod('checkEmail', function () {
   
   
    // 验证邮箱
    console.log('验证邮箱');
    return this;
});
methods.addMethod('checkPassword', function () {
   
   
    // 验证密码
    console.log('验证密码');
    return this;
});
methods.checkName().checkEmail().checkPassword(); // 验证姓名 验证邮箱 验证密码
// 链式添加-方式二 (方式一的改进版本) 存在消耗问题
Function.prototype.addMethod = function (name, fn) {
   
   
    this[name] = fn;
    return this;
}

let methods = function () {
   
   
}; // 或者 let methods = new Function();

methods.addMethod('checkName', function () {
   
   
    // 验证姓名
    console.log('验证姓名');
    return this;
}).addMethod('checkEmail', function () {
   
   
    // 验证邮箱
    console.log('验证邮箱');
    return this;
}).addMethod('checkPassword', function () {
   
   
    // 验证密码
    console.log('验证密码');
    return this;
});
methods.checkName().checkEmail().checkPassword(); // 验证姓名 验证邮箱 验证密码

改进:在原型上添加方法功能的方法

02.png

// 链式添加-方式三 (方式二的改进版本) 减小消耗
Function.prototype.addMethod = function (name, fn) {
   
   
    this.prototype[name] = fn;
    return this;
}

let Methods = function () {
   
   
}; // 或者 let methods = new Function();

Methods.addMethod('checkName', function () {
   
   
// 验证姓名
    console.log('验证姓名');
    return this;
}).addMethod('checkEmail', function () {
   
   
// 验证邮箱
    console.log('验证邮箱');
    return this;
}).addMethod('checkPassword', function () {
   
   
// 验证密码
    console.log('验证密码');
    return this;
});

let m = new Methods();
m.checkName().checkEmail().checkPassword(); // 验证姓名 验证邮箱 验证密码

写的都是看到的-面向对象编程

创建一个类(三种方式)

方式一:函数this创建方式

03.png

// 1.函数this创建方式
function Book(id, bookName, price) {
   
   
    this.id = id;
    this.bookName = bookName;
    this.price = price;
}

let book = new Book('abc', 'JS设计模式', 123.12);
console.log(book);

方式二:class-this创建方式

04.png

// 2.class-this创建方式
class Book {
   
   
    constructor(id, bookName, price) {
   
   
        this.id = id;
        this.bookName = bookName;
        this.price = price;
    }
}

let book = new Book('abc', 'JS设计模式', 123.12);
console.log(book);

方式三:原型创建方式 (setBookInfo方法在原型上)

05.png

// 3.原型创建方式 setBookInfo方法在原型上
let Book = function () {
   
   
};
Book.prototype.setBookInfo = function (id, bookName, price) {
   
   
    this.id = id;
    this.bookName = bookName;
    this.price = price;
}
let book = new Book();
book.setBookInfo('abc', 'JS设计模式', 123.12);
console.log(book);

图解

06.png

类的属性和方法

  • 属性和方法
    • 私有属性
    • 私有方法
    • 特权方法
    • 对象公有属性
    • 对象公有方法
    • 构造器
    • 类静态公有属性
    • 类静态公有方法

07.png

let Person = function (id, name, age) {
   
   
    // 私有属性
    let topSecret = '私密';

    // 私有方法
    function secretFn() {
   
   
    }

    // 特权方法
    //         能访问到自身的一些属性和方法,所以被称为特权方法;
    //         在对象创建时可以实例化对象的一些属性,又可被用作构造器;
    this.setName = function (n) {
   
   
        this.name = n;
    };
    this.setAge = function (a) {
   
   
        this.age = a;
    };

    // 对象公有属性
    this.id = id;

    // 对象公有方法(让他说出自己的秘密)
    this.publicFn = function () {
   
   
        console.log(topSecret);
    };

    // 构造器
    this.setName(name);
    this.setAge(age);
}

// 类静态公有属性(new过的对象不能访问)
Person.num = 10;
// 类静态公有方法(new过的对象不能访问)
Person.say = function () {
   
   
};

Person.prototype = {
   
   
    // 公有属性
    publicProp: '原型上的属性!',
    // 公有方法
    publicMethod: function () {
   
   
    }
}

let lee = new Person('abc', 'ProsperLee', 18);

console.log('Person', {
   
   Person});
console.log('lee', lee);

lee.publicFn(); // 私密

lee.publicProp; // 原型上的属性!

Person.num; // 10

lee.say; // undefined

在类的外部通过.语法定义的属性和方法和在类的外部通过prototype定义的属性和方法的区别:

function Person() {
   
   
    // this.say1(); // Error TypeError: this.say1 is not a function
    this.say2(); // Hello Lee!!!
}

Person.say1 = function () {
   
   
    console.log('Hello World!!!');
};

Person.prototype = {
   
   
    say2() {
   
   
        console.log('Hello Lee!!!');
    }
};

let person = new Person();

// person.say1(); // Error TypeError: person.say1 is not a function
person.say2(); // Hello Lee!!!
  • 区别:
    • 在类的外部通过.语法定义的属性和方法:
      • 不可通过 this 或者 new 的实例对象进行访问;
      • 可通过类进行调用 Person.say1();;
    • 在类的外部通过prototype定义的属性和方法:
      • 可通过 this 或者 new 的实例对象进行访问;
      • 不可通过类进行调用 Person.say2(); // Error;
      • 可通过 Person.prototype.方法 进行调用;

通过闭包来实现类的静态变量定义,使之更像一个整体

08.png

// 利用闭包实现
let Book = (function () {
   
   

    // 静态私有变量
    let bookNum = 0;

    // 静态私有方法
    let checkBook = function (name) {
   
   
    };

    // 创建类
    function _book(newId, newName, newPrice) {
   
   

        // 私有变量
        let name, price;

        // 私有方法
        function checkID(id) {
   
   
        }

        // 特权方法
        this.getName = () => name;
        this.getPrice = () => price;
        this.setName = function (n) {
   
   
            name = n;
        };
        this.setPrice = function (p) {
   
   
            price = p;
        };

        // 公有属性
        this.id = newId;
        name = newName;
        price = newPrice;

        // 公有方法
        this.copy = function () {
   
   
        };

        bookNum++;

        if (bookNum > 100) {
   
   
            throw new Error('我们仅出版100本书!!!');
        }

        // 构造器
        this.setName(name);
        this.setPrice(price);
    }

    // 构造原型
    _book.prototype = {
   
   
        // 静态公有属性
        isJSBook: true,
        // 静态公有方法
        display() {
   
   
        },
    };

    // 返回类
    return _book;

})();


let book = new Book('abc', 'JS设计模式', '12.34');

console.log('Book', {
   
   Book});

console.log('book', book);
book.getName(); // 'JS设计模式'
book.getPrice(); // '12.34'

忘记 new 怎么办?

let Book = function (id, bookName, price) {
   
   
    this.id = id;
    this.bookName = bookName;
    this.price = price;
}
let book = Book('abc', '《JS设计模式》', 12.34);
console.log(book);               // undefined
console.log(window.id);          // abc              this指向了window
console.log(window.bookName);    // 《JS设计模式》     this指向了window
console.log(window.price);       // 12.34            this指向了window

解决办法:

let Book = function (id, bookName, price) {
   
   
    // 判断this是否是当前这个对象(如果是说明是用new创建的)
    if (this instanceof Book) {
   
   
        this.id = id;
        this.bookName = bookName;
        this.price = price;
    } else {
   
    // 否则重新创建这个对象
        return new Book(id, bookName, price);
    }
}
let book = Book('abc', '《JS设计模式》', 12.34);
console.log(book);                  // Book {id: 'abc', bookName: '《JS设计模式》', price: 12.34}
console.log(window.id);             // undefined
console.log(window.bookName);       // undefined
console.log(window.price);          // undefined

子类的原型对象-类式继承

09.png

10.png

// 父类
function SuperClass() {
   
   
    this.superValue = true;
}

// 为父类添加共有方法
SuperClass.prototype.getSuperValue = function () {
   
   
    return this.superValue;
};

// 子类
function SubClass() {
   
   
    this.subValue = false;
}

// 继承父类
SubClass.prototype = new SuperClass();
// 为子类添加共有方法
SubClass.prototype.getSubValue = function () {
   
   
    return this.subValue;
};

let superClass = new SuperClass();
let subClass = new SubClass();

console.log(superClass, subClass);
  • instanceof 通过判断对象的 prototype链 来确定这个对象是否是某个类的实例,并不是表示两者的继承关系
  • 所有对象都是 Object 的实例
console.log(superClass instanceof SuperClass);          // true
console.log(subClass instanceof SubClass);              // true

console.log(subClass instanceof SuperClass);            // true
console.log(SubClass instanceof SuperClass);            // false

console.log(SubClass.prototype instanceof SuperClass);  // true        契合以上判断条件
console.log(SubClass instanceof Object);                  // true        契合以上判断条件

类式继承的缺点:

// 父类
function Father() {
   
   
    this.str = 'Lee';
    this.data = ['Lee'];
}

// 子类
function Son() {
   
   
}

// 继承父类
Son.prototype = new Father();

let instance1 = new Son();
let instance2 = new Son();

console.log(instance1.data, instance2.data);  // ['Lee'] ['Lee']

instance1.str = 'Tom';
instance1.data.push(18);

console.log(instance1.str, instance2.str);    // Tom Lee
console.log(instance1.data, instance2.data);  // (2)['Lee', 18] (2)['Lee', 18]
  1. 当一个子类的实例``更改子类原型从父类构造函数继承来的共有属性就会直接影响到其他子类
    • 比如: 修改 instance1 原型上继承来自父类的引用类型的值时, instance2 获取到的值也被改变了
  2. 无法在实例化子类的同时向父类传递参数
    • 比如: new Son(参数); 的时候没发把参数传递给父类,因为子类实现的继承是靠其原型等于父类的实例化实现的

创建即继承-构造函数继承

利用 call 改变函数作用环境

11.png

// 父类
function Father(id) {
   
   
    // 值类型公有属性
    this.id = id;
    // 引用类型公有属性
    this.data = ['Lee', 'Tom'];
}

// 父类原型方法
Father.prototype.showData = function () {
   
   
    console.log(this.data);
}

// 子类
function Son(id) {
   
   
    // 继承父类
    Father.call(this, id);
}

let instance1 = new Son('id-001');
let instance2 = new Son('id-002');

instance1.data.push('张三');

instance1.id;       // 'id-001'
instance1.data;     // ['Lee', 'Tom', '张三']

instance2.id;       // 'id-002'
instance2.data;     // ['Lee', 'Tom']

instance1.showData(); // Error TypeError: instance1.showData is not a function
instance2.showData(); // Error TypeError: instance2.showData is not a function

构造函数继承缺点:

  • 无法调用父类原型上的属性和方法(无法继承来自原型上的属性和方法)
    • 比如: instance1.showData();instance2.showData(); 会报错

将优点为我所用-组合继承

12.png

// 父类
function Father(fatherName) {
   
   
    // 值类型公有属性
    this.fatherName = fatherName;
    // 引用类型公有属性
    this.friends = ['Lee', 'Tom'];
}

Father.prototype.getFatherName = function () {
   
   
    console.log(this.fatherName);
};

// 子类
function Son(fatherName, myName) {
   
   
    // 构造函数式继承类
    Father.call(this, fatherName);
    // 子类中的公有属性
    this.myName = myName;
}

// 类式继承 - 子类继承父类
Son.prototype = new Father();

Son.prototype.getMyName = function () {
   
   
    console.log(this.myName);
};

console.log({
   
   Father}, {
   
   Son});

let son = new Son('汤姆', 'Tom');

console.log(son);

组合 类式和构造函数式 继承的缺点:

  • 父类的构造函数执行了两遍
    • 使用构造函数式继承时执行了一次父类的构造函数
    • 实现子类原型的类式继承时又调用了一遍父类的构造函数

洁净的继承者-原型式继承

13.png

// 原型式继承
function inheritObject(o) {
   
   
    // 声明一个 过渡函数对象
    function F() {
   
    }
    // 过渡对象 的 原型 继承 父对象
    F.prototype = o;
    // 返回过度对象的一个实例,该实例的原型继承了父对象
    return new F();
}

let friends = ['Lee', 'Tom'];

let obj1 = inheritObject({
   
    getName() {
   
    console.log('obj1', this.name); } });
obj1.name = 'Lee';
obj1.friends = friends;

let obj2 = inheritObject({
   
    getName() {
   
    console.log('obj2', this.name); } });
obj2.name = 'Tom';
obj2.friends = friends;

原型式继承的缺点:

14.png

obj1.friends.push('张三'); // friends.push('张三');
console.log('【obj1】', obj1, '【obj2】', obj2);
  • 当一个子类的实例``更改子类从父类构造函数继承来的共有属性就会直接影响到其他子类的实例
    • 比如: 修改 obj1 上继承来自父类的引用类型的值时, obj2 获取到的值也被改变了

如虎添翼-寄生式继承(对原型式继承的增强)

其实寄生式继承就是对原型继承的第二次封装,并且在这第二次封装过程中对继承的对象进行了拓展,这样新创建的对象不仅仅有父类中的属性和方法而且还添加新的属性和方法

15.png

// 基类
let userInfo = {
   
    name: 'Lee', age: 18 };
let friends = ['Lee', 'Tom'];

// 原型式继承
function inheritObject(o) {
   
   
    // 声明一个 过渡函数对象
    function F() {
   
    }
    // 过渡对象 的 原型 继承 父对象
    F.prototype = o;
    // 返回过度对象的一个实例,该实例的原型继承了父对象
    return new F();
}

function createObj(obj) {
   
   
    // 原型式继承
    let o = inheritObject(obj);
    // 拓展新对象
    o.friends = friends;
    o.getName = function () {
   
   
        console.log(this.name);
    }
    // 返回拓展后的新对象
    return o;
}

let obj1 = createObj(userInfo);
let obj2 = createObj(userInfo);

obj1.friends.push('张三');

console.log('【obj1】', obj1, '【obj2】', obj2);

寄生式继承缺点:

  • 与原型式继承相同

终极继承者-寄生组合式继承(寄生式继承构造函数继承的组合)

解决了子类实例化 修改公有属性 影响其他实例化的对象 的问题

16.png

// 原型式继承
function inheritObject(o) {
   
   
    // 声明一个 过渡函数对象
    function F() {
   
    }
    // 过渡对象 的 原型 继承 父对象
    F.prototype = o;
    // 返回过度对象的一个实例,该实例的原型继承了父对象
    return new F();
}

/**
 * 寄生组合式继承 - 寄生式继承,继承原型
 * @param {class} sonClass 子类
 * @param {class} fatherClass 父类
 */
function inheritPrototype(sonClass, fatherClass) {
   
   
    // 赋值一份父类的原型副本保存在变量中
    let p = inheritObject(fatherClass.prototype);
    // 修正因为重写子类原型导致子类的constructor属性被修改
    p.constructor = sonClass;
    // 设置子类的原型
    sonClass.prototype = p;
}

// 父类
function Father(fatherName) {
   
   
    this.fatherName = fatherName;
    this.friends = ['Lee', 'Tom'];
}

Father.prototype.getFatherName = function () {
   
   
    console.log(this.fatherName);
}

// 子类
function Son(fatherName, sonName) {
   
   
    Father.call(this, fatherName);
    this.sonName = sonName;
}

// 寄生式继承父类原型
inheritPrototype(Son, Father);

Son.prototype.getSonName = function () {
   
   
    console.log(this.sonName);
}

let son1 = new Son('汤姆', 'Tom');
let son2 = new Son('张三', 'ZhangSan');

son1.getFatherName();   // 汤姆
son1.getSonName();      // Tom

son1.friends.push('张三');

console.log('【son1】', son1, '【son2】', son2);

原理图

17.png

老师不止一位-多继承

单继承

18.png

// 单继承 属性复制继承(此示例使用的是浅克隆)
var extend = function (target, source) {
   
   
    // 遍历源对象中的属性
    for (var property in source) {
   
   
        // 将源对象中的属性复制到目标对象中
        target[property] = source[property];
    }
    // 返回目标对象
    return target;
};

var father = {
   
   
    money: 1E10,
    friends: ['Lee', 'Tom']
}
var son = {
   
   
    name: '张三'
}

// son 继承 father
extend(son, father);

son.friends.push('Lucy');

son.money = 10;

son.name = '小明';

多继承 (方式一)

19.png

// 多继承 属性复制  
var mix = function () {
   
   
    var i = 1,                      // 从第二个参数起为被继承的对象
        len = arguments.length,     // 获取参数长度
        target = arguments[0],      // 第一个对象为目标对象
        arg;                        // 缓存参数对象
    // 遍历被继承的对象
    for (; i < len; i++) {
   
   
        // 缓存当前对象
        arg = arguments[i];
        // 遍历被继承对象中的属性
        for (var property in arg) {
   
   
            // 将被继承对象中的属性复制到目标对象中
            target[property] = arg[property];
        }
    }

    // 返回目标对象
    return target;
};

let parent1 = {
   
    money: 1E10 };
let parent2 = {
   
    friends: ['Lee', 'Tom'] };
let parent3 = {
   
    hobbies: ['躺着'] };
let son = {
   
    name: '小明' };

mix(son, parent1, parent2, parent3);

console.log(son);

多继承 (方式二)

20.png

Object.prototype.mix = function () {
   
   
    var i = 0,                      // 从第一个参数起为被继承的对象
        len = arguments.length,     // 获取参数长度
        arg;                        // 缓存参数对象
    // 遍历被继承的对象
    for (; i < len; i++) {
   
   
        // 缓存当前对象
        arg = arguments[i];
        // 遍历被继承对象中的属性
        for (var property in arg) {
   
   
            // 将被继承对象中的属性复制到目标对象中
            this[property] = arg[property];
        }
    }
}

let parent1 = {
   
    money: 1E10 };
let parent2 = {
   
    friends: ['Lee', 'Tom'] };
let parent3 = {
   
    hobbies: ['躺着'] };
let son = {
   
    name: '小明' };
son.mix(parent1, parent2, parent3);
console.log(son);

多种调用方式-多态

多态,就是同一个方法多种调用方式

function Add() {
   
   

    // 无参数算法
    function zero() {
   
   
        return 10;
    }

    // 一个参数算法
    function one(num) {
   
   
        return 10 + num;
    }

    // 两个参数算法
    function two(num1, num2) {
   
   
        return num1 + num2;
    }

    // 相加共有方法
    this.add = function () {
   
   
        var arg = arguments,
            // 获取参数长度
            len = arg.length;
        switch (len) {
   
   
            // 如果没有参数
            case 0:
                return zero();
            // 如果只有一个参数
            case 1:
                return one(arg[0]);
            // 如果有两个参数
            case 2:
                return two(arg[0], arg[1]);
        }
    }
}
// 实例化类
var A = new Add();
//测试
console.log(A.add());       // 10
console.log(A.add(5));      // 15
console.log(A.add(6, 7));   // 13
目录
相关文章
|
1天前
|
设计模式 前端开发 JavaScript
【JavaScript 技术专栏】JavaScript 设计模式与实战应用
【4月更文挑战第30天】本文探讨JavaScript设计模式在提升开发效率和代码质量中的关键作用。涵盖单例、工厂、观察者、装饰器和策略模式,并通过实例阐述其在全局状态管理、复杂对象创建、实时数据更新、功能扩展和算法切换的应用。理解并运用这些模式能帮助开发者应对复杂项目,提升前端开发能力。
|
1天前
|
设计模式 安全 Java
面向对象编程的精髓:Java设计模式 - 原型模式(Prototype)完全参考手册
【4月更文挑战第7天】原型模式是OOP中的创建型设计模式,用于通过复制现有实例创建新实例,尤其适用于创建成本高或依赖其他对象的情况。它包括Prototype接口、ConcretePrototype实现和Client客户端角色。优点是性能优化、避免子类化和动态增加产品族。实现包括定义原型接口、实现具体原型和客户端调用克隆方法。最佳实践涉及确保克隆正确性、选择深拷贝或浅拷贝及考虑线程安全。但需注意克隆方法管理、性能开销和循环引用等问题。在Java中,实现Cloneable接口和覆盖clone方法可实现原型模式。
|
1天前
|
JavaScript 前端开发
JavaScript 继承的方式和优缺点
JavaScript 继承的方式和优缺点
15 0
|
1天前
|
JavaScript 前端开发 Java
深入JS面向对象(原型-继承)(三)
深入JS面向对象(原型-继承)
31 0
|
1天前
|
JavaScript 前端开发 Java
深入JS面向对象(原型-继承)(一)
深入JS面向对象(原型-继承)
32 0
|
1天前
|
设计模式 JavaScript 前端开发
js设计模式-观察者模式与发布/订阅模式
观察者模式和发布/订阅模式是JavaScript中的两种设计模式,用于处理对象间的通信和事件处理。观察者模式中,一个主题对象状态改变会通知所有观察者。实现包括定义主题和观察者对象,以及在主题中添加、删除和通知观察者的功能。发布/订阅模式则引入事件管理器,允许发布者发布事件,订阅者通过订阅接收通知。
|
1天前
|
设计模式 JavaScript 算法
js设计模式-策略模式与代理模式的应用
策略模式和代理模式是JavaScript常用设计模式。策略模式通过封装一系列算法,使它们可互换,让算法独立于客户端,提供灵活的选择。例如,定义不同计算策略并用Context类执行。代理模式则为对象提供代理以控制访问,常用于延迟加载或权限控制。如创建RealSubject和Proxy类,Proxy在调用RealSubject方法前可执行额外操作。这两种模式在复杂业务逻辑中发挥重要作用,根据需求选择合适模式解决问题。
|
1天前
|
JavaScript 前端开发
JavaScript 中最常用的继承方式
【5月更文挑战第9天】JavaScript中的继承有多种实现方式:1) 原型链继承利用原型查找,但属性共享可能引发问题;2) 借用构造函数避免共享,但方法复用不佳;3) 组合继承结合两者优点,是最常用的方式;4) ES6的class继承,是语法糖,仍基于原型链,提供更直观的面向对象编程体验。
17 1
|
1天前
|
设计模式 JavaScript 前端开发
在JavaScript中,继承是一个重要的概念
【5月更文挑战第9天】JavaScript继承有优点和缺点。优点包括代码复用、扩展性和层次结构清晰。缺点涉及深继承导致的复杂性、紧耦合、单一继承限制、隐藏父类方法以及可能的性能问题。在使用时需谨慎,并考虑其他设计模式。
15 2
|
1天前
|
JavaScript 前端开发 开发者
JavaScript 继承的方式和优缺点
JavaScript 继承的方式和优缺点
12 0