this指向
# 1. 严格模式和非严格模式下的this指向
下面答案输出什么?
function f1() {
console.log(this)
}
function f2() {
'use strict'
console.log(this)
}
f1()
f2()
2
3
4
5
6
7
8
9
10
11
查看答案
// f1() => window
// f2() => undefined
函数在全局环境中简单调用,非严格模式下,this指向window,严格模式下this指向undefined
# 2. 对象中this指向
下面答案输出什么?
const foo = {
bar: 10,
fn: function() {
console.log(this)
console.log(this.bar)
}
}
var fn1 = foo.fn
fn1()
2
3
4
5
6
7
8
9
查看答案
// window
// undefined
此时foo.fn赋值给了fn1,依旧在全局环境下执行,所以this指向window,window中没有bar那么第二个输出undefined
# 3. 对象中this指向2
下面答案输出什么?
const foo = {
bar: 10,
fn: function() {
console.log(this)
console.log(this.bar)
}
}
foo.fn()
2
3
4
5
6
7
8
查看答案
// {bar: 10, fn: ƒ}
// 10
this指向调用它的对象,所以第一个是foo对象,第二个是foo中的bar属性,为10
# 4. 对象中this指向3
下面答案输出什么?
const student = {
name: 'xm',
fn: function() {
return this
}
}
console.log(student.fn() === student)
2
3
4
5
6
7
查看答案
// true
this指向student
# 5. 对象中setTimeout中的this指向
下面答案输出什么?
const foo = {
bar: 10,
fn: function() {
setTimeout(function() {
console.log(this.bar)
})
}
}
foo.fn()
2
3
4
5
6
7
8
9
查看答案
// undefined
虽然是foo方法调用,但是在setTimeout的匿名函数中,this指向全局window
# 6. 对象嵌套中的this指向
下面答案输出什么?
const student = {
name: 'xm',
brother: {
name: 'xh',
fn: function() {
return this.name
}
}
}
console.log(student.brother.fn())
2
3
4
5
6
7
8
9
10
查看答案
// xh
当对象发生嵌套关系的时候,this会指向最后调用它的对象
# 7. 对象中this指向4
下面答案输出什么?
const o1 = {
text: 'o1',
fn: function() {
return this.text
}
}
const o2 = {
text: 'o2',
fn: function() {
return o1.fn()
}
}
const o3 = {
text: 'o3',
fn: function() {
var fn = o1.fn
return fn()
}
}
console.log(o1.fn())
console.log(o2.fn())
console.log(o3.fn())
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
查看答案
// o1
// o1
// undefined
- 第一个this指向o1,o1的属性text值为'o1'
- 第二个对象的调用发生了嵌套,指向最后一个调用的对象o1,o1的属性text值为'o1'
- 第三个对象是函数的简单调用,指向window,window没有text属性,返回undefined
# 8. 对象中this指向5
如何将上面的题,第二个输出'o2'
查看答案
- 方法一:使用call/apply/bind强制修改this
- 方法二:将o1.fn提前赋值
const o1 = {
text: 'o1',
fn: function() {
return this.text
}
}
const o2 = {
text: 'o2',
fn: o1.fn
}
}
2
3
4
5
6
7
8
9
10
11
上面代码中,提前进行复制操作,将函数fn挂载到o2对象上,最终用o2对象的方法被调用
# 9. 使用call/apply/bind的this指向
下面答案输出什么?
const foo = {
name: 'xm',
logName: function() {
console.log(this.name)
}
}
const bar = {
name: 'xh'
}
console.log(foo.logName.call(bar))
2
3
4
5
6
7
8
9
10
查看答案
// xh
最终执行的使用,将this指向了bar,所以输出的是bar的name属性
# 10. 构造函数中的this指向
下面答案输出什么?
function Foo() {
this.bar = 'xm'
}
const foo = new Foo()
console.log(foo.bar)
2
3
4
5
查看答案
// xm
构造函数内部的this指向new出来的foo实例对象
# 11. 构造函数中的this指向2
下面答案输出什么?
function Foo() {
this.bar = 'xm'
const o = {}
return o
}
const foo = new Foo()
console.log(foo.bar)
2
3
4
5
6
7
查看答案
// undefined
如果构造函数返回一个对象,那么foo则等于返回的对象o,o中没有bar,所以是undefined
# 12. 构造函数中的this指向3
下面答案输出什么?
function Foo() {
this.bar = 'xm'
return 1
}
const foo = new Foo()
console.log(foo.bar)
2
3
4
5
6
查看答案
// xm
如果构造函数返回的不是一个对象,那么foo返回的是构造函数Foo的实例对象
# 13. this优先级
下面答案输出什么?
function foo(a) {
console.log(this.a)
}
const obj1 = {
a: 1,
foo: foo
}
const obj2 = {
a: 2,
foo: foo
}
obj1.foo.call(obj2)
obj2.foo.call(obj1)
2
3
4
5
6
7
8
9
10
11
12
13
查看答案
// 2
// 1
显式绑定比隐式绑定的优先级更高,所以第一个this指向obj2,第二个this指向obj1
# 14. this优先级2
下面答案输出什么?
function foo(a) {
this.a = a
}
const obj1 = {}
var bar = foo.bind(obj1)
bar(2)
console.log(obj1.a)
var baz = new bar(3)
console.log(baz.a)
2
3
4
5
6
7
8
9
10
查看答案
// 2
// 3
- 上述代码通过bind将foo的this指向obj1,执行bar(2)的使用,给obj1添加了一个值为2的属性a,所以打印obj1.a是2
- 尽管上面foo改了指向,但是new的优先级大于bind,new又修改了bind绑定的this指向,foo里面的this指向创建的实例baz,所以baz.a是3
# 15. 箭头函数this指向
下面答案输出什么?
const foo = {
fn: function() {
setTimeout(() => {
console.log(this)
})
}
}
console.log(foo.fn())
2
3
4
5
6
7
8
查看答案
// {fn: ƒ}
箭头函数的this指向上级的this,这里this指的是foo
# 16. 箭头函数this指向2
下面答案输出什么?
function foo(a) {
return a => {
console.log(this.a)
}
}
const obj1 = {
a: 2
}
const obj2 = {
a: 3
}
const bar = foo.call(obj1)
console.log(bar.call(obj2))
2
3
4
5
6
7
8
9
10
11
12
13
14
15
查看答案
// 2
foo中this绑定到了obj1上,箭头函数的绑定无法更改,所以就算使用call也不行。
# 17. 箭头函数this指向3
下面答案输出什么?
var a = 123
const foo = () => a => {
return a => {
console.log(this.a)
}
}
const obj1 = {
a: 2
}
const obj2 = {
a: 3
}
const bar = foo.call(obj1)
console.log(bar.call(obj2))
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
查看答案
// 123
箭头函数的this指向外层的作用域,这里指的是window,且不能被call更改。
# 18. 箭头函数this指向4
下面答案输出什么?
const a = 123
const foo = () => a => {
return a => {
console.log(this.a)
}
}
const obj1 = {
a: 2
}
const obj2 = {
a: 3
}
const bar = foo.call(obj1)
console.log(bar.call(obj2))
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
查看答案
// undefined
箭头函数的this指向外层的作用域,const声明的变量不能挂载到window对象上,且不能被call更改,所以是undefined。
# 19. 箭头函数this指向5
下面答案输出什么?
const a = 13
const obj = {
a: 12,
b: () => {
console.log(this.a)
},
c: function() {
console.log(this.a)
},
d: function() {
return () => {
console.log(this)
}
},
e: function() {
return this.b
}
}
obj.b()
obj.c()
obj.d()()
obj.e()()
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
查看答案
// undefined
// 12
// {a: 12, b: ƒ, c: ƒ, d: ƒ, e: ƒ}
// undefined
- 第一个,b虽然是方法调用,但是箭头函数的this指向外层作用域,外层作用域是window,const定义的变量不在window下,所以window下面没有a,返回undefined。
- 第二个,c是方法调用,this指向obj,所以是obj.a是12
- 第三个,d是方法调用,所以obj.d()中的this指的是obj,return里面是箭头函数,this指向外层,就是obj
- 第四个,e是方法调用,里面的return虽然也是箭头函数,但是this.b的作用域是window,因为箭头函数的this一旦确定不可更改,所以不可能变成obj,window下面没有a所以是undefined
# 20. arguments调用函数中的this指向
下面答案输出什么?
let length = 10
function fn() {
console.log(this.length);
}
let obj = {
length: 5,
method(fn) {
// 两次调用各输出什么
fn()
arguments[0](0)
}
}
obj.method(fn, 1)
2
3
4
5
6
7
8
9
10
11
12
13
查看答案
// 第一个输出的是当前window上挂载的iframe和frame框架数量 // 第二个输出2
- 首先调用obj.method(fn, 1)这个语句的时候,fn是直接调用,里面的this指的是window,window.length指的是当前window上挂载的框架数量
- 其次arguments调用函数,this指的是arguments,arguments.length指的是实参的数量,所以是两个