- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
假设您有一个装饰器来跟踪它装饰了哪些字段:
interface FieldTracker {
fields: string[];
}
const decorator = <T extends FieldTracker>(target: T, fieldName: string) => {
target.fields = target.fields || [];
target.fields.push(fieldName);
};
然后假设您创建了一个使用该装饰器的抽象 Base
类:
abstract class Base implements FieldTracker {
fields: string[];
@decorator
a: string = 'a';
}
然后您创建两个扩展 Base
类的类。
class FirstClass extends Base {
@decorator
b: string = 'b';
}
class SecondClass extends Base {
@decorator
c: string = 'c';
}
在实例化 SecondClass
时,它的 fields
将包含在 FirstClass
中修饰的字段:
const secondInstance = new SecondClass();
expect(secondInstance.fields).toEqual(['a', 'c']);
这导致:
Expected value to equal:
["a", "c"]
Received:
["a", "b", "c"]
如果我将参数记录到 decorator
,我得到:
target: Base {}, fieldName: 'a'
target: FirstClass {}, fieldName: 'b'
目标:SecondClass {},fieldName:'c'
请注意,Base
是抽象的
,无法实例化。 target
如何成为它的一个实例?
请注意,我什至从未实例化过 FirstClass
。 target
如何成为它的一个实例?
如果我不在 Base
上使用 decorator
,则不会发生这种情况。这意味着 fields
在 Base.prototype
上,这似乎不应该存在。
最佳答案
这里有点困惑。
Base
类的抽象
性质意味着,如果您尝试直接构造 Base< 的实例,编译器将会对您大喊大叫
与它。它仍然具有类构造器的所有功能,包括拥有一个原型(prototype)
。如果您在 the TypeScript Playground 检查您的代码发出的 JavaScript,您可以看到这一点。 .
装饰器作用于每个类构造函数的prototype
(所以当你装饰Base
时,它正在修改Base.prototype
).它不(直接)作用于该类的任何实例。对于您装饰的每个类,装饰器只被调用一次。
子类的原型(prototype)
inherits from父类(super class)的 prototype
。这样,子类实例的原型(prototype)链包括子类构造函数的 prototype
以及父类(super class)构造函数的 prototype
。
如果您将一个数组赋值给一个变量,您并不是在复制数组的内容;只有一个数组对象,您从一个变量对其所做的任何更改都将在另一个变量中可见。
话虽如此,让我们检查一下您的装饰器:
const decorator = <T extends FieldTracker>(target: T, fieldName: string) => {
target.fields = target.fields || []; // hmm
target.fields.push(fieldName);
};
在标记为 //hmm
的行中,您正在检查传入的 prototype
对象的 fields
属性。对于 Base.prototype
,这将不存在并将被初始化为一个新的空数组。对于 FirstClass.prototype
,这不会被直接找到,但由于 FirstClass.prototype
继承自 Base.prototype
,它会在那里找到。通过将 FirstClass.prototype.fields
设置为 Base.prototype.fields
,您将属性直接添加到 FirstClass.prototype
,但值是与 Base.prototype
相同的数组对象。当您将值推送到 FirstClass.prototype.fields
时,您也会在 Base.prototype.fields
上看到更改。对于 SecondClass.prototype.fields
也是类似的。
这意味着你得到了不良行为:
console.log(Base.prototype.fields); // Array [ "a", "b", "c" ]
console.log(FirstClass.prototype.fields); // Array [ "a", "b", "c" ]
console.log(SecondClass.prototype.fields); // Array [ "a", "b", "c" ]
解决这个问题很简单;不要复制数组引用,而是将其内容复制到一个新数组。最简单的方法是使用原始数组的 slice()
method :
const decorator = <T extends FieldTracker>(target: T, fieldName: string) => {
target.fields = (target.fields || []).slice(); // all better
target.fields.push(fieldName);
};
现在,如果您运行上面的代码,测试应该会通过。具体来说,您应该看到:
console.log(Base.prototype.fields); // Array [ "a" ]
console.log(FirstClass.prototype.fields); // Array [ "a", "b" ]
console.log(SecondClass.prototype.fields); // Array [ "a", "c" ]
希望对您有所帮助;祝你好运!
关于typescript - 为什么基类上的 TypeScript 装饰器会导致扩展相互影响?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48122319/
我正在尝试使用 Spark 从 Cassandra 读取数据。 DataFrame rdf = sqlContext.read().option("keyspace", "readypulse
这是代码: void i_log_ (int error, const char * file, int line, const char * fmt, ...) { /* Get erro
我必须调试一个严重依赖 Gtk 的程序。问题是由于某些原因,在使用 GtkWindow 对象时开始出现许多运行时警告。问题是,即使 Gtk 提示严重错误,它也不会因这些错误而中止。我没有代码库的更改历
我正在尝试从已有效编译和链接的程序中检索二进制文件。我已经通过 GL_PROGRAM_BINARY_LENGTH 收到了它的长度。该文档说有两个实例可能会发生 GL_INVALID_OPERATION
我有一个托管在 Azure 环境中的服务。我正在使用控制台应用程序使用该服务。这样做时,我得到了异常: "The requested service, 'http://xxxx-d.yyyy.be/S
我有以下代码,它被 SEGV 信号杀死。使用调试器表明它被 main() 中的第一个 sem_init() 杀死。如果我注释掉第一个 sem_init() ,第二个会导致同样的问题。我试图弄清楚是什么
目前我正在编写一个应用程序(目标 iOS 6,启用 ARC),它使用 JSON 进行数据传输,使用核心数据进行持久存储。 JSON 数据由 PHP 脚本通过 json_encode 从 MySQL 数
我对 Xamarin.Forms 还是很陌生。我在出现的主页上有一个非常简单的功能 async public Task BaseAppearing() { if (UserID
这是我的代码的简化版本。 public class MainActivity extends ActionBarActivity { private ArrayList entry = new Arr
我想弄明白为什么我的两个 Java 库很难很好地协同工作。这是场景: 库 1 有一个类 A,其构造函数如下: public A(Object obj) { /* boilerplate */ } 在以
如果网站不需要身份验证,我的代码可以正常工作,如果需要,则在打印“已创建凭据”后会立即出现 EXC_BAD_ACCESS 错误。我不会发布任何内容,并且此代码是直接从文档中复制的 - 知道出了什么问题
我在使用 NSArray 填充 UITableView 时遇到问题。我确信我正在做一些愚蠢的事情,但我无法弄清楚。当我尝试进行简单的计数时,我得到了 EXC_BAD_ACCESS,我知道这是因为我试图
我在 UITableViewCell 上有一个 UITextField,在另一个单元格上有一个按钮。 我单击 UITextField(出现键盘)。 UITextField 调用了以下方法: - (BO
我有一个应用程序出现间歇性崩溃。崩溃日志显示了一个堆栈跟踪,这对我来说很难破译,因此希望其他人看到了这一点并能为我指出正确的方向。 基本上,应用程序在启动时执行反向地理编码请求,以在标签中显示用户的位
我开发了一个 CGImage,当程序使用以下命令将其显示在屏幕上时它工作正常: [output_view.layer performSelectorOnMainThread:@selector(set
我正在使用新的 EncryptedSharedPreferences以谷歌推荐的方式上课: private fun securePrefs(context: Context): SharedPrefe
我有一个中继器,里面有一些控件,其中一个是文本框。我正在尝试使用 jquery 获取文本框,我的代码如下所示: $("#").click(function (event) {}); 但我总是得到 nu
在以下场景中观察到 TTS 初始化错误,太随机了。 已安装 TTS 引擎,存在语音集,并且可以从辅助功能选项中播放示例 tts。 TTS 初始化在之前初始化和播放的同一设备上随机失败。 在不同的设备(
maven pom.xml org.openjdk.jol jol-core 0.10 Java 类: public class MyObjectData { pr
在不担心冲突的情况下,可以使用 MD5 作为哈希值,字符串长度最多为多少? 这可能是通过为特定字符集中的每个可能的字符串生成 MD5 哈希来计算的,长度不断增加,直到哈希第二次出现(冲突)。没有冲突的
我是一名优秀的程序员,十分优秀!