使用 JavaScript 开发的时候,很多人多多少少都会被 this 的指向问题搞蒙圈,但是实际上,关于 this 的指向,记住最核心的一句话:哪个对象调用函数,函数里面的this指向哪个对象。
接下来我们看看几个例子:
<script type="text/javascript">
function test(a){
this.b = a;
console.log(this);
}
test(3);
console.log(b);//3 这里相当于与访问window.b
</script>
1.因为test函数是在整个window对象中,当我们调用test函数时,相当于window.test(3),所以此时的this指向window。
2.因为函数中有this.b,又因为this指向,所以在调用时,给window对象添加了一个b属性
<script type="text/javascript">
var obj = {
a:1,
c:2,
say:function(a){
console.log("this1: "+this);
var sayA = function(a){
console.log("this2: "+this);
this.a = a;
};
function sayC(){
console.log("this3: "+this);
}
sayA(a);
sayC()
}
}
obj.say(3);
console.log(obj.a+" "+obj.c);
console.log(window.a+" "+window.c);
</script>
是不是跟想的有点不一样呢?
我们要记住这句话:哪个对象调用函数,函数里面的this指向哪个对象。
1.当我们使用obj调用say函数时,say作为obj的属性,this当然会指向obj对象,所以this1指向的是obj对象
2.为什么sayA中的this指向window呢,因为sayA函数被执行时默认被window调用,所以this指向window,此时还向window中添加了一个a属性
3.sayC函数也是如此,默认被window调用
<script type="text/javascript">
function Person(name,age){
this.name = name;
this.age = age;
}
var person1 = new Person("张三",18);
var person2 = Person("李四",12);
console.log(person1);
console.log(person2);
console.log(person1.name,person1.age);
console.log(window.name,window.age);
</script>
运行结果:
是不是又懵了?
在这里补充一下new关键字的作用:
a.在构造函数代码开始执行前,创建一个空的对象
b.修改this的指向,把this指向刚刚创建出来的空对象
c.执行函数的代码
d.在函数完成之后返回this–即创建出来的对象
1.此时Person相当于构造函数,使用new关键字后,创建一个空对象,并将this指向这个对象,所以打印时person1是一个对象,里面有name和age属性
2.为什么person2是undefined呢?此时的Person(“李四”,12) 相当于函数执行,没有返回值,所以person2为undefined。
3.为什么window中有name和age属性可以打印?因为Person(“李四”,12)相当于window.Person(“李四”,12),所以Person函数执行时,将name和age属性添加到window中去了
<script type="text/javascript">
function Test(a, b) {
this.a = a;
this.b = b;
this.say = function (a, b) {
this.a = a;
this.b = b;
console.log(this);
console.log(a, b);
}
}
var obj1 = new Test(1, 1);
console.log(obj1.a, obj1.b);
obj1.say();
console.log(obj1.a, obj1.b);
var obj2 = { a: 2, b: 2 };
obj1.say(4, 4)
console.log(obj1.a,obj1.b);
console.log("------------");
obj1.say.call(obj2, 3, 3);
console.log(obj2.a + "--" + obj2.b);//3--3
</script>
是不是又又懵逼了??
我们一条一条的分析:
1.首先我们可以知道,obj1是构造函数Test new出来的对象,所以打印属性a,b时,就是当时传参进去的值 (1 和 1)
2. obj1.say(); 当obj1.调用say时,因为say是obj1的属性,所以say的this也指向obj1,调用say函数时,由于没有传参,所以say中的a,b都为undefined,因为this指向obj1,所以也将obj1中的a,b属性进行了修改。
3.call方式可以用来暂时修改this指向,第一个参数传指定对象,后面的进行传参,所以此时的this指向obj2,同时将obj2中的a,b属性值也进行了修改。
链接: JavaScript 中 call()、apply()、bind() 的用法,及区别.
看到这里也不容易,出两道简单的题考考你吧!
<script type="text/javascript">
function test(){
var age = "张三";
console.log(this.age);
console.log(this);
}
test();
</script>
<script type="text/javascript">
var obj = {
name:"张三",
sayName:function(){
console.log(this);
console.log(this.name);
function show(){
console.log(this);
}
show()
}
}
obj.sayName()//
window.obj.sayName();//obj本来就在window中,与上面的结果一样
</script>
<script type="text/javascript">
var obj = {
name:"小明",
objInner:{
name:"小红",
sayName:function(){
console.log(this);
console.log(this.name);
}
}
}
obj.objInner.sayName();
</script>