javascript --- > 类、class、事件委托的编程风格

类风格:

// 父类
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);
    }
};

// 子类
function Button(width, height, label) {
    // 调用父类(Widget)的构造函数
    Widget.call(this, width, height);
    this.label = label || "Default";
     
    this.$elem = $("<button>").text(this.label);
}

// 让Button"继承"Widget(Button可以使用Widget原型上的方法,本例中是render方法)
Button.prototype = Object.create(Widget.prototype);

// 重写render
Button.prototype.render = function($where) {
    // 调用父类(Widget)的render方法
    Widget.prototype.render.call(this, $where);  
    this.$elem.click(this.onClick.bind(this)); // 监听点击事件
};

Button.prototype.onClick = function(evt) {
    console.log("Button '" + this.label + " 'clicked!" );
};

$(document).ready(function() {
    var $body = $(document.body);
    var btn1 = new Button(125, 30, "Hello" );
    var btn2 = new Button(150, 40, "World");
     
    btn1.render($body);
    btn2.render($body);
});

// 注:用到了jquery故需要导入cdn <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.js"></script>

在这里插入图片描述
在这里插入图片描述
上述代码,首先定义了一个Widget的父类,然后使用使用在constructor中使用call方法(作用域绑定到当前)调用父类Widget的初始化…并添加了一个新的$elem(即Butoon标签).
在Button的原型上,使用Object.create()方法继承父类的原型方法(render).并新增了一个(按钮特有的)点击功能.

说明:上面是一个仿照类实现的方法,其实就是使用Widget.call 和Widget.prototype.render.call在Button函数中调用Widget…
用书上的原话说就是…丑陋的显示多态

ES6的class语法糖实现:

class Widget{
    constructor(width, height) {
         this.width = width || 50;
         this.heigth = height || 50;
         this.$elem = null;
    }
    // 很巧妙的render...
    render($where) {
        if(this.$elem) {
            this.$elem.css({
                width: this.width + "px",
                height: this.height + "px"
            }).appendTo($where);
        }
    }
}
class Button extends Widget{
    constructor(width, height, label) {
        super( width, height);
        this.label = label || "Default";
        this.$elem = $("<button>").text(this.label);  // 生成一个<button> 内容是label
    }
    render($where) {  // $where 是调用时传入的参数
        super.render($where);   // 调用父类Widget的render
        this.$elem.click(this.onClick.bind(this));
    }
    onClick(evt) {
        console.log("Button ' " + this.label + " ' clicked!");
    }
}
$(document).ready(function(){
    var $body = $(document.body);
    var btn1 = new Button(125, 30, "Hello" );
    var btn2 = new Button(150, 40, "World" );
     
    btn1.render($body);
    btn2.render($body);

})
//说明: 关键是super替代了伪类中的call方法...变得更简洁(at least看上去是这样...)

委托控件对象:

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.heigth + "px"
            }).appenTo($where);
        }
    }
};
// 还是定义一个Widget对象,, 使用委托(Object.create)顺着原型链[[prototype]]由下而上读取方法
var Button = Object.create(Widget);

Button.setup = function(width, height, label) {
    this.init(width, height);  // Button无init方法,顺着原型链找到了Widget中的init.
    this.label = label || "Default";
     
    this.$elem = $('<button>').text(this.label);
};
Button.build = function($where) {
    this.insert($where);
    this.$elem.click(this.onClick.bind(this));  // this.onClick实际上是Button.onClick
};
Button.onClick = function(evt) {
    console.log("Button '" + this.label + "' clicked!" );
};
$(document).ready(function(){
    var $body = $(document.body);
     
    var btn1 = Object.create(Button);
    btn1.setup(123, 30, 'Hello');
     
    var btn2 = Object.create(Button);
    btn2.setup(150, 40, 'World');
     
    btn1.build($body);
    btn2.build($body);
});
// 很美的方式

参考《你不知道的JavaScript》(上卷) P174 ~P177

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值