JavaScript中的 this 的指向问题

this的指向

在js中的this的指向。经常说谁调用他就指向谁下面我们来分析下

	var obj = {
	  fun: function () { console.log(this.a) },
	  a: 1
	};
	 
	var fun = obj.fun;
	var a= 2;
	 
	obj.fun() // 1
	fun() // 2

在这里插入图片描述

由图片我们可以看出 虽然执行的是同一个函数但是结果却不同。造成这种情况的原因,就在于函数体内部使用了this,
obj.fun()执行的时候this指向的obj。所以输出的是1
直接调用foo()相当于window.fun() this指向的是window,所以输出的是2。但是实际上this指的是函数运行时所在的环境。对于obj.fun()来说,fun运行在obj环境,所以this指向obj;对于fun()来说,foo运行在全局环境,所以this指向全局环境。所以,两者的运行结果不一样。

有以上可得:

  • this是在函数体内部 自动生成 的一个对象,只能在 函数体内部 使用。
  • this就是函数运行时所在的 环境对象。

那么问题来了为什么会这样,函数的运行环境到底是怎么决定的?
js 在储存应用类型的时候储存的是有个地址。就好比
var obj = { a: 5 };
先在内存里面,生成一个对象{ a: 5 },然后把这个对象的内存地址赋值给变量obj。
变量obj中储存一个地址。后面如果要读取obj.a,引擎先从obj拿到内存地址,然后再从该地址读出原始的对象,返回它的a属性。

上面的的结构是很清晰的,问题在于属性的值可能是一个函数。就好比如

var obj = { foo: function () {} };

这时,引擎会将函数单独保存在内存中,然后再将函数的地址赋值给a。但是函数是一个独立的值,所以它可以在不同的环境(上下文)执行。就如同上面的 fun()可以在全局中执行也可以在其他环境中执行

当函数引用当前环境的其他变量。
就如同上面代码中的在全局中指向

fun() 

上面代码中,函数体里面使用了变量a。该变量由运行环境提供。

由于函数可以在不同的运行环境执行,所以需要有一种机制,能够在函数体内部获得当前的运行环境(context)。所以,this就出现了,它的设计目的就是在函数体内部,指代函数当前的运行环境。
但是有时候我们向this指向其他的执行环境就需要用到 call()、bind()、apply();

改变this指向的三中方法

call()、bind()、apply()都是js预定义的方法,可以挂载对象或某个属性,来改变函数内部的this指向,他们最大的区别就是传入参数的方式不太一样。

改变fn函数的this指向为obj对象。

let obj = {
		name: "张三",
		age: 13
	}
	function fn(height,weight) {
		console.log(this);
		console.log(`姓名:${this.name},年龄:${this.age},身高:${height},体重:${weight}`);
	}

call()方法
call()参数:

  1. 重定义this指向为某个对象或属性。
  2. 传入的实参,可以传入多个,逗号隔开。例如:fn.call(obj,“180cm”,“50kg”);
	fn.call(obj,"180cm","50kg");

在这里插入图片描述

apply()

  1. 重定义this指向为某个对象或属性。
  2. 传入的实参,是以数组的方式传入,数组内的每一个都对应着一个形参。例如:fn.apply(obj,[“180cm”,“50kg”]);
	fn.apply(obj,["180cm","50kg"]);

在这里插入图片描述
达到的效果和call一样。

bind()
bind()方法绑定后会返回一个函数。 参数基本和call是一样的
bind()参数:

  1. 重定义this指向为某个对象或属性。
  2. 传入的实参,可以传入多个,逗号隔开。例如:fn.bind(obj,“180cm”,“50kg”);
	var objfun = fn.bind(obj,"180cm","50kg");
	objfun();

在这里插入图片描述

三种改变this指向的比较

相同点:

  • call()、bind()、apply()都是重定向function中的this指向,并且都可以进行传递参数。

不同点:

  • call() 传入的参数以逗号隔开,可以是任何类型。并且在call()的同时函数会执行。
  • apply() 传入参数的时候必须是一个数组,数组内的每一个值都对应着一个形参,并且在apply()的同时函数会执行
  • bind() 传入的参数以逗号隔开,可以是任何类型。在bind()的同时不会执行函数,但是会返回一个函数。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值