Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/html/85.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 用TypeScript扩展Object.prototype_Javascript_Object_Interface_Prototype_Typescript - Fatal编程技术网

Javascript 用TypeScript扩展Object.prototype

Javascript 用TypeScript扩展Object.prototype,javascript,object,interface,prototype,typescript,Javascript,Object,Interface,Prototype,Typescript,我目前正在开发一个TypeScript API,它需要绑定到对象原型(Object.prototype)的一些附加功能 考虑以下代码: class Foo { } interface Object { GetFoo(): Foo; GetFooAsString(): string; } //This is problematic... Object.prototype.GetFoo = function() { return new Foo(); // No

我目前正在开发一个TypeScript API,它需要绑定到对象原型(Object.prototype)的一些附加功能

考虑以下代码:

class Foo {

}

interface Object {
    GetFoo(): Foo;
    GetFooAsString(): string;
}

//This is problematic...
Object.prototype.GetFoo = function() {
    return new Foo();
    // Note, this line is just for testing...I don't want my function to just return a blank instance of Foo!
}

//This is ok.
Object.prototype.GetFooAsString = function () {
    return this.GetFoo().toString();
}
你可能想直接在办公室试试这个

如您所见,我有一个名为
Foo
(不是我将使用的实际对象名称)的类。我还扩展了
对象
接口,以包括两个新功能。最后,我针对
原型
实现了这些函数(这些函数在纯JavaScript中工作,只是TypeScript有问题)

在我注释“//这是有问题的…”的地方,TypeScript用红色波浪线突出显示,并显示以下错误:

Cannot convert '() => Foo' to '{ (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; }': Call signatures of types '() => Foo' and '{ (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; (): Foo; }' are incompatible
() => Foo
要么这只是一个TypeScript错误(我知道它仍处于开发阶段,所以很多错误需要解决,我已经在CodePlex上演示了其中的一些),要么我遗漏了一些东西

为什么我会遇到这个问题


如果不是TypeScript错误,我如何修复它?

此错误在TS 0.9.0 alpha中修复,如下所示:

操场仍在以0.8.3的速度运行

这主要是因为一些关键接口(对象、数字、字符串)上的方法作为性能优化得到缓存

如果你运行这个。第一次加载时,您不会看到该错误

一旦您对代码进行编辑,解析器就会再次检查代码,因为它缓存了旧的接口定义,因此会看到重复的函数定义,然后有效地崩溃。对该文件所做的编辑越多,错误语句将变得越复杂

我以前有:

// See if an array contains an object
Array.prototype.contains = function (obj) {
    var i = this.length;
    while (i--) {
        if (this[i] === obj) {
            return true;
        }
    }
    return false;
}
为了使用typescript编译代码,我添加了以下行:

interface Array {
    contains(obj: Object): boolean;
}

谢谢

我以同样的方式扩展了数组,当一方使用
for I in…
循环它时,我遇到了一个大问题。现在,您无法控制每一个第三方代码,这些bug可能会变得非常烦人,因此我建议您使用更好的方法:

interface Array<T> {
   crandom(): T;
}

/** Retrieve a random element from the list */
 Object.defineProperty(Array.prototype, 'crandom', { value: function() {

    let index = Math.floor(Math.random() * this.length);

    return this[index];
}
});

使用
Object.defineProperty
可以更好地控制此创建,还可以添加其他限制

好极了!很高兴这不是因为糟糕的编码……至少不是因为我;-)不包含(obj:any):布尔值;在这里更合适吗?注意:我必须在这里使用
接口数组
,否则我会得到“错误TS2428:接口的所有声明必须具有相同的类型参数”。如何使用
导入
?正是这样。它允许您控制它的枚举和不变性,但是社区不赞成在现有对象(如数组、字符串、数字等)上添加或覆盖功能。您可能会发现,当使用defineProperty和writable:false时,您的代码可以正常工作,因为第三方代码无法覆盖您的代码。好的一点,我不同意人们不赞成它,因为在功能应该存在但不存在的情况下,扩展基类可能非常好(例如数组上的
随机
方法)。只要您编写的库不是供他人使用的,我个人认为扩展库没有问题,因为它的使用是适度的,不会过度使用。当ECMAScript委员会批准在这些对象上实现新功能的标准时会发生什么,但是你已经用相同的名字和不同的行为添加了你自己的功能?你的库突然死亡,因为它不兼容。PrototypeJS就是一个著名的例子,这正是为什么我提到用这种方式创建库不好的原因,我用前缀命名我的方法,比如
crandom
,而不是
random
,只是不要在任何需要加密强大的随机性或重要资源的上下文中使用
Math.random()(如真钱)处于危险之中。
Math.random()
可被利用,且加密性不强。请参阅。在在线洗牌游戏中使用此选项将是一个坏主意,或者在任何情况下,攻击者可能会利用预测下一个值的能力来实现不公平或恶意的结果。
Object.defineProperty(Array.prototype, 'popRandom', { value: function() {

    let index = Math.floor(Math.random() * this.length);

    let result = this[index];
    this.splice(index, 1);

    return result;
}
});