# this的指向
this 总是指向执行时
的当前对象
其四种情况:
- 作为对象的方法调用。指向调用对象。
- 作为普通函数调用。指向Windows。
- 构造器调用。指向构造器。
- Function.prototype.call 或 Function.prototype.apply 调用。指向被绑定的对象。
# 二、call, apply 和 bind
# 简介及区别
call 和 apply作用一模一样,区别仅在于传入参数形式的不同。
# apply
apply
接受两个参数,第一个参数指定了函数体内 this 对象的指向,第二个参数为一个带下标的集合,这个集合可以为数组,也可以为类数组
。
类数组:
- 对象本身要可以存取属性;
- 对象的 length 属性可读写。
# call
call
传入的参数数量不固定,第一个参数也是代表函数体内的 this 指向,从第二个参数开始往后,每个参数被依次传入函数。
# bind
bind
参数类型和 call 相同,不过它不会执行函数,而是修改 this 后返回一个新的函数。
# 动手实现apply
函数
Function.prototype.apply = function (context) {
//判断对象是否存在
var context = context || window;
//获取参数(下标1即第二个参数,为目标数组)
var args = arguments[1] || [];
//为目标对象绑定要调用的方法,即apply的调用者
context.fn = this;
//调用方法
var result = context.fn(...args);
delete context.fn;
return result;
}
1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
# call
函数的实现
将args改为arguments.silce(1)。
# bind
函数的实现
在call基础上去掉return。
# 与此同时,可以引申出new
的实现
- 首先创一个新的空对象。
- 根据原型链,设置空对象的
__proto__
为构造函数的prototype
。 - 构造函数的 this 指向这个对象,执行构造函数的代码(为这个新对象添加属性)。
- 判断函数的返回值类型,如果是引用类型,就返回这个引用类型的对象。
function myNew(context) {
const obj = new Object();
obj.__proto__ = context.prototype;
const res = context.apply(obj, [...arguments].slice(1));
return typeof res === "object" ? res : obj;
}
1
2
3
4
5
6
2
3
4
5
6