js中this的指向

75 阅读3分钟
1 this的创建时间
  • 所有的函数在被调用时,都会创建一个执行上下文
  • 这个上下文中记录着函数的调用栈、AO对象等;
  • this也是其中的一条记录;
2 this的值在执行时确定
  • 函数在调用时,JavaScript会默认给this绑定一个值;
  • this的绑定和定义的位置(编写的位置)没有关系;
  • this的绑定和调用方式以及调用的位置有关系;
  • this是在运行时被绑定的;
3 this的绑定规则
  • 默认绑定:this指向全局对象
    • 独立的函数调用我们可以理解成函数没有被绑定到某个对象上进行调用;
  • 隐式绑定:this指向调用函数的对象
    • 也就是它的调用位置中,是通过某个对象发起的函数调用。
    • 隐式绑定有一个前提条件:
      • 必须在调用的对象内部有一个对函数的引用(比如一个属性);
      • 如果没有这样的引用,在进行调用时,会报找不到该函数的错误;
      • 正是通过这个引用,间接的将this绑定到了这个对象上;
  • 显示绑定:this指向call,apply,bind函数中的第一个参数
    • JavaScript所有的函数都可以使用call和apply方法(这个和Prototype有关)。
    • 它们两个的区别其实非常简单:第一个参数是相同的,后面的参数,apply为数组,call为参数列表;
    • 这两个函数的第一个参数都要求是一个对象,这个对象的作用是什么呢?就是给this准备的。
    • 在调用这个函数时,会将this绑定到这个传入的对象上。
    • 在显示绑定中,我们传入一个null或者undefined,此时this执行全局
  • new关键字绑定:this指向构造函数生成的对象
    • 使用new关键字来调用函数是,会执行如下的操作:
      • 创建一个全新的对象;
      • 这个新对象会被执行prototype连接;
      • 这个新对象会绑定到函数调用的this上(this的绑定在这个步骤完成);
      • 如果函数没有返回其他对象,表达式会返回这个新对象;
4 四条规则的优先级问题
5 内置函数中的this
  • setTimeout、setInterval:指向全局
  • 数组的方法:默认指向全局,可以通过传参改变
  • dom元素绑定的事件(如点击事件等):指向触发事件的dom元素
6 箭头函数
  • 箭头函数中没有this的概念,查找this会沿着作用域查找
  • 箭头函数中也没有arguments
7 模拟实现apply,call,bind函数
  • 确定函数中this的指向,
  • 传入参数执行函数,获得返回值
  • 将返回值返回
Function.prototype.selfCall = function(obj, ...args) {
	if (obj === null || obj === undefined) {
		obj = window;
	} else {
		obj = Object(obj);
	}
	obj.fn = this;
	const result = obj.fn(...args);
	delete obj.fn;
	return result;
};

Function.prototype.selfApply = function(obj, args) {
	if (obj === null || obj === undefined) {
		obj = window;
	} else {
		obj = Object(obj);
	}
	args = args || [];
	obj.fn = this;
	const result = obj.fn(...args);
	delete obj.fn;
	return result;
};

Function.prototype.selfBind = function(obj, ...args1) {
	var fn = this;
	return function(...args2) {
		if (obj === null || obj === undefined) {
			obj = window;
		} else {
			obj = Object(obj);
		}
		obj.fn = fn;
		var result = obj.fn(...args1, ...args2);
		delete obj.fn;
		return result;
	};
};