前端面试代码题

总结了几道 this 指向的代码题,做过之后我发现我对 this 一无所知。

1.

var num = 1;
var myObject = {
    num: 2,
    add: function() {
        this.num = 3;
        (function() {
            console.log(this.num);
            this.num = 4;
        })();
        console.log(this.num);
    },
    sub: function() {
        console.log(this.num)
    }
}
myObject.add();
console.log(myObject.num);
console.log(num);
var sub = myObject.sub;
sub();

输出结果:

1 3 3 4 4

解析:

执行myObject.add()时,add里的this指向myObject,所以先将myObject中的num改为3;

接着执行下边的自执行函数,没有任何对象调用该函数,所以该自执行函数的 this 指向 window,所以输出 1,再将window中num改为4;

接着输出 myObject的 num,3;

输出 3;

输出 4;

var sub = myObject.sub 此时 sub只是一个函数指针,最后在window下调用这个函数,所以sub()的this指向 window,输出 4;

 

2.

var name = 'window'        
var person1 = {
    name: 'person1',
    show1: function () {
        console.log(this.name)
    },
    show2: () => console.log(this.name),
    show3: function () {
        return function () {
            console.log(this.name)
        }
    },
    show4: function () {
        return () => console.log(this.name)
    }
}
var person2 = { name: 'person2' }

person1.show1()
person1.show1.call(person2)

person1.show2()
person1.show2.call(person2)

person1.show3()()
person1.show3().call(person2)
person1.show3.call(person2)()

person1.show4()()
person1.show4().call(person2)
person1.show4.call(person2)()

输出结果:

person1.show1()   // person1
person1.show1.call(person2)  // person2

person1.show2()   // window
person1.show2.call(person2)  // window

person1.show3()()  // window
person1.show3().call(person2)   // person2
person1.show3.call(person2)()  // window

person1.show4()()   // person1
person1.show4().call(person2)   // person1
person1.show4.call(person2)()   // person2

其中最让人不解的应该是 show2 和 show4

解析:

person1.show2() 实际是执行:()=>console.log(this.a),根据“箭头函数的this指向外层作用域”,该箭头函数外层没有函数了,即指向全局作用域

这里很有迷惑性的地方是:容易把person1这个对象的{}大括号理解为函数作用域,实际上对象并没有生成作用域!!

person1.show2.call(person2)这个根据“箭头函数直接应用bind、call、apply不起作用”,很容易可知这里this依然指向全局

person1.show4()()实际是执行了以下两步:

执行:function () { return ... }返回一个箭头函数

return回来的这个箭头函数再执行

该箭头函数执行时它的外层作用域是这个show4的function,这个function的this指向person1,所以箭头函数中的this指向person1

很容易可得person1.show4().call(person2)指向person1

person1.show4.call(person2)()这个执行的时候,显式绑定将person2绑定到show4这个function上,那么依上面的分析,该箭头函数指向show4的function,所以箭头函数的this指向了person2

注意箭头函数:

箭头函数没有自己的this,它的this指向的是谁调用箭头函数的外层function,箭头函数的this就是指向谁,如果箭头函数没有外层函数,则指向window。

3.

var name = 'window'

function Person(name) {
    this.name = name;
    this.show1 = function () {
        console.log(this.name)
    }
    this.show2 = () => console.log(this.name)
    this.show3 = function () {
        return function () {
            console.log(this.name)
        }
    }
    this.show4 = function () {
        return () => console.log(this.name)
    }
}

var personA = new Person('personA')
var personB = new Person('personB')

personA.show1()
personA.show1.call(personB)

personA.show2()
personA.show2.call(personB)

personA.show3()()
personA.show3().call(personB)
personA.show3.call(personB)()

personA.show4()()
personA.show4().call(personB)
personA.show4.call(personB)()

输出结果:

personA.show1()  // personA
personA.show1.call(personB)  // personB

personA.show2()   // personA
personA.show2.call(personB)  // personA

personA.show3()()   // window
personA.show3().call(personB)  // personB
personA.show3.call(personB)()  // window

personA.show4()()  // personA
personA.show4().call(personB)   // personA
personA.show4.call(personB)()  // personB

这组例子和上一题的对比我有两个疑惑点:

  1. show2为什么会输出两次personA?不是指向外层作用域吗?这里外层作用域难道不是全局了?
  2. new绑定的优先级不是高于显示绑定吗?为什么personA.show1.call(personB)还能变成personB?

首先针对第一个疑惑点要说明的是:构造函数创建对象后其实多了一层构造函数的作用域,如图所示:

解析:

可以看到personA的scope和person1的差别:person1中的show1作用域仅仅是global,而personA中show1的函数作用域链是从构造函数产生的闭包开始的!

所以这样就很容易能知道show2的执行为什么会不同了:

personA的show2中的this指向构造函数形成的闭包函数,即Person函数,所以这里输出personA

 

 

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

前端卡卡西呀

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值