this常见的4中指向
1.在浏览器中
<script type="text/javascript">
/**
* 1.this默认指向当前window,在函数中也是指向当前window。
而全局变量,也会变成当前window对象的一个属性。
*/
var num = 4
console.log(this)
console.log(this.num)
function f() {
console.log(this)
console.log(this.num)
}
f()
</script>
image.png
可以看到,打印出来的this指向的都是window对象,在函数中也是如此
2.在元素的监听事件中
<style>
.div1 {
width: 100px;
height: 100px;
background-color: red;
}
.div2 {
width: 50px;
height: 50px;
background-color: yellow;
}
</style>
<body>
<div class="div1">
<div class="div2"></div>
</div>
<script type="text/javascript">
/**
* 2.在事件侦听中,this指向侦听的那个元素本身,
*/
console.log(document.getElementsByClassName('div2'))
document.getElementsByClassName('div1')[0].onclick = function (e) {
console.log(this)
console.log(e.target) //target指触发这个事件的元素
console.log(e.currentTarget) //currentTarget指事件侦听的这个元素
}
</script>
这里我们有两个div,一个大的div1包着一个小的div2,我们给这个div1绑定一个点击侦听,并且在里面去打印这个this。
image.png
可以看到这里的this指向了div1这个元素,在研究this的时候我还惊奇的发现,e.target和e.currentTarget有点细微的区别。
上图的打印是点击小黄块触发的,也就是点击div2触发的,这个时候可以看到this指向的是div1,e.target是div2,e.currentTarget还是div1。接下来我们点击大红块看看会发生什么
image.png
点击红快快的时候看到e.target也变成了div1,所以这个时候得出,e.target指的是触发这个侦听事件的元素,就是你点的那个元素。e.currentTarget则是绑定侦听事件的元素,和this一样。他们俩是不变的,哪个元素绑定了点击侦听,他们俩就指向谁
3.对象中的this
/**
* 3.当this处在一个对象中,这个this指向的是这个对象本身
*/
let obj = {
a: 1,
b: function () {
console.log(this.a)
}
};
obj.b()
首先看一下打印结果
image.png
可以看到这里的this指向了这个obj
接下来我们看看去this在构造函数中的指向
这里先创建一个对象的构造函数
function addobj(a) {
this.a = a
this.d = 5
console.log(this)
}
先看看这里面的this指向什么,很显然指向的是window,没有new关键字在,这个函数就不是个构造函数,
他还是一个普通的函数,跟this的第一种指向一样,他指向的也是window。
接下来我们用上new关键字,来实例化一个对象
function addobj(a) {
console.log(this,'我是构造函数里的this')
this.a = a
this.d = 5
}
let obj = new addobj(6)
console.log(obj,'我是构造出来的对象obj')
image.png
可以看到构造函数里的this打印出来和构造出的obj是一样的,这是为什么呢。原因就在new这个关键字中。
new关键字做了什么:创建一个对象,把this指向这个对象,然后给这个对象赋值,最后return这个对象,所以我们let 的obj的值,其实就是new关键字创建的对象,这就很合理的解释了,为什么构造函数中打印的东西会和构造出来的obj一样。其实他们本来就是同一个对象!
我们都知道对象的原型链指向的是构造函数的原型对象,也就是说obj.proto=>addobj.prototype。先来验证一下
function addobj(a) {
this.a = a
this.d = 5
}
addobj.prototype = {
b: 2,
};
let newobj = new addobj(1);
console.log(newobj);
上面代码中给addobj这个函数的原型prototype赋值了一个对象,我们打印看看结果
image.png
可以看到,obj本身已经有了构造函数中的a和d属性,并且obj的proto中还有一个b,这个b当然就是构造函数的prototype上的属性。
那么这个时候我们看看this指向的是谁呢
function addobj(a) {
this.a = a
this.d = 5
}
addobj.prototype = {
b: 2,
c: function () {
console.log(this)
}
};
// addobj.prototype.c()
let newobj = new addobj(1);
console.log(newobj);
newobj.c()
image.png
可以看到,构造函数中的两个打印出来的东西还是一样的,那我们是不是可以理解为,函数中的this始终指向调用他的那个对象呢,
再来看一段代码验证猜想
function addobj(a) {
this.a = a
this.d = 5
}
addobj.prototype = {
b: 2,
c: function () {
console.log(this)
}
};
addobj.prototype.c()
let newobj = new addobj(1);
console.log(newobj);
newobj.c()
image.png
我们通过addobj.prototype去调用c,这个时候this指向的不是newobj了,他指向了addobj.prototype。
综上所述,this在对象中,指向的就是当前对象本身。
4.简单使用一下call aplay bind
在了解了上述知识之后,我们知道了this的指向,那在有些情况下,我们需要this不按照常规来指向,而是按照我们自己的意愿去指向,这个时候 call aplay bind 方法就派上用场了
call:
let obj = {
a:2
}
function f1() {
console.log(this)
}
f1()
f1.call(obj)
image.png
在f1函数中打印this,直接调用f1方法和通过call去调用打印出了不一样的值,
直接调用毋庸置疑,打印出的是window对象,因为函数中的this指向的就是window,
而当我们通过call方法,并且传入一个对象的时候,这个时候this的指向就发生变化了,他指向了obj这个对象。这样就做到了改变this 的指向了。
call方法还可以传入参数
let obj = {
a:2
}
function f1(...param) {
console.log(this,param)
}
f1()
f1.call(obj,1,2,3)
image.png
applay方法和call方法一样,只是在传入参数的时候call方法可以传任意形式的,而applay方法只能传入数组,
f1.apply(obj,[1,2,3])
bind方法就是给当前this绑定一个对象,但是bind方法跟其他两个不一样,他会返回一个函数,这个函数如果不主动调用,他是不会执行的
let obj = {
a:2
}
function f1(...param) {
console.log(this,param)
}
f1()
let fu = f1.bind(obj,1,2)
fu()
image.png
如果不去调用fu的话,这个函数是不会自己执行的哦!
以上均为个人理解,并不全面。
网友评论