为什么我不能这样做?是由于Javascript / Typescript的技术限制,还是由Typescript的开发人员做出的设计决定?这个相同的代码在Java或C#中可以正常工作。
class Test {
static str: string = "test";
public static getTest(): string {
return this.str;
}
}
//works as expected
console.log(Test.getTest());
//won't compile
var test: Test = new Test();
console.log(test.getTest());
答案 0 :(得分:3)
但我仍然想知道原因。
少魔法。 Class
非实例上存在静态属性。它清楚地知道从代码调用的是什么,而不是在运行时魔术绑定到类或成员函数。
是由于Javascript / Typescript的技术限制,还是由Typescript的开发人员做出的设计决定
不是技术限制。一个设计决定。更多地与ES6保持一致:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes/static但是在那里它决定了更少的魔法
答案 1 :(得分:0)
正如@basarat所说,这只是设计决定,而不是技术限制。
实际上,即使像Java或C#一样无法访问test.getTest()
,也可以通过以下方式进行访问:
Object.getPrototypeOf()(替换为现在已弃用的Object.prototype.__proto__
)或Object.prototype.constructor
均应起作用:
Object.getPrototypeOf(test).constructor.getTest();
test.constructor.getTest();
实际上:
Object.getPrototypeOf(test).constructor === test.constructor; // true
在这里您可以看到正在编译的源代码:
class Test {
static getTest() {
return this.str;
}
}
Test.str = 'test';
const test = new Test();
console.log(Object.getPrototypeOf(test).constructor.getTest());
console.log(test.constructor.getTest());
console.log(Object.getPrototypeOf(test).constructor === test.constructor);
console.log(Object.getPrototypeOf(test) === Test.prototype);
请注意,静态属性存在于类中,但不存在于实例中。
因此,如果您想从test
转到其原型,则应该调用Object.getPrototypeOf(test)
,而不是test.prototype
,这是完全不同的事情。
.prototype
属性仅存在于函数中,并且在使用new
实例化新对象并调用该构造函数(new Test()
)时,它将成为新创建的对象的原型(已弃用的.__proto__
)。
在您的示例中:
test.prototype; // undefined
Test; // class Test { static getTest() { ... } }
Test.protoype; // { constructor: class Test { ... } }
Test.protoype.constructor; // class Test { static getTest() { ... } }
Test.protoype.constructor === Test; // true
test.constructor; // class Test { static getTest() { ... } }
test.constructor === Test; // true
Object.getPrototypeOf(test) === Test.prototype; // true