CoffeeScript 中的继承实现
Inheritance implementation in CoffeeScript
我正在学习javascript中不同的继承实现,主要是遵循Stoyan Stefanov的Javascript Patterns一书。
现在我正在检查 Coffescript 如何实现它。因此,给定父项和子项classes
或构造函数:
class Animal
constructor: (@name) ->
move: (meters) ->
alert @name + " moved #{meters}m."
class Snake extends Animal
move: ->
alert "Slithering..."
super 5
sam = new Snake "Sammy the Python"
sam.move()
它们被编译为:
var Animal, Horse, Snake, sam,
_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;
},
_hasProp = {}.hasOwnProperty;
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);
sam = new Snake("Sammy the Python");
sam.move();
正如我所理解的那样,咖啡脚本中继承的实现是由不同模式的组合产生的:
1. 经典代理构造函数
在这种情况下,我们还重置constructor pointer
并存储超类引用。斯特凡诺夫对"圣杯"的定义。使用此模式,子项仅继承原型的属性。
// the proxy function
function ctor() {
this.constructor = child;
}
ctor.prototype = parent.prototype;
child.prototype = new ctor();
child.__super__ = parent.prototype;
2. 通过复制属性进行继承
使用这种模式,我们只需将一个对象的属性复制到另一个对象中
_hasProp = {}.hasOwnProperty;
for (var key in parent) {
if (_hasProp.call(parent, key)) child[key] = parent[key];
}
3. 经典模式 - 租用构造函数(或借用构造函数(
function Snake() {
return Snake.__super__.constructor.apply(this, arguments);
}
问题:
- 我的假设正确吗?咖啡脚本编译器是否使用 1+2+3?
- 通过复制进行的继承似乎使用浅拷贝,这意味着它不会检查该属性是否是对象/数组并开始递归。即使结果也很艰难,似乎是一个完美的深层副本(对象/数组是副本,而不是引用(。为什么/如何?
- 租一个构造器不是在重复继承吗?复制属性,然后再次调用父构造函数?
_extends
函数也可以在对象之间而不是构造函数之间使用吗?
谢谢
- 租一个构造器不是在重复继承吗?复制属性,然后再次调用父构造函数?
此处复制的属性...
for (var key in parent) {
if (_hasProp.call(parent, key)) child[key] = parent[key];
}
。不是原型属性,它们是"类级"属性,是在函数本身上定义的方法。它将属性从函数Animal
复制到函数Horse
。
区别在于:
class Animal
# Not part of prototype, part of Animal, must be copied
@build: (name) ->
new @(name)
constructor: (name) ->
@name = "An animal named #{name}"
# Part of prototype
sayName: ->
alert(@name)
class Bird extends Animal
constructor: (name) ->
@name = "A bird named #{name}"
# Both Animal and Bird have build because of the copying of properties:
a = Animal.build('sam') # an animal named sam
b = Bird.build('bob') # a bird named bob
对编译的 JavaScript 的一些注释:
var Animal, Bird, a, b,
__extends = function(child, parent) {
for (var key in parent) {
# Copies Animal.build to Bird.build
if (__hasProp.call(parent, key)) child[key] = parent[key];
}
function ctor() {
this.constructor = child;
}
# Makes sayName available to Bird via prototypal inheritance
ctor.prototype = parent.prototype;
child.prototype = new ctor();
child.__super__ = parent.prototype;
return child;
},
__hasProp = {}.hasOwnProperty;
Animal = (function() {
Animal.build = function(name) {
return new this(name);
};
function Animal(name) {
# This still (theoretically) needs to be invoked, regardless of whether
# the properties are copied over, though it isn't invoked in this example
this.name = "An animal named " + name;
}
Animal.prototype.sayName = function() {
return alert(this.name);
};
return Animal;
})();
Bird = (function(_super) {
__extends(Bird, _super);
# There is no "Bird.build" defined here, it is copied from Animal
function Bird(name) {
this.name = "A bird named " + name;
}
# There is no "move" defined here, it is provided by our prototyep
return Bird;
})(Animal);
a = Animal.build('sam');
b = Bird.build('bob');
无论如何,复制属性然后"再次调用父构造函数"并不是真正会发生的情况。
属性不是在父构造函数中定义的,父构造函数只是需要运行的可执行代码 blob。它可能没有定义任何属性,或者它可能定义一堆属性,但这些属性不会由原型或_hasOwnProperty
循环设置。
相关文章:
- 在JavaScript中使用对象文字实现继承
- CoffeeScript 中的继承实现
- 在 JavaScript 中实现简单继承
- 使用Google闭包库的正确继承/子类实现剖析
- 如何在 javascript 中实现继承
- 如何实现 JavaScript 对象继承
- 在这种情况下在 JavaScript 中实现继承 [更具体地说是 node.js]
- 如何在 Screeps 对象中实现继承
- 在 AngularJS 指令中实现继承
- 在Javascript中使用寄生继承,是否可以实现内省实例方法
- 这种嵌套命名空间继承模式是否得到了很好的实现
- 用Selfish实现Javascript中的简单继承
- 我怎么能在Backbone中简单地实现类Sencha继承呢
- 使用父对象中的私有变量实现原型继承
- 如何在JavaScript中实现继承
- 我如何在JavaScript中实现这个java模式(使用继承)
- Javascript:如果不使用define prototype方法就可以实现继承,为什么还要使用它呢?
- 如何在Jquery UI控件中实现继承
- 在javascript中实现继承时出错
- 如何实现继承像&;var obj = new OpenLayers.Layer.WMS(.. ..)&;在Javascr