38道关于this的面试题,让你彻底解决this 的指向问题

thisthisthisthis不可以用作构造函数,不能使用new命令,否则会报错箭头函数没有arguments对象,如果要用,使用rest参数代替不可以使用yield命令,因此箭头函数不能用作Generator函数。thisthis箭头函数没有prototype属性。这份清华大牛整理的进大厂必备的redis视频、面试题和技术文档祝大家早日进入大厂,拿到满意的薪资和职级~~~加油!!!《一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码》点击传送门,即可获取!
摘要由CSDN通过智能技术生成

《一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码》点击传送门,即可获取!

答案

obj 是通过 var 定义的, obj 会挂载到 window 之上的, obj.foo() 就相当于 window.obj.foo() ,这也印证了 this永远指向最后调用它的那个对象 规则。

题目2.2:对象链式调用

感觉上面总是空谈链式调用的情况,下面直接来看一个例题:

var obj1 = {

a: 1,

obj2: {

a: 2,

foo(){

console.log(this.a)

}

}

}

obj1.obj2.foo() // 2

3.隐式绑定的丢失


隐式绑定可是个调皮的东西,一不小心它就会发生绑定的丢失。一般会有两种常见的丢失:

  • 使用另一个变量作为函数别名,之后使用别名执行函数

  • 将函数作为参数传递时会被隐式赋值

隐式绑定丢失之后, this 的指向会启用默认绑定。

具体来看题目:

题目3.1:取函数别名

a = 1

var obj = {

a: 2,

foo() {

console.log(this.a)

}

}

var foo = obj.foo;

obj.foo();

foo();

JavaScript 对于引用类型,其地址指针存放在栈内存中,真正的本体是存放在堆内存中的。

上面将 obj.foo 赋值给 foo ,就是将 foo 也指向了 obj.foo 所指向的堆内存,此后再执行 foo ,相当于直接执行的堆内存的函数,与 obj 无关, foo 为默认绑定。笼统的记, 只要fn前面什么都没有,肯定不是隐式绑定 。

答案

不要把这里理解成 window.foo 执行,如果 foo 为 let/const 定义, foo 不会挂载到 window 上,但不会影响最后的打印结果

题目3.2:取函数别名

如果取函数别名没有发生在全局,而是发生在对象之中,又会是怎样的结果呢?

var obj = {

a: 1,

foo() {

console.log(this.a)

}

};

var a = 2;

var foo = obj.foo;

var obj2 = { a: 3, foo: obj.foo }

obj.foo();

foo();

obj2.foo();

obj2.foo 指向了 obj.foo 的堆内存,此后执行与 obj 无关(除非使用 call/apply 改变 this 指向)

答案

题目3.3:函数作为参数传递

function foo() {

console.log(this.a)

}

function doFoo(fn) {

console.log(this)

fn()

}

var obj = { a: 1, foo }

var a = 2

doFoo(obj.foo)

用函数预编译的知识来解答这个问题:函数预编译四部曲前两步分别是:

  1. 找形参和变量声明,值赋予 undefined

  2. 将形参与实参相统一,也就是将实参的值赋予形参。

obj.foo 作为实参,在预编译时将其值赋值给形参 fn ,是将 obj.foo 指向的地址赋给了 fn ,此后 fn 执行不会与 obj 产生任何关系。 fn 为默认绑定。

答案

Window {…}

2

题目3.4:函数作为参数传递

将上面的题略作修改, doFoo 不在 window 上执行,改为在 obj2 中执行

function foo() {

console.log(this.a)

}

function doFoo(fn) {

console.log(this)

fn()

}

var obj = { a: 1, foo }

var a = 2

var obj2 = { a: 3, doFoo }

obj2.doFoo(obj.foo)

console.log(this)

obj2.doFoo

xxx.fn

doFoo

this

obj2

{a: 3, doFoo: ƒ}

  • fn() : 没有于 obj2 产生联系,默认绑定,打印2

答案

{a: 3, doFoo: ƒ}

2

题目3.5:回调函数

下面这个题目我们写代码时会经常遇到:

var name=‘zcxiaobao’;

function introduce(){

console.log('Hello,My name is ', this.name);

}

const Tom = {

name: ‘TOM’,

introduce: function(){

setTimeout(function(){

console.log(this)

console.log('Hello, My name is ',this.name);

})

}

}

const Mary = {

name: ‘Mary’,

introduce

}

const Lisa = {

name: ‘Lisa’,

introduce

}

Tom.introduce();

setTimeout(Mary.introduce, 100);

setTimeout(function(){

Lisa.introduce();

},200);

setTimeout 是异步调用的,只有当满足条件并且同步代码执行完毕后,才会执行它的回调函数。

Tom.introduce()执行

console

setTimeout

this

window

Mary.introduce

setTimeout

题目3.3

this

Lisa.introduce

setTimeout

xxx.fn

this

答案

Window {…}

Hello, My name is zcxiaobao

Hello,My name is zcxiaobao

Hello,My name is Lisa

所以如果我们想在 setTimeout 或 setInterval 中使用外界的 this ,需要提前存储一下,避免 this 的丢失。

const Tom = {

name: ‘TOM’,

introduce: function(){

_self = this

setTimeout(function(){

console.log('Hello, My name is ',_self.name);

})

}

}

Tom.introduce()

题目3.6:隐式绑定丢失综合题

name = ‘javascript’ ;

let obj = {

name: ‘obj’,

A (){

this.name += ‘this’;

console.log(this.name)

},

B(f){

this.name += ‘this’;

f();

},

C(){

setTimeout(function(){

console.log(this.name);

},1000);

}

}

let a = obj.A;

a();

obj.B(function(){

console.log(this.name);

});

obj.C();

console.log(name);

本题目不做解析,具体可以参照上面的题目。

答案

javascriptthis

javascriptthis

javascriptthis

undefined

4.显式绑定


显式绑定比较好理解,就是通过 call()、apply()、bind() 等方法,强行改变 this 指向。

上面的方法虽然都可

  • 17
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值