• 前端基础(四十一):你不知道的JavaScript - 行为委托 及 类写法的实例应用


    [[Prototype]]机制

    [[Prototype]] 机制: JavaScript 中这个[[Prototype]] 机制的本质就是对象之间的关联关系。

    面向委托的设计

    类理论

    SonA 未重写父类方法,所以.say()执行的是父类中的say方法

    SonB 重写了父类方法,所以.say()执行的是重写后的say方法

    在这里插入图片描述

    class Father {
        id = '';
        constructor(id) {
            this.id = id;
        }
        say() {
            return this.id;
        }
    }
    
    class SonA extends Father {
        label = '';
        constructor(id, label) {
            super(id);
            this.label = label;
        }
    }
    
    class SonB extends Father {
        label = '';
        constructor(id, label) {
            super(id);
            this.label = label;
        }
        say() {
            return this.label;
        }
    }
    
    const sonA = new SonA('aaa', 'Lee');
    const sonB = new SonB('bbb', 'Tom');
    
    console.log(sonA, sonB); // SonA {id: 'aaa', label: 'Lee'}  SonB {id: 'bbb', label: 'Tom'}
    console.log(sonA.say(), sonB.say()); // aaa Tom
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34

    委托理论

    以委托行为方式来思考上述代码

    以下的编码格式风格称为 “对象关联”(OLOO, objects linked to other objects)

    在这里插入图片描述

    const Father = {
        setData(id) { this.id = id },
        say() { return this.id }
    }
    
    const sonA = Object.create(Father);
    sonA.setDataA = function (id, label) { this.setData(id); this.label = label; }
    
    const sonB = Object.create(Father);
    sonB.setDataB = function (id, label) { this.setData(id); this.label = label; }
    sonB.say = function () { return this.label; }
    
    sonA.setDataA('aaa', 'Lee');
    sonB.setDataB('bbb', 'Tom');
    
    console.log(sonA, sonB); // {id: 'aaa', label: 'Lee', setDataA: ƒ} {id: 'bbb', label: 'Tom', setDataB: ƒ, say: ƒ}
    console.log(sonA.say(), sonB.say()); // aaa Tom
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 对象关联特点:
      • idlabel 数据成员都是直接存储在 sonA sonB 上(而不是 Father)
      • 应尽量避免方法的重写,如以上代码重写了say方法
      • this.setData(id);会先从本身开始像原型链上查找此方法

    类与对象 - JavaScript创建UI控件

    比如使用ES6类的class形式创建一个Button UI组件 - (面向对象的UI控件创建)
    在这里插入图片描述

    控件创建渲染 (ES5类继承形式)

    // 控件基类
    function Widget(width, height) {
        this.width = width || 50;
        this.height = height || 50;
        this.$elem = null;
    }
    
    // 渲染方法
    Widget.prototype.render = function ($where) {
        if (this.$elem) {
            this.$elem.css({
                width: this.width + "px",
                height: this.height + "px"
            }).appendTo($where);
        }
    };
    
    // Button控件
    function Button(width, height, label) {
        // 调用“super”构造函数
        Widget.call(this, width, height);
        this.label = label || "Default";
        this.$elem = $("

    控件“类” (类形式)

    // UI组件基类
    class Widget {
    
        /**
         * 初始化控件
         * @param {number} width 宽度
         * @param {number} height 高度
         * @returns {undefined}
         */
        constructor(width, height) {
            this.width = width || 50;
            this.height = height || 50;
            this.$elem = null;
        }
    
        /**
         * 渲染控件
         * @param {Element} $where 父控件
         * @returns {undefined}
         */
        render($where) {
            if (this.$elem) {
                this.$elem.css({
                    width: this.width + "px",
                    height: this.height + "px"
                }).appendTo($where);
            }
        }
    
    }
    
    // Button组件
    class Button extends Widget {
    
        /**
         * 初始化控件
         * @param {number} width 宽度
         * @param {number} height 高度
         * @param {string} label 控件内容
         * @returns {undefined}
         */
        constructor(width, height, label) {
            // 调用父类方法
            super(width, height);
            this.label = label || "Default";
            this.$elem = $("

    委托控件对象 (委托形式)

    // UI控件基类
    var Widget = {
        init: function (width, height) {
            this.width = width || 50;
            this.height = height || 50;
            this.$elem = null;
        },
        insert: function ($where) {
            if (this.$elem) {
                this.$elem.css({
                    width: this.width + "px",
                    height: this.height + "px"
                }).appendTo($where);
            }
        }
    };
    
    // Button继承自Widget
    var Button = Object.create(Widget);
    
    // Button控件初始化
    Button.setup = function (width, height, label) {
        // 委托调用
        this.init(width, height);
        this.label = label || "Default";
        this.$elem = $("

    更好的语法

    在这里插入图片描述

    <form action="#" onsubmit="return false;">
        <p><label for="login_username">用户名:<input id="login_username" type="text">label>p>
        <p><label for="login_password">密码:<input id="login_password" type="password">label>p>
        <button id="login_btn" type="submit">登录button>
    form>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    {
        "code": 200,
        "data": {
            "name": "PLee",
            "age": 18
        },
        "msg": "操作成功"
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    // 基类
    class Controller {
    
        errors = null;
    
        constructor() {
            this.errors = [];
        }
    
        // 获取得到的数据
        getData(title, data) {
            console.log(title, data);
        }
    
        // 成功
        success(res) {
            this.getData("【Success】", res);
        }
    
        // 失败
        failure(err) {
            this.errors.push(err);
            this.getData("【Error】", err);
        }
    
    }
    
    // 登录
    class LoginController extends Controller {
    
        constructor() {
            super();
        }
    
        // 获取用户名
        getUser() {
            return document.getElementById("login_username").value;
        }
    
        // 获取密码
        getPassword() {
            return document.getElementById("login_password").value;
        }
    
        // 验证 用户名/密码
        validateEntry(user, pw) {
            user = user || this.getUser();
            pw = pw || this.getPassword();
            if (!user) {
                return this.failure("请输入用户名!");
            }
            if (!pw) {
                return this.failure("请输入密码!");
            }
            // 如果执行到这里说明通过验证
            return true;
        }
    
        // 重写基础的 failure()
        failure(err) {
            super.failure(err);
        }
    
    }
    
    // 认证
    class AuthController extends Controller {
    
        login = null;
    
        constructor(login) {
            super();
            this.login = login;
        }
    
        // 数据请求
        server(url, data) {
            return $.ajax({ url, data });
        }
    
        // 检查认证
        checkAuth() {
            var user = this.login.getUser();
            var pw = this.login.getPassword();
            if (this.login.validateEntry(user, pw)) {
                this.server("/check-auth.json", { user, pw })
                    .then(res => this.success(res))
                    .fail(err => this.failure(err));
            }
        }
    
        // 成功
        success(res) {
            super.success(res);
        }
    
        // 失败
        failure(err) {
            super.failure(err);
        }
    
    }
    
    $(document).ready(function () {
        $('#login_btn').click(function (e) {
            var auth = new AuthController(new LoginController());
            auth.checkAuth();
        })
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
  • 相关阅读:
    如何选择适合自己门店的收银系统呢?
    PyCharm及第三方库安装教程
    递归的总结和案例
    BP神经网络算法基本原理,bp神经网络算法详解
    Hexagon_V65_Programmers_Reference_Manual(6)
    北京化工大学2022-2023-1 ACM集训队每周程序设计竞赛(10)题解
    kettle在linux上的运行方法
    java计算机毕业设计ssm+jsp计算机视频学习网站
    技术分享 | 误删表以及表中数据,该如何恢复?
    MongoDB_实战部分(二)
  • 原文地址:https://blog.csdn.net/weixin_43526371/article/details/126472396