一、概述
我们都知道call、apply、bind的作用是改变某个函数运行时的上下文(context),也就是改变函数内部this指向。new操作符通过把this固化在实例对象上改变this的指向。本文从this的指向出发重点研究call、apply、bind以及new的使用方法,以及它们内部的实现原理。二、this指向
使用 JavaScript 开发的时候,很多开发者多多少少会被 this 的指向搞蒙圈。没有弄清楚this的指向到底是什么,所以在某些情况下,this得到的不是我们想要的值。本节内容就来分析一下函数中this指向的问题,在此分享出来也方便自己今后巩固学习。函数分为普通函数和箭头函数,它们的this指向可以总结为以下情况。1、普通函数中this
(1) 默认情况下,没有直接调用者,this指向window。

(2)总是代表着它的直接调用者,如obj.foo,this就是指向obj。

(3)严格模式下(设置了'use strict'),this为undefined。

(4)当使用call,apply,bind绑定的,this指向绑定对象。

(5)对于new 的方式来说,this永远被绑定在实例化对象上。不会被任何方式改变。
2、箭头函数中this
(1)箭头函数没有自己的this, 它的this是继承而来; 默认指向在定义它时所处的对象(宿主对象),而不是执行时的对象, 定义它的时候,可能环境是window。



(2)即使是call,apply,bind等方法也不能改变箭头函数this的指向.

以上就是this指向的规则,可通过下图来说明this的指向。



上图说明new的优先级高于bind。bar 被硬绑定到 obj1 上, 但是 new bar(3) 并没有像我们预计的那样把 obj1.a 修改为 3。 相反,new 修改了硬绑定( 到 obj1 的) 调用 bar(..) 中的 this。 因为使用了 new 绑定, 我们得到了一个名字为 baz 的新对象, 并且 baz.a 的值是 3
三、call、apply、bind的用法和区别
1、call方法用法: A.call(B,x,y)。
(1)改变函数A的this指向,使之指向B。
(2)把A函数放到B中运行,x和y是A函数的参数。

2、apply方法
用法: A.apply(B,[x,y])。
(1)改变函数A的this指向,使之指向B.
(2)把A函数放到B中运行,A函数的参数是数组。这是跟call方法不同的地方。

3、bind方法
用法: A.bind(B,x,y)。
(1)改变函数A的this指向,使之指向B。
(2)把A函数放到B中运行,x和y是A函数的参数。
(3)bind 是返回新的函数。

四、手写call、apply、bind、以及new函数
1、call函数的实现

首先context(上下文)为可选参数,不传的话默认上下文为window。接下来给context创建一个fn属性,并将值设置为需要调用的函数(text)。通过[...arguments].slice(1)获取myCall传入的参数。并在调用的时候传入。最后是调用函数并且删除对象上的函数。
2、apply函数的实现

apply的实现思路跟call的实现思路类似。区别在于对参数的处理。
3、bind函数的实现

4、new函数的实现
在调用new的过程中会发生以下4件事情:(1) 新生成一个对象。
(2) 绑定this到新生成的对象上。
(3) 执行构造函数中的代码(即为这个新对象添加属性)。
(4) 返回新对象。
根据以上几个过程,实现一个new函数如下
1、创建一个空对象
2、获取构造函数
3、设置空对象的原型
4、绑定this并执行构造函数
5、确保返回值为对象
五、总结
本文分析this在不同场景的指向问题,通过自己写call、apply、bind以及new函数加深对其原理的理解。