this指向及call、apply和bind

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));
    }
  }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值