接触js有一段时间了,js中始终避不开的一个问题就是this,我们话不多说,直接上代码。
this.c = 1
function a() {
console.log(this.c)
}
function b() {
a()
}
a()
b()
问上面输出结果是什么?显然结果是1,1;第一个函数a调用的时候this指向Window全局,拿到其中的c,因此此时输出全局对象中的c的值,当b调用时,接着a被调用,此时的this是指向哪里呢?根据输出结果,我们可以判断它指向的也是全局作用域中的c。根据this的相关原理,前人总结了以下几个结论:
this指向哪里,要看他在哪里以什么方式调用
- 1: this默认指向window
- 2: 以 对象.xxx() 方式调用
- 3:以 call/apply/bind 方式调用
- 4: new 的方式调用*
也就是说,根据以上规则,我们基本就可以弄清楚this所指代的到底是什么了。显然,函数b调用时,a随之被调用,这里的a是遵从第一条原则的,因此a的this指向的就是Window全局,所以输出结果就是1。下面让我们给代码加上一点东西,如下:
this.c = 1
function a() {
console.log(this.c)
}
function b() {
this.c = 2
a()
}
a()
b()
我们在 b 函数体中增加了一行关于 c 的代码,那么这个时候输出结果会有什么变化呢?结果是1,2;如果你理解为 a 函数在 b 函数内部被调用,因此 a 函数中的 this 指向了 b,因此输出结果是 2,那就错了。我们可以试想,如果是这样的话,那为什么第一种情况 b 调用后不输出 undefined 呢?显然这种想法是错误的,那为什么输出结果是 2 呢?我们再回顾一下上面的规则,我们发现a其实是默认指向Window全局的,那为什么会输出 2 呢?那是因为函数b在被调用后,this.c = 2 将全局中的c的值改成了 2 ,因此得到的全局中的 c 的值变成了 2 ,所以结果是1, 2。我们再来看看下面这道面试题:
this.a = 20;
function go() {
console.log(this.a);
this.a = 30;
}
go.prototype.a = 40;
var test = {
a: 50,
init: function (fn) {
fn();
console.log(this.a);
return fn;
}
};
console.log((new go()).a);
test.init(go);
var p = test.init(go);
p();
这段代码看上去似乎有些复杂,但没关系,我们一点一点来剖析。题目的要求就是写出输出结果,首先第一行,在Window全局设置 this.a = 20 接着定义了一个构造函数 go,在给go的原型链加上了 a 属性值为 40 ,然后定义了一个 test 对象,接着就是输出以及函数的调用。我们先来看第一个输出,显然 new go() 利用构造函数创建了一个对象,根据第四条规则,相当于改变了this的指向,因此 this 此时指向的是构造出来的实例本身,接着 go() 函数执行输出 this.a 我们发现 go 函数本身是没有 a 这个属性的,于是它往原型链上找,最终找到了 40 ,于是输出 40 ,紧接着输出实例对象中的 a 属性,可以发现构造出来的实例对象中是有 a 属性的,即 a = 30, 因此输出 30 。
然后调用的是对象 test 中的 init 方法,根据第二条规则,this的指向会发生改变,指向调用的对象test,则函数 init 中的 this 此时指向 test 对象,将函数 go 作为参数传入 init ,在 init 内部,调用了 fn 即 go, 那么问题来了,这时的函数 go 中的 this 指向哪里呢?根据规则,我们可以得出结论,它是指向 Window 全局的,因此它首先会输出全局中的 a 的值即输出 20, 然后,注意了!这是一个坑,输出完之后,它将全局中的 a 的值改成了 30 ,接着继续 init 函数的执行,打印出的 a 是 test 对象中的 a 的值为 50 ,然后返回 go 。
下面定义了一个变量 p 接收了返回的 go ,在此之前,init 函数又执行了一遍,输出为全局的 a 此时为 30,以及 test 对象中的 a,值为 50 。
最后一行是 p 函数的执行,也就是 go 函数的执行,结果显然是全局中 a 的值为 30。因此,输出结果为:40,30,20,50,30,50,30,如下:
this.a = 20;
function go() {
console.log(this.a);
this.a = 30;
}
go.prototype.a = 40;
var test = {
a: 50,
init: function (fn) {
fn();
console.log(this.a);
return fn;
}
};
console.log((new go()).a); // 40 30
test.init(go); // 20 50
var p = test.init(go); // 30 50
p(); // 30
以上便是关于js中this的一点见解,希望我的文章对大家有所帮助,若有什么不恰当之处,希望大佬多多指点!!!