class/继承/super
JavaScript 的原型继承有点烧脑, 存在大量的类库用于在 JavaScript 的原型之上实现更清晰的 class 继承, 比如: Base2, Prototype.js, JS.Class. 这些类库提供了语法糖, 但如果不是因为一些例外的话原生的继承完全是可用的, 例外比如: 很难调用 super(当前函数的原型上的实现), 很难正确设置原型链.
相比重复地设置函数的原型, CoffeeScript 提供了一个基础的 class 结构, 你可以在一个定义的表达式里完成命名 class, 定义父类, 赋值原型上的属性, 定义构造器.
构造函数被命名, 这对查看调用栈有更好的支持. 下面例子中的第一个类, this.constructor.name is "Animal".
CoffeeScript:编译成JS:
- class Animal
- constructor: (@name) ->
- move: (meters) ->
- alert @name + " moved #{meters}m."
- class Snake extends Animal
- move: ->
- alert "Slithering..."
- super 5
- class Horse extends Animal
- move: ->
- alert "Galloping..."
- super 45
- sam = new Snake "Sammy the Python"
- tom = new Horse "Tommy the Palomino"
- sam.move()
- tom.move()
- var Animal, Horse, Snake, sam, tom,
- __hasProp = {}.hasOwnProperty,
- __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
- Animal = (function() {
- function Animal(name) {
- this.name = name;
- }
- Animal.prototype.move = function(meters) {
- return alert(this.name + (" moved " + meters + "m."));
- };
- return Animal;
- })();
- Snake = (function(_super) {
- __extends(Snake, _super);
- function Snake() {
- return Snake.__super__.constructor.apply(this, arguments);
- }
- Snake.prototype.move = function() {
- alert("Slithering...");
- return Snake.__super__.move.call(this, 5);
- };
- return Snake;
- })(Animal);
- Horse = (function(_super) {
- __extends(Horse, _super);
- function Horse() {
- return Horse.__super__.constructor.apply(this, arguments);
- }
- Horse.prototype.move = function() {
- alert("Galloping...");
- return Horse.__super__.move.call(this, 45);
- };
- return Horse;
- })(Animal);
- sam = new Snake("Sammy the Python");
- tom = new Horse("Tommy the Palomino");
- sam.move();
- tom.move();
如果你不喜欢用 class 的裁判法定义原型, CoffeeScript 提供了一些低级的方便写法. extends 操作符可以用来恰当地定义任何一对构造函数的原型链; 用 :: 可以快速访问对象的原型; super() 可以编译为一个父类上同名方法的调用.
CoffeeScript:编译成JS:
- String::dasherize = ->
- this.replace /_/g, "-"
- String.prototype.dasherize = function() {
- return this.replace(/_/g, "-");
- };
最后, class 定义是可执行的代码, 这样就可能进行元编程. 因为在 class 定义的上下文当中, this 是类对象本身(构造函数), 可以用 @property: value 赋值静态的属性, 也可以调用父类的方法: @attr 'title', type: 'text'.
转载本站内容时,请务必注明来自W3xue,违者必究。