6.1 聊聊 this、call、apply,怎么用。

一、前言

之前学过this、call、apply怎么去用,但是理解地不够深刻,离开了案例,实际操作起来就出问题了。当然了,写这篇文章只是个人在使用过程中产生的理解。

二、正文

1、什么是this,call,apply?

this是函数内部的属性,也就是说this只能在函数运行的时候才能确定,只能在函数内部访问。
指向的对象是调用当前函数的对象(谁调用我这个函数,我就是谁)。
如何更好判断this具体指向谁?

  • 第一种情况:函数调用时,函数名前面有对象,这时this指向函数名前面这个对象
var obj = {
	name:"lodash",
	age:13,
	foo:function(){
		console.log(this);
	}
}
obj.foo();//{name:"lodash",age:"13",foo:[Function:foo]}

因为是对象obj调用了这个函数foo,所以这时this就是obj,进而打印出来整个obj对象。

  • 第二种情况:函数名前面没有对象,这时this指向全局对象(window/global)
var a = 6;
var obj = {name:"bb"};
function foo(){
 	console.log(this);//一大堆东西,巴拉巴拉
 	consoele.log(this.a);//6
 	console.log(this.obj);//{name:"bb"}
 	console.log(this.foo);//[Function:foo]
}
foo ();

对于全局对象不太理解的,可以将全局对象看做一个网页最大的对象,这个对象包含了网页全部的内容,例如上面代码定义的a,obj,foo都是全局对象里的成员。所以全局对象可以像对象的调用一样调用a,obj,foo。

  • 第三种情况:函数名后面有call/apply,这是this指向传参的第一个参数。
var obj = {
	name:"lala",
	age:5,
	foo:function(){
		console.log(this);
	}
}
var obj2 = {
	name:"baba",
	age:"30"
}
obj.foo();//{name:"lala",age:"5"}
obj.foo.call(obj2);//{name:"baba",age:30}
obj.foo.apply(obj2);//{name:"baba",age:30}

这里的call,apply是指定调用函数的对象方法。(告诉this现在谁调用这个函数),传入的参数第一个作为手动指定调用函数的对象,这里只给一个参数,其实可以有多个参数,但不管有几个参数,第一个参数永远都是指定调用函数的对象。

2、疑问

看完上面,小伙伴可能会有些疑问
不是说好的函数名前面有对象,this就指向前面这个对象嘛?怎么后面有call就变了?
这里只能告诉你,一旦函数名后面有call/apply,这个优先指向第一个参数,如果没有传参,就指向全局对象。

3、总结

判断this指向优先级:
有call/apply就指向第一个参数(没有参数就指向全局对象)->函数名前面有对象就指向这个对象->即没对象又没call/apply就指向全局对象。

4、拓展

1、一个代码看懂this

var name = "全局对象";
var obj ={
	name:"对象1",
	age:15
}
var obj2 = {
	name:"对象2",
	age:22
}
function foo(){
	console.log(this.name);
}
Object.prototype.foo = foo;//这里是为了让对象能调用函数foo,这个知识点是函数的原型链继承
foo();//全局对象

obj.foo();//对象1
obj2.foo();//对象2

foo.call();//全局对象
foo.call(obj);//对象1
foo.call(obj2);//对象2

obj.foo.call();//全局对象
obj2.foo.call();//全局对象
obj.foo.call(obj2);//对象2
obj2.foo.call(obj);//对象1

2、call与apply简单区分
它们两用法总体差不多,区别在于传参上
call传参是指定对象后面接实参列表
apply传参是指定对象后面接参数数组

var obj ={
	name:"对象1",
	age:15
}
var obj2 = {
	name:"对象2",
	age:22
}
function foo(a,b,c){
	console.log(this,a,b,c);
}
Object.prototype.foo = foo;

foo.call(obj,1,3,4,5);//{name:"对象1",age:15} 1 3 4
foo.apply(obj2,[1,3,4,6]);//{name:"对象2",age:22} 1 3 4

由此可见参数传的第一个不能看做参数,而是指定的对象,而对象后面接的第一个才是真正的第一个参数。

©️2020 CSDN 皮肤主题: 创作都市 设计师:CSDN官方博客 返回首页