this指向问题:
- 默认情况下,this指向window;
- 严格模式下,this值为undefined;
- 在事件回调函数中,this指向事件源;
- 箭头函数本身没有this,会向最外层查找,如果找不到就指向window;
- 在构造函数中,this指向构造函数创建的对象实例;
- 在Vue2框架中,this指向组件实例;
- 在对象的方法中,this指向当前对象;
如何改变this指向: 使用call、bind、apply;
call的重写:
var a = 123;
function f1(...arg) {
const a = this.a;
const obj = {
src: this,
a,
arg: [...arg]
}
return obj;
}
const obj = {
a: 1
}
Function.prototype.callFn = function(reidrectObj, ...arg) {
const symbol = Symbol('_fn')
reidrectObj[symbol] = this;
const result = reidrectObj[symbol](...arg);
Reflect.deleteProperty(reidrectObj, symbol);
return result;
}
console.log(f1.callFn(obj, 8))
/*
输出结果:
{
a: 1,
arg: [8],
src: {
a: 1
}
}
*/
console.log(f1(9))
/*
输出结果:
{
a: 123,
arg: [9],
src: window { window: Window, self: Window, document: document, name: '', location: Location, ... }
}
*/
bind的重写:
var a = 123;
function f1(...arg) {
const a = this.a;
const obj = {
src: this,
a,
arg: [...arg]
}
return obj;
}
const obj = {
a: 1
}
Function.prototype.bindFn = function (reidrectObj) {
const symbol = Symbol('_fn')
reidrectObj[symbol] = this;
return reidrectObj[symbol];
}
console.log(f1.bindFn(obj)(123, 456), obj)
/*
输出结果:
{
a: 123,
arg: [123,456],
src: window { window: Window, self: Window, document: document, name: '', location: Location, ... }
}
*/
apply的重写:
var a = 123;
function f1(...arg) {
const a = this.a;
const obj = {
src: this,
a,
arg: [...arg]
}
return obj;
}
const obj = {
a: 1
}
Function.prototype.applyFn = function(reidrectObj, arg = []) {
const symbol = Symbol('_fn')
const v = Array.isArray(arg) ? arg : [];
let argList = [];
if(Array.isArray(arg)) {
argList = arg;
} else {
if(typeof arg === 'object') {
if (!arg) {
throw new Error('CreateListFromArrayLike called on non-object');
}
argList = Array.from(arg);
}
}
reidrectObj[symbol] = this;
const result = reidrectObj[symbol](...argList);
Reflect.deleteProperty(reidrectObj, symbol);
return result;
}
console.log(f1.applyFn(obj, [1,2,3]))
/*
输出结果:
{
a: 1,
arg: [1, 2, 3],
src: {
a: 1
}
}
*/
console.log(f1([9]))
/*
输出结果:
{
a: 123,
arg: [[9]],
src: window { window: Window, self: Window, document: document, name: '', location: Location, ... }
}
*/