var obj = {
a: 10,
b: this.a + 10,
fn: function() {
return this.a;
}
}
console.log(obj.b);
console.log(obj.fn());
运行结果:
obj.b => NaN
obj.fn() => 10
在对象里,属性
里的this指向window,在全局作用域没有定义a,但由于是对象.a相当于创建了a,只是没赋值,this.a为undefined,加上一个数值,故NaN
;方法
里的this指向方法的调用者,这里就是obj对象本身,执行函数,故得到对象里的a值10
。
2.
var a = 20;
var obj = {
a: 10,
getA: function() {
return this.a;
}
}
console.log(obj.getA());
var test = obj.getA;
console.log(test());
运行结果:
obj.getA() => 10
test() => 20
第一个输出10不难理解,就是对象里的方法this指向它的调用者obj;var test = obj.getA;
相当把对象里的getA方法函数体赋值给test,即var test = function(){return this.a;}
此时this指向window对象,故输出20。
3.
var a = 5;
function fn1() {
var a = 6;
console.log(a);
console.log(this.a);
}
function fn2(fn) {
var a = 7;
fn();
}
var obj = {
a: 8,
getA: fn1
}
fn2(obj.getA);
输出结果:
a => 6
this.a => 5
首先从fn2函数调用开始,这里有个实参obj.getA,指的是obj对象里getA方法,而getA方法是fn1,即相当于在fn2里传了fn1函数,由于作用域,a输出6
,this这里指的是window对象,故this.a值为5
。
4.
function fn() {
'use strict';
var a = 1;
var obj = {
a: 10,
c: this.a + 20
}
return obj.c;
}
console.log(fn());
输出结果:
fn() => 报错
这个函数体内部是在严格模式下运行的,在严格模式下,禁止this关键字指向全局对象,对象属性里的this指向全局对象window,故会报错。
5.
function Person(name,age) {
this.name = name;
this.age = age;
console.log(this);
}
Person.prototype.getName = function() {
console.log(this);
}
var p1 = new Person('test', 18);
p1.getName();
输出结果:
构造函数里的this、原型上getName方法里的this都是指向实例化对象,故结果都是Person这个构造函数。
6.
var obj = {
foo: "test",
fn: function() {
var mine = this;
console.log(this.foo);
console.log(mine.foo);
(function() {
console.log(this.foo);
console.log(mine.foo);
})();
}
};
obj.fn();
输出结果:
第一组:test
test
第二组:undefined
test
对象的方法里this指向方法的调用者,故第一组都是打印obj本身的foo属性值,在第二组时,由于时自执行函数,函数体内this指向的是window对象
,在全局作用域下没有foo属性,故undefined
,由于前面把this赋值给了一个变量保存,所以第二组mine.foo还是调用对象的属性foo。
7.
function foo() {
console.log(this.a);
}
var a = 2;
var o = {
a: 3,
foo: foo
};
var p = {
a: 4
};
o.foo();
(p.foo = o.foo)();
p.foo = o.foo;
p.foo();
输出结果:
o.foo() => 3
(p.foo = o.foo)() => 2
p.foo() => 4
o.foo()指访问o对象里有个名为foo的方法,并执行它,这里我们知道了,这是对象内的方法,this指向o这个对象,故为3
;第二个是个自执行函数,它是把对象o的方法foo添加到对象p的方法中去,但由于此时是个自执行函数,函数体内this指向window,故为2
;第三个也是如同第二个,只不过是在是访问对象内的方法,此时this指向对象p,故为4
.
8.
function foo() {
console.log(this.a);
}
var obj1 = {
a: 3,
foo: foo
};
var obj2 = {
a: 5,
foo: foo
};
obj1.foo();
obj2.foo();
obj1.foo.call(obj2);
obj.foo.call(obj1);
输出结果:
obj1.foo() => 3
obj2.foo() => 5
obj1.foo.call(obj2) => 5
obj1.foo.call(obj1) => 3
这道题没什么说的,只不过利用call
方法改变了函数内this指向,不清楚这个方法的可以看这篇博客:
https://blog.csdn.net/qq_48784569/article/details/107562945
9.
function test(arg) {
this.x = arg;
return this;
}
var x = test(5);
var y = test(6);
console.log(x.x);
console.log(y.x);
输出结果:
x.x => undefined
y.x => 6
这道题有点意思:首先我们分析我们把5这个实参传给了test函数的形参,函数体内this指向window,即在window下添加了一个x属性值为5,函数返回这个window对象通过全局变量x接受,但由于此时x也是window对象上的,执行x.x
时它会覆盖之前window.x=5
,现在是window.x=window
,所以它不会向我们想的那样拿到5,而是无限循环访问window对象;而执行y = test(6)
时,把6传进去,此时window对象上的x又一次被覆盖,现在是window.x=6
,通过全局变量y去接受这个返回值window对象,相当于是window.y=window
,即此时window.x=6
了,y变为window对象了,可以通过y.x
访问到6,用x.x访问时全局变量x变成了数值了,故是undefined
。
10.
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();
输出结果:
实际这里主要是让我们区分箭头函数与普通函数的区别,这里是对象,在fn方法内this指向调用者,故为obj对象,在return语句里函数里由于window下调用了函数,故this指向window,循环输出5次window对象;在fn2方法里,同理,this指向obj对象,在箭头函数里,this指向靠近的作用域,故为obj对象。
这里扩展一下箭头函数和普通函数的区别吧:
- 箭头函数体内
this
对象,是定义时所在的作用域中的this值,而不是使用时所在的对象; - 不可以使用
arguments
对象,该对象在函数体内不存在,如果要用,可以用rest参数(剩余参数)
代替; - 不可使用
yield
命令,因此箭头函数不能做Generator函数; - 不可使用new命令:因为没有自己的this,
无法调用call()、apply()
;没有prototype属性,而new命令在执行时需将构造函数的prototype赋值给新对象__proto__。