我是一名强大的JavaScript背景的架构师,但我过去曾做过一些.NET和Java。
但是,我想把手放在ActionScript3上,我承诺这与JavaScript非常相关。
作为一个启动项目,我自己尝试将ActionScript3移植到我最喜欢的断言工具之一 - should.js - 这使得您的测试代码非常适合阅读。
更新时间:2013-02-19
我看到我对我的抽象发言感到困惑,所以我用一些具体问题替换了一些帖子。 这是完整的图片:
考虑以下JavaScript代码:
Object.defineProperty(Object.prototype, 'should'
, { set: function(){}
, get:
function(){
return new Assertion(Object(this).valueOf());
}
, configurable: true
, enumerable : false
}
);
这是JavaScript模块Should
的实现的一部分。另一部分是类Assertion
的定义,它是用值构造的,并且针对该值实现了一组广泛且好的断言方法。像
var o = Assertion(actualValue)
o.equals(expectedValue1)
o.moreThan(expectedValue2)
o.contains(expectedValue3)
和别名以保留英语语法
var o = Assertion(actualValue)
o.equal(expectedValue1)
o.contain(expectedValue3)
和懒惰神枪手的别名,如
o.eql(expectedValue)
o.gt(expectedValue) //greater then
o.gte(...) //greater then or equal
//and so on...
和一些只返回this
的连接符(使用测试值构造的Assertion
的实例),如
o.be
o.and
它给你什么?
var person = getPerson();
Should.exist(person); //that's a static call, and that's easy
//but these are a member calls:
person.should.have("name","age","address","friends");
person.name.should.equal("John");
person.age
.should
.be.number()
.and.be.between(20,30);
person.address
.should
.be.string().and
.startWith("\d").and
.endWith(" st.")
//or even
.and.match(/^[0-9]{1,9}\s+[A-Z][a-z0-9 ]* st\.$/);
person.friends
.should
.be.array().and
.be.between(3,5).and
.containOnlyType(String);
这不是很棒吗?这是简单的英语!
你可以争论缩进的美学,在哪里放and
,如果它们完全是必要的,但除此之外 - 任何人都可以读或写它:
一旦你采用<em>每个对象上存在的'should'属性,但不会破坏地图迭代 - 你可以继续链接任何关于你开始的价值的索赔。
它可以有更多漂亮的迭代工具,反射实用程序,可以使用与对象模型相关的测试函数进行扩充,依此类推,但是让我们来完成第一步:)
但为此,您需要系统中的每个对象都有一个名为should
的不可枚举的智能属性,其中包含 getter < / strong> function返回用Assertion
构造的this
对象作为测试值。
(你还没有看到任何东西 - 等着看它给出的美丽拒绝信息!Yummie !! 所以,是的 - 我很乐意牺牲选择一个属性“应该”...并且也会高兴地放弃知识分子 - 至少只要它是简单的英语)
所以,在评论中, bfavaretto 给了我们第一步 - 我们知道如何防止属性的枚举 - 伟大的&amp;谢谢!
现在,我们可以将其作为getter属性,其功能可以访问this
吗?
当我完成后,我将把它放在麻省理工学院授权的公共仓库中,让我们所有人都玩得开心:)
帮助任何人?
答案 0 :(得分:0)
你的例子实际上是90%正确 - 但是像动作一样定义它,而不是像javascript!
您仍然可以在AS3中定义原型,它们仍然可以像AS2中的原型一样工作。 AS3的唯一区别是编译器。 AVM2由于某种原因没有将原型转换为本机类(虽然我没有测试自定义类)。
原型技巧:将类作为对象进行投射。
例如:如果您创建:
Array.prototype.random = function():void {}
然后创建对象:
var myProtoArray:Array = new Array;
将会发生两件事:
myProtoArray.random()//错误 - 这将失败,AVM2没有将原型映射到数组
但
Object(myProtoArray).random()// WORKS
random()被强制转换为Object类,然后映射到Array - 我不知道为什么!
希望这会有所帮助,欢呼。
答案 1 :(得分:0)
我承认我并不十分熟悉Javascript的工作原理,但如果我正确地理解defineProperties目的,那么它不仅仅是属性的运行时指示,而且还是它所属的关联命名空间(或至少AS3认为是命名空间)。
类属性是预定义的&amp;只能通过自定义get()set()函数或动态修改。一旦编译,它们的命名空间就不能改变(据我所知),所以任何非私有属性都是隐式可枚举的,并且可以修改你是否已经编写了getter / setter(即:foo.a = value
)。 According to Adobe...
您创建的属性是可枚举的,但内置属性是 一般不会列举。
也就是说,您可以使用describeType从类中获取完整的属性列表。可以通过这种方式收集相当多的信息,如果您想要移植Mozilla's recreated defineProperties示例,我怀疑应该满足您的需求。以下是仅打印属性值的示例。
function showProps(obj:*):void {
var desc:XML= describeType(obj);
// public vars
for each (var n:XML in desc.variable){
trace(n.@name + ": " + obj[n.@name]);
}
// getters
for each (n in desc.accessor){
try {
trace(n.@name + ": " + obj[n.@name]);
} catch (error:Error) {
trace("Unable to read write-only property.");
}
}
}
我希望这会有所帮助,但我确定我并不完全理解你想要完成的事情。如果你能详细说明,那就不胜感激了。
答案 2 :(得分:0)
好的,伙计们,感谢所有帮助,22岁以上 我会给那些对原始问题感兴趣的人做一个总结,之后 - 我会告诉你我努力的结果。
挑战由两部分组成:
1 - 防止枚举增强(=运行时添加)属性
至于第一部分 - 感谢@bfavaretto,对问题级别发表了评论 - Object.setPropertyIsEnumerable
- 这个技巧很棒。
2 - 使扩充属性运行一个可以访问this
的getter函数,以便它可以在返回值的构造函数上使用它。
关于第二部分 - 基本上 - 我找不到一种方法来增加(=添加)一个属性getter到一个原型,让它通过继承树来操作它们的API。
无论如何,在这些限制范围内 - 结果如下:
由于平台差异,不准确移植, 我还有一些方法可以赶上原来的should.js(比如HTTP测试方法) 但足够接近。 主要区别在于
var o:Object =
{ name : "Radagast"
, color: "Brown"
}
o.should.have.properties("name","color")
.and.have.property("name","Radagast");
o.name.should.not.equal("Palandoo");
o.color.should.equal("Brown");
你必须去
o.should().have.properties("name","color")
and.have.property("name","Radagast");
o.name.should().not.equal("Palandoo");
o.color.should().equal("Brown");
(括号 - 没有可能的getter - 所以should属性是一个方法,你必须自己调用它)
现在,如果您遇到困难并需要智能感知的帮助,您必须这样做:
var should:tdd.Should = o.color.should();
should. <ctrl+space>
哪种有点刺痛,但是为了窥探知识分子 - 它有帮助
还有一件事 - 你必须尽快强制执行We的静态构造函数, 例如,我在这里做:
[Suite]
[RunWith("org.flexunit.runners.Suite")]
public class my_awsome_test_suite
{
//forces the static constructor of tdd.Should
import tdd.Should;
private static var s:Should = new Should();
public var c1:testCase1;
public var c2:testCase2;
public var c3:testCase3;
public var c4:testCase4;
}
我可能会稍后添加一些propper README.md,并将更多令人敬畏的成员函数添加到tdd.Should
玩得开心