this是Javascript语言的一个关键字
随着函数使用场合的不同,this的值会发生变化:
- 如果是一般函数,this指向全局对象window;
- 在严格模式下"use strict",为undefined;
- 对象的方法里调用,this指向调用该方法的对象;
- 构造函数里的this,指向创建出来的实例。
但this一般是指向调用它的那个对象
改变this指向的方式: call、apply和bind
call和apply实现思路:
- 判断是否为函数调用,否则抛出异常;
- 通过新对象(context)来调用函数;
- 给context创建一个fn设置为需要调用的函数;
- 结束调用完之后删除fn。
call:
Function.prototype.myCall = function(context) {
//判断调用myCall是不是一个函数
if(typeof this !== 'function') {//this ——> 调用myCall的
throw new TypeError('Not a Function');
}
//当不传入参数时,默认为window
context = context || window;
context.fn = this;//保存this
let args = Array.from(arguments).slice(1);//保存参数
let result = context.fn(...args);//调用函数
delete context.fn;
return result;
}
调用
function Product(name, price) {
this.name = name;
this.price = price;
}
function Food(name, price) {
Product.myCall(this, name, price);
this.category = 'food';
}
console.log(new Food('cheese', 5).name);//"cheese"
apply:
Function.prototype.myApply = function(context) {
//判断this是否为function
if(typeof this !== 'function') {
throw new TypeError("Not a Function");
}
let result;
//默认调用时window
context = context || window;
context.fn = this;//保存this
//保存参数
if(arguments[1]){
result = context.fn(...arguments[1]);
}else {
result = context.fn();
}
delete context.fn;
return result;
}
调用:
const numbers = [1, 2, 3, 4, 5];
const max = Math.max.MyApply(null, numbers);
console.log(max);//5
bind实现思路:
- 判断是否为函数调用,否则抛出异常;
- 返回函数
- 判断函数的调用方式,是否是new出来的;
- new出来的话返回空对象,否则实例的__proto__指向_this的原型对象- 完成函数柯里化
- Array.prototype.slice.call()。
Function.prototype.myBind = function(context) {
if(typeof this != 'function') {
throw new TypeError("Not a Function");
}
let _this = this;//保存调用bind的函数
let args = Array.prototype.slice.call(arguments, 1);//保存参数
//返回一个新的函数
return function Fn() {
if(this instanceof Fn) {//判断是否是new出来的
//如果是new出来的,就返回一个空对象,且使创建出来的实例的__proto__指向_this的原型,完成函数柯里化
return new _this(...args, ...arguments);
}else{
//如果不是new出来的,就改变this指向,完成函数柯里化
return _this.apply(context, args.concat(...arguments));
}
}
}