在这之前我们要先了解几条法则,了解以后对this的问题就会迎刃而解
- 对象方法的内部函数的this指向window(非对象中的方法)
- 对象的方法内,this指向对象
- 对象中的this指向window
- 严格模式下(
use strict
)对象中禁止this关键字指向全局对象,此时的this
是undefined
如果此时出现this.a
就会报错,因为undefined
不能添加属性。 - 如果说方法中的回调函数(就是方法
return
的值)是箭头函数,根据箭头函数的特点,他的this指向应该是根据上面的this指向来判断的。(简单的说就是上面的this
指向什么下面的箭头函数就是指向什么的)。如果回调函数是一个普通的function
函数那么始终是指向window
的。 - 如果把对象方法的函数赋值给全局变量的变量,此时再去调用这个变量的函数,这个时候变量是被
window
调用的。 - 当函数1传入的是函数2的时候在函数2还在GO里面,此时函数2中的
this
是指向window
的
下面我们来举例子:
一:
var obj = {
a: 10,
b: this.a + 10, //this指向window 所以a为undefined
fn: function() {
return this.a; //this指向obj
}
}
console.log(obj.b); //NaN
console.log(obj.fn());
二:
var a = 20;
var obj = {
a: 10,
getA: function() {
return this.a;
}
}
console.log(obj.getA()); //10 对象obj调用方法,this指向obj对象
var test = obj.getA; //表示将getA的属性值赋值给test变量,也就是将函数的地址赋值给test
// var test = function(){
// return this.a
// }
console.log(test()); //20 window调用方法,所以this指向window
这道题中我们需要注意的是,将函数赋值给了test
此时再去调用test
这个时候的test
在全局变量中,所以此时test
被window
调用。
三:
var a = 5;
// 顶层函数:this指向window
function fn1() {
var a = 6;
console.log(a); //6
console.log(this.a); //谁调用方法,this就指向谁
}
function fn2(fn) { //fn = function fn1(){}
var a = 7;
fn(); //window调用的
}
var obj = {
a: 8,
getA: fn1
}
fn2(obj.getA);
当函数1传入的是函数2的时候在函数2还在GO里面,此时函数2中的this
是指向window
的
四:
function fn() {
// "use strict";
// 严格模式下:禁止this关键字指向全局对象
// console.log(this); //undefined
var a = 1;
var obj = {
a: 10,
c: this.a + 20 //不能为undefined添加属性
}
return obj.c;
}
console.log(fn()); //Cannot read property 'a' of undefined
五:
function Person(name, age) {
this.name = name;
this.age = age;
console.log(this);//使用new创建出来的对象,输出Person
}
Person.prototype.getName = function() {
console.log(this); //使用哪个对象来调用,this就指代谁,输出Person
}
var p1 = new Person("test", 18)
p1.getName()
这里是给Person
对象添加一个原型,还是在Person
上面所以这个时候应该是指向Person
六:
var obj = {
foo: "test",
fn: function() { //对象的方法内,this指向该对象
var mine = this;
console.log(this.foo); //"test"
console.log(mine.foo); //"test"
// 方法的内部函数的this指向window
(function(){
console.log(this.foo); //undefined
console.log(mine.foo); //"test" mine指向方法的局部变量mine,最终指向obj对象
})()
}
}
obj.fn();
在这里的考点其实是我们经常在项目中用到的,把上一层的this
赋值给一个变量,然后再在下一层中使用这个变量,也就是下一层中使用的是上一层中的this
.
七:
function foo() {
console.log(this.a);
}
var a = 2;
var o = {
a: 3,
foo: foo
}
var p = {
a: 4,
}
o.foo(); //3 对象调用方法,方法内的this指向该对象
(p.foo = o.foo)(); //2 自调用函数 this指向window
p.foo = o.foo;
p.foo(); //4 对象调用方法,方法内的this指向该对象
在这里注意的是第二三个输出,第二个输出是自调用函数,this
指向的是window
也可以在这里把他看成将foo()
这个函数赋值给p.foo
这里的p.foo
就是一个变量在window
下面调用这个函数,现在的foo
函数也是在window
里面,而且又是一个自调用函数,所以此时是被window
调用的。
第三个输出是先赋值然后再通过,p.foo()
调用的,此时是被p
调用的。
八:
function foo() {
console.log(this.a);
}
var obj1 = {
a: 3,
foo: foo
};
var obj2 = {
a: 5,
foo: foo
};
obj1.foo();//3
obj2.foo();//5
obj1.foo.call(obj2)//5
obj2.foo.call(obj1)//3
这里涉及到了一个方法劫持,顾名思义就是把一个对象劫持到另外一个对象上面比如obj1.foo.call(obj2)
就是把obj
的foo
方法劫持到了obj2
上面现在的foo
方法就是obj2
调用的
九:
<script type="text/javascript">
function test(arg) {
this.x = arg;
console.log(this);
return this;
}
var x = test(5);
var y = test(6);
console.log(window.x.x); //undefined
console.log(y.x); //6
这道题的陷阱比较多,主要是全局变量中的x
和函数中的this.x
是一样的。这是一个陷阱。全局变量中的x
y的返回值都是``window
但是在执行x
y
的时候先进去的是5,此时window
下面的x
变成了5,然后又执行y
此时的window
下面的x
变成了6。再来看看输出的结果,第一个相当于window.x.x
这时候的window.x.x
被上面赋值以后是6。6.x
找不到,所以输出undefined
后面输出的是window.y.x
这儿的window.y
返回的是window
就相当于window.x
就等于6.
十:
var obj = {
data: [1,2,3,4,5],
data2: [1,2,3,4,5],
fn: function(){
console.log("-----test-----");
console.log(this);
return this.data.map(function(item) {
console.log(this);
return item*2;
})
},
fn2: function() {
console.log("-----test2-----");
console.log(this);
return this.data2.map(item => {
console.log(this);
return item*2;
})
}
};
obj.fn();
obj.fn2();
这道题按照最开始的法则就可以得出结果了,我就不做过多的赘述了。
有错误希望各路大神指出。小弟感激不尽