Angular中typescript的this问题
1. 例子
在使用Angular的时候封装一个http请求模块,具体代码如下:
import { Injectable } from '@angular/core';
import { HttpClient, HttpParams, HttpHeaders, HttpErrorResponse } from '@angular/common/http';
import { throwError, Observable } from 'rxjs';
import { catchError } from 'rxjs/operators';
import { MsgService } from './confirm.service';
@Injectable({
providedIn: 'root'
})
export class HttpService {
constructor(private http: HttpClient, private msgService: MsgService) { }
/**
*
*http错误捕捉
* @param {HttpErrorResponse} error
* @returns
* @memberof HttpService
*/
handleError(error: HttpErrorResponse) {
if (error.error instanceof ErrorEvent) {
// A client-side or network error occurred. Handle it accordingly.
console.log(error.error.message);
// 发生客户端或者网络错误提醒用户
} else {
console.log(this);
this.msgService.msgError( `请求失败,错误代码为${error.status}`);
console.error(
`Backend returned code ${error.status}, ` +
`body was: ${error.error}`);
}
return throwError(
'Something bad happened; please try again later.');
}
// 也可以统一设置请求头
// get请求,参数为url,有参数的第二个为请求参数
httpGet(url: string, myParams?: any): Observable<any> {
const option = myParams ? { params: new HttpParams({ fromObject: myParams })} : {};
return this.http.get(url, option).pipe(
catchError(this.handleError)
);
}
// post请求
httpPost(url: string, body: any | null, myparams?: any): Observable<any> {
const options = myparams ? { params: new HttpParams({ fromObject: myparams }) } : {};
return this.http.post(url, null, options).pipe(
catchError(this.handleError)
);
}
// 文件上传
}
主要看handleError函数,它是服务类的一个方法,然后在catchError里面作为回调函数,本来我们是希望handleError里的this指代它的对象也就是HttpService
,但是结果去让人失望,所以当请求失败的时候就不会出现弹出框,打印出来的this指代的是调用该函数时的上下文。那么如何解决呢,我们知道在es6中的箭头函数能保存函数创建时的 this值,而不是调用时的值,所以我们可以将handleError函数修改。
解决方法
将handleError函数修改成
handleError = (error: HttpErrorResponse) => {
if (error.error instanceof ErrorEvent) {
// A client-side or network error occurred. Handle it accordingly.
console.log(error.error.message);
// 发生客户端或者网络错误提醒用户
} else {
console.log(this);
this.msgService.msgError( `请求失败,错误代码为${error.status}`);
console.error(
`Backend returned code ${error.status}, ` +
`body was: ${error.error}`);
}
return throwError(
'Something bad happened; please try again later.');
}
2. javascript中的this拓展
this 是在运行时进行绑定的,并不是在编写时绑定,它的上下文取决于函数调 用时的各种条件。this 的绑定和函数声明的位置没有任何关系,只取决于函数的调用方式。
2.1 调用位置
this 是在运行时进行绑定的,并不是在编写时绑定,它的上下文取决于函数调 用时的各种条件。this 的绑定和函数声明的位置没有任何关系,只取决于函数的调用方式.
eg:
function baz() { // 当前调用栈是:baz // 因此,当前调用位置是全局作用域
console.log( "baz" ); bar(); // <-- bar 的调用位置
}
function bar() {
// 当前调用栈是 baz -> bar // 因此,当前调用位置在 baz 中
console.log( "bar" ); foo(); // <-- foo 的调用位置
}
function foo() { // 当前调用栈是 baz -> bar -> foo // 因此,当前调用位置在 bar 中
console.log( "foo" );
}
baz(); // <-- baz 的调用位置
2.2 绑定规则
2.1 默认绑定
在严格模式下绑定到 undefined,否则绑定到全局对象当this不符合其他绑定规则时默认就是window,比如说
function foo() {
console.log( this.a );
}
var a = 2;
foo(); // 最后结果就是2,this则指代的是window
2.2 隐式绑定
函数引 用有上下文对象时,隐式绑定规则会把函数调用中的 this 绑定到这个上下文对象,比如说:
function foo() {
console.log( this.a );
}
var obj2 = { a: 42, foo: foo };
var obj1 = { a: 2, obj2: obj2 };
obj1.obj2.foo(); // 42
2.3 显示绑定
显示绑定主要是使用call,apply显示的绑定this的指向,它们的第一个参数是一个对象,它们会把这个对象绑定到 this,接着在调用函数时指定这个 this。因为你可以直接指定 this 的绑定对象,因此我 们称之为显式绑定。
eg:
function foo() { console.log( this.a ); }
var obj = { a:2 };
foo.call( obj ); // 2
另外哈有bind也可以硬绑定this:
function foo(something) {
console.log( this.a, something);
return this.a + something;
}
var obj = { a:2 };
var bar = foo.bind( obj );
var b = bar( 3 ); // 2 3
console.log( b ); // 5
2.4 new绑定
使用 new 来调用函数,或者说发生构造函数调用时,会自动执行下面的操作。
- 创建(或者说构造)一个全新的对象。
- 这个新对象会被执行 [[ 原型 ]] 连接。
- 这个新对象会绑定到函数调用的 this
- 如果函数没有返回其他对象,那么 new 表达式中的函数调用会自动返回这个新对象。
function foo(a) { this.a = a; }
var bar = new foo(2);
console.log(bar.a); // 2
使用 new 来调用 foo(…) 时,我们会构造一个新对象并把它绑定到 foo(…) 调用中的 this 上。new 是最后一种可以影响函数调用时 this 绑定行为的方法,我们称之为 new 绑定.