Tha*_*you 71 javascript constructor instance ecmascript-6
给出一个简单的类
class Foo {
constructor(x) {
if (!(this instanceof Foo)) return new Foo(x);
this.x = x;
}
hello() {
return `hello ${this.x}`;
}
}
Run Code Online (Sandbox Code Playgroud)
是否可以在没有new
关键字的情况下调用类构造函数?
用法应该允许
(new Foo("world")).hello(); // "hello world"
Run Code Online (Sandbox Code Playgroud)
要么
Foo("world").hello(); // "hello world"
Run Code Online (Sandbox Code Playgroud)
但后者失败了
Cannot call a class as a function
Run Code Online (Sandbox Code Playgroud)
ade*_*neo 38
类有一个"类体",它是一个构造函数.
如果使用内部constructor()
函数,那么该函数也将是同一个类体,并且将在调用类时调用,因此类始终是构造函数.
构造函数需要使用的new
运算符来创建一个新的实例,因此调用类没有new
一个错误操作的结果,因为它需要的类的构造函数来创建一个新的实例.
错误消息也非常具体,而且正确
TypeError:没有'new'时不能调用类构造函数
你可以;
new
.new
,这样你就可以获得类的好处,但是使用和不使用new
运算符2仍然可以调用包装函数.1)
function Foo(x) {
if (!(this instanceof Foo)) return new Foo(x);
this.x = x;
this.hello = function() {
return this.x;
}
}
Run Code Online (Sandbox Code Playgroud)
2)
class Foo {
constructor(x) {
this.x = x;
}
hello() {
return `hello ${this.x}`;
}
}
var _old = Foo;
Foo = function(...args) { return new _old(...args) };
Run Code Online (Sandbox Code Playgroud)
小智 29
正如其他人已经指出的那样,ES2015规范严格规定这样的调用应该抛出TypeError,但同时它提供了可用于实现精确所需结果的特性,即Proxies.
代理允许我们虚拟化对象的概念.例如,它们可用于更改特定对象的某些行为,而不会影响其他任何内容.
在您的特定使用案例class Foo
是Function object
可以称之为-这通常意味着该函数的身体将被执行.但这可以通过以下方式改变Proxy
:
const _Foo = new Proxy(Foo, {
// target = Foo
apply (target, thisArg, argumentsList) {
return new target(...argumentsList);
}
});
_Foo("world").hello();
const f = _Foo("world");
f instanceof Foo; // true
f instanceof _Foo; // true
Run Code Online (Sandbox Code Playgroud)
(注意,_Foo
现在是您要公开的类,因此标识符可能应该是另一种方式)
如果由支持Proxies的浏览器运行,则调用_Foo(...)
现在将执行apply
陷阱功能而不是orignal构造函数.
同时,这个"新" _Foo
类与原始类无法区分Foo
(除了能够将其称为正常函数).类似地,你可以告诉使用Foo
和创建的对象没有区别_Foo
.
这方面的最大缺点是它无法被发现或被pollyfilled,但仍然是其可行的解决方案,以便将来在JS中应用类似Scala的类.
Tha*_*you 23
这是我遇到的一种模式,真的对我很有帮助.它不使用a class
,但它不需要使用new
任何一个.赢/赢.
const Foo = x => ({
x,
hello: () => `hello ${x}`,
increment: () => Foo(x + 1),
add: ({x: y}) => Foo(x + y)
})
console.log(Foo(1).x) // 1
console.log(Foo(1).hello()) // hello 1
console.log(Foo(1).increment().hello()) // hello 2
console.log(Foo(1).add(Foo(2)).hello()) // hello 3
Run Code Online (Sandbox Code Playgroud)
Ber*_*rgi 14
不,这是不可能的.正在使用所创建的构造class
关键字只能与构造new
,如果它们是[[呼叫]] ED而不他们总是throw
一个TypeError
1(和甚至有不从外部检测到该一个方式).
1:我不确定转发器是否正确
但是,您可以使用普通函数作为变通方法:
class Foo {
constructor(x) {
this.x = x;
}
hello() {
return `hello ${this.x}`;
}
}
{
const _Foo = Foo;
Foo = function(...args) {
return new _Foo(...args);
};
Foo.prototype = _Foo.prototype;
}
Run Code Online (Sandbox Code Playgroud)
免责声明:instanceof
并且Foo.prototype
正常扩展工作,Foo.length
没有,.constructor
静态方法不能,但可以通过添加Foo.prototype.constructor = Foo;
和修复(Object.setPrototypeOf(Foo, _Foo)
如果需要)来修复.
对于子类化Foo
(非_Foo
)class Bar extends Foo …
,您应该使用return Reflect.construct(_Foo, args, new.target)
而不是new _Foo
调用.Foo.call(this, …)
无法使用ES5样式(带)进行子类化.
class MyClass {
constructor(param) {
// ...
}
static create(param) {
return new MyClass(param);
}
doSomething() {
// ...
}
}
MyClass.create('Hello World').doSomething();
Run Code Online (Sandbox Code Playgroud)
那是你要的吗?
如果在创建新实例时需要一些逻辑MyClass
,那么实现"CreationStrategy"可能会有所帮助,以超越逻辑:
class MyClassCreationStrategy {
static create(param) {
let instance = new MyClass();
if (!param) {
// eg. handle empty param
}
instance.setParam(param);
return instance;
}
}
class DefaultCreationStrategy {
static create(classConstruct) {
return new classConstruct();
}
}
MyClassCreationStrategy.create(param).doSomething();
DefaultCreationStrategy.create(MyClass).doSomething();
Run Code Online (Sandbox Code Playgroud)
我刚给你做了这个npm模块;)
https://www.npmjs.com/package/classy-decorator
import classy from "classy-decorator";
@classy()
class IamClassy {
constructor() {
console.log("IamClassy Instance!");
}
}
console.log(new IamClassy() instanceof IamClassy); // true
console.log(IamClassy() instanceof IamClassy); // true
Run Code Online (Sandbox Code Playgroud)
Here's a where you can use a 'scope safe constructor' Observe this code:
function Student(name) {
if(this instanceof Student) {
this.name = name;
} else {
return new Student(name);
}
}
Run Code Online (Sandbox Code Playgroud)
Now you can create a Student object without using new as follows:
var stud1 = Student('Kia');
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
57977 次 |
最近记录: |