我正在构建一个可操作的运算符,但发现自己对方法的这两种排列之间的确切区别一无所知。一种有效,另一种无效。
export class CrudService {
constructor(private datastore: DatastoreService,
private http: HttpClient) { }
// Making the operator an attribute on the object
// instance allows `this.datastore` to work as expected ✅
upsertResponse = (source: any) =>
source.pipe(
map((data: any) => {
this.datastore.validate_and_upsert(data)
return true
})
)
}
export class CrudService {
constructor(private datastore: DatastoreService,
private http: HttpClient) { }
// Making the operator an instance method means that
// `this.datastore` throws an error ❌
upsertResponse(source: any){
return source.pipe(
map((data: any) => {
this.datastore.validate_and_upsert(data)
return true
})
)
}
}
为什么this.datastore.validate_and_upsert
在一个而不是另一个中起作用?
该问题已被重新表述,以使其更加关注导致问题的原因。
答案 0 :(得分:3)
它们都是可管道的,但是只有一个可以访问该类的this
上下文。我猜你可以猜到哪一个。一个作为属性。使用.bind(this)
可以解决此问题:
readonly obs$ = this.http.get().pipe(
this.upsertResponse.bind(this)
);
upsertResponse<T>(source: Observable<T>){
return source.pipe(
tap((data) => this.datastore.validate_and_upsert(data)),
mapTo(true)
);
}
或仅使用整个可观察对象作为源,但是它不再是管道:
readonly obs$ = this.upsertResponse(this.http.get());
但是从观点来看,我相信您提出问题的属性方式会更好。
readonly upsertResponse = //...;
这样,您不必担心此上下文,很明显,该方法是实用程序方法。
费耶,添加事件侦听器时也会发生同样的事情,在那里您可以使用匿名箭头函数来解决它,这不是可管道运算符的选项:document.addEventListener('click', (event) => this.upsertEvent(event));
通过测试课程更深入地了解
:如果您有此类:
class TestClass {
readonly attributeMethod = () => {
this.executeThis()
};
functionMethod() {
this.executeThis();
}
executeThis() {
console.log('hi');
}
constructor() {
document.addEventListener('click', this.functionMethod);
document.addEventListener('click', this.attributeMethod);
}
}
不幸的是,这将转换为ES5的角度,这将导致:
"use strict";
var TestClass = /** @class */ (function () {
function TestClass() {
var _this = this;
this.attributeMethod = function () {
_this.executeThis();
};
document.addEventListener('click', this.functionMethod);
document.addEventListener('click', this.attributeMethod);
}
TestClass.prototype.functionMethod = function () {
this.executeThis();
};
TestClass.prototype.executeThis = function () {
console.log('hi');
};
return TestClass;
}());
您可以看到functionMethod
被放置在prototype
上,并且attributeMethod
在TestClass
构造函数中。但是,只有attributeMethod
可以通过使用this
来访问类的_this = this
。
因此,当您将functionMethod
引用作为回调方法传递时,无论实际执行该方法的内容如何,都会调用此方法。对attributeMethod
的引用发生了相同的事情,不同之处在于attributeMethod
的范围内有_this = this
。