JavaScript中this的指向

this的指向概念

this指向的可以说js是中重中之重,如果要考试,那么它就是逢考必问的题。
要弄清this的指向问题,我们首先要了解一些概念:

  1. 作用域
  2. 执行期的上下文
  3. 上下文对象(this)
1.作用域
定义:**变量(变量作用域又称为上下文)**和函数生效的区域
2.执行期的上下文
当**函数执行**时(在函数发生编译的前一刻),会创建一个执行期的上下文的内部对象。
一个执行期上下文定义了一个函数执行时的环境。
每调用一次函数,就会创建一个新的上下文对象,他们之间是互不影响且独一无二的。
当函数执行完毕,它所执行期上下文会被销毁。
3.上下文对象
*解析器在调用函数每次都会向函数内部传递一个隐含的参数,
这个隐含的参数就是this,this会指向一个对象,这个对象我们称为函数执行的	上下文对象*

函数内this的指向(important!!!)

	函数调用方式的不同,`this` 会指向不同的对象:
  1. 以函数的形式(包括普通函数,定时器函数(setTimeout,setInterval),立即执行函数)调用时,this的指向永远都是window比如fun(); 相当于windoww.fun();
  2. 以方法的形式调用时,this指向调用方法的那个对象1sff
  3. 以构造函数的形式调用时,this指向实例对象
  4. 以事件绑定函数的形式调用时,this指向绑定事件的对象
  5. 使用 call 和apply 调用时,this 会指向指定的那个对象
    注意:this永远指向调用它的对象,new的时候(构造函数),指向new出来的对象
    箭头函数的this,要记得,箭头函数没有自己的this,当我们在箭头函数内部使用了this,this会继承外层函数调用的this绑定(无论this绑定的是什么)

1.函数的形式

var name = '全局的name属性'
function demo(){
	console.log(this);//输出结果:Window
	console.log(this.name);//输出结果:全局的name属性
};
var obj1 = {
	name:'西城辉',
	sayName:demo
};
var obj2 = {
	name:'老王',
	sayName:demo
};

由上可知,this的指向是window 对象,所以 this.name 指的是全局的name
2.以方法的形式调用

function demo(){
	console.log(this);//输出结果:Object
	console.log(this.name);//输出结果:vaw
};
var obj1 = {
	name:'xichenghui',
	sayName:demo,	
};
var obj2 = {
    name: 'vaw',
    sayName: demo,
};

var name = '全局的name属性';
//以方法的形式调用,this是调用方法的对象
obj2.sayName();

上面的举例可以看出,this 指向的是 对象 obj2 ,所以 this.name 指的是 obj2.name。

在JS中提供的几种改变this指向的函数

js提供改变函数内部的this指向的方法有:call() ,apply(), bind()

  1. call()方法
    我们先来看看call()。
    call()方法的作用:可以调用一个函数,并可以改变这个函数内部的this指向
    call()方法的其他应用:可以实现继承。之所以可以实现继承,就是因为改变了函数内部的this指向
    注意:第一个参数中,如果不需要改变this的指向,则传null。
    语法
	fn1.call(想要this指向哪里,函数实参1,函数实参2);	
举例

例一通过call()调用函数:

	const obj1 = {
		nickName:'xichenghui',
		age:18,
	};
	function fn1(){
		console.log(this);//输出结果:window
		console.log(this.nickName);//undefined
	}
	fn1.call(this);//此时this的指向并没有改变,此时相当于 fn1();

例二通过call()改变this的指向:

	const obj1 = {
		nickName:'xichenghui',
		age:18,
	};
	function fn1(a,b){
		console.log(this);//输出结果:window
		console.log(this.nickName);//undefined
		console.log(a + b);
	}
	fn1.call(obj1,2,4);//此时 先将 this 指向 obj1,然后执行 fn1() 函数

例三通过call()实现继承:

	//给 Father 增加 name 和 age 属性
	function Father(myName,myAge){
		this.name = myName;
		this.age = myAge;
	}

	function Son(myName,myAge){
		//重要:通过这一步,将Father 里面的 this 修改为 Son 里面的 this;
		//然后给Son 加上相应的参数,让Son 自动拥有 Father 里面的属性。最终实现继承
		Father.call(this,myName,MyAge);
	}
	const son1 =new Son {'西尘辉',18};
	console.log(JOSN.stringify(son1));//输出结果:{"myName":"西尘辉","myAge":28}

上方代码中,通过 call()方法,让Son 继承了 Father 里面的 name 和 age 属性

  1. apply() 方法
    apply() 方法的作用:可以调用一个函数,与此同时,它还可以改变这个函数内部的 this 指向。这一点和call()类似。
    apply() 方法的应用: 由于 apply() 需要传递数组,有些地方的使用会有很巧妙的应用。
    语法:
	fn1.apply(想要将this指向哪里,[函数实参1,函数实参2]);//注意和call()语法的区别,函数参数为一个数组

在此处,外面可以看出,call() 和 apply() 方法的作用是相同的。唯一区别在于,apply()里面传入实参,必须是数组或者伪数组

Tips:伪数组是基于Object构造函数创建的,它的原型是Object.prototype,所以只拥有原型的属性值,没有Array的数组方法。

举例

例一通过 apply() 改变 this 指向:

	let obj1 ={
		nickName:'xichenghui',
		age:18,
	};
	
	function fn1(a){
		console.log(this);//输出结果:obj1
		console.log(this.nickName);//输出结果:xichenghui
		console.log(a);//输出结果:hello
	}
	
	fn1.apply(obj1,['hello']);//此处将this指向 obj1 ,然后执行 fn1() 函数

注意:上方的代码中,apply() 里面传实参时,需要以数组的形式。即便是一个实参,也需要传数组
例二apply()方法巧用
我们知道,想要求数组元素的最大值时,数组本身是没有自带方法的。那么该怎么办呢?
虽然数组里面没有获取最大值的方法但是数值里面有Math.max(数字1,数字2,数字3)方法,可以获取多个数值中的最大值,且,由于apply()方法在传递实参时,必须要以数组的形式,所以我们可以通过Math.max() 和 apply() 来实现要求。
**例子:**求数组中多个元素的最大值:

	const arr1 =[3,7,10,8];
	//下面代码的目的是,无需改变 this 的指向, 所以: 第一个参数填 null 或者填Math,或者填 			      this 都可以。严格模式下,不可填写null
	//求数组arr1 中元素的最大值
	const maxValue =Math.max.apply(Math,arr1);
	consoloe.log(maxValue);//10

	//求数组 arr1 中元素最小值
	const minValue = Math.min.apply(Math,arr1);
	consoloe.log(minValue);	//3
  • bind方法
    bind()方法的作用:bind()方法不会调用函数,但是可以改变函数内部的this 指向。
    在bind(),apply(),call()三个方法对比之下,我们会发现,实际开发中,bind()方法是使用最多的。如果有函数,我们不需要立刻调用,但是又想要改变这个函数内部的this指向,此时使用bind()函数是最适合的。
    语法:
 		新函数 = fn1.bind(想要将this指向哪里,函数实参1,函数实参2)

参数:

  • 第一个参数:在fn1函数运行时,指定fn1函数的this指向。如果不需要改变this 指向,则传null.
  • 其他参数:fn1函数的实参
    注意:bind()不会调用fn1 函数,但是会返回由指定this和指定实参的原函数拷贝从此处可以看出,bind()方法是有返回值的。
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值