005 - 类与对象

1、下面这段代码展示的是如何在不使用任何“类”辅助库或者语法的情况下,使用纯JavaScript 实现类风格的代码:

继承属性:Widget.call( this, width, height );

继承方法:Button.prototype = Object.create( Widget.prototype );

// 父类
 
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) {
    // 调用“super”构造函数
    Widget.call(this, width, height);
    this.label = label || "Default";
    this.$elem = $("<button>").text(this.label);
}
// 让 Button“继承”Widget
Button.prototype = Object.create(Widget.prototype);
// 重写 render(..)
Button.prototype.render = function ($where) {
    //“super”调用
    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);
});


2、ES6的class语法糖方法实现

class Widget {
    constructor(width, height) {
        this.width = width || 50;
        this.height = height || 50;
        this.$elem = null;
    }
    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);
    }
    render($where) {
        super($where);
        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);
});



3、委托控件对象方式实现

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);
        }
    }
};
var Button = Object.create(Widget);
Button.setup = function (width, height, label) {
    // 委托调用
    this.init(width, height);
    this.label = label || "Default";
    this.$elem = $("<button>").text(this.label);
};
Button.build = function ($where) {
    // 委托调用
    this.insert($where);
    this.$elem.click(this.onClick.bind(this));
};
Button.onClick = function (evt) {
    console.log("Button '" + this.label + "' clicked!");
};
$(document).ready(function () {
    var $body = $(document.body);
    var btn1 = Object.create(Button);
    btn1.setup(125, 30, "Hello");
    var btn2 = Object.create(Button);
    btn2.setup(150, 40, "World");
    btn1.build($body);
    btn2.build($body);
});
3.1、更好的语法

在 ES6 中 我 们 可 以 在 任 意 对 象 的 字 面 形 式 中 使 用 简 洁 方 法 声 明(concise method
declaration),所以对象关联风格的对象可以这样声明(和 class 的语法糖一样):

var LoginController = {
    errors: [],
    getUser() { // 妈妈再也不用担心代码里有 function 了!
        // ...
    },
    getPassword() {
        // ...
    }
    // ...
};
唯一的区别是对象的字面形式仍然需要使用“,”来分隔元素,而 class 语法不需要。这个
区别对于整体的设计来说无关紧要。


此外,在 ES6 中,你可以使用对象的字面形式(这样就可以使用简洁方法定义)来
改 写 之 前 繁 琐 的 属 性 赋 值 语 法( 比 如 AuthController 的 定 义 ), 

然 后 用 Object.setPrototypeOf(..) 来修改它的 [[Prototype]]:

// 使用更好的对象字面形式语法和简洁方法
var AuthController = {
    errors: [],
    checkAuth() {
        // ...
    },
    server(url, data) {
        // ...
    }
    // ...
};
// 现在把 AuthController 关联到 LoginController
Object.setPrototypeOf(AuthController, LoginController);
使用 ES6 的简洁方法可以让对象关联风格更加人性化(并且仍然比典型的原型风格代码更
加简洁和优秀)。你完全不需要使用类就能享受整洁的对象语法!


小结:

在软件架构中你可以选择是否使用类和继承设计模式。大多数开发者理所当然地认为类是
唯一(合适)的代码组织方式,但是本章中我们看到了另一种更少见但是更强大的设计模

式:行为委托。
行为委托认为对象之间是兄弟关系,互相委托,而不是父类和子类的关系。JavaScript 的
[[Prototype]] 机制本质上就是行为委托机制。也就是说,我们可以选择在 JavaScript 中努
力实现类机制(参见第 4 和第 5 章),也可以拥抱更自然的 [[Prototype]] 委托机制。
当你只用对象来设计代码时,不仅可以让语法更加简洁,而且可以让代码结构更加清晰。
对象关联(对象之前互相关联)是一种编码风格,它倡导的是直接创建和关联对象,不把
它们抽象成类。对象关联可以用基于 [[Prototype]] 的行为委托非常自然地实现。











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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值