c语言进阶项目笑傲江湖,【进阶3-2期】JavaScript深入之this笑傲江湖

本文通过两组实战题目详细解析了JavaScript中的this绑定、作用域和闭包。题目涉及隐式绑定、显式绑定、箭头函数等知识点,通过解答这些题目,读者可以更深入地理解this的五种绑定规则以及作用域和闭包的原理。同时,文章还探讨了new操作符在构造函数中的应用,强调了new操作符对作用域的影响。
摘要由CSDN通过智能技术生成

高级前端进阶(id:FrontendGaoji)

作者:木易杨,资深前端工程师,前网易工程师,13K star Daily-Interview-Question 作者

AAffA0nNPuCLAAAAAElFTkSuQmCC

本期推荐文章

从这两套题,重新认识JS的this、作用域、闭包、对象

推荐理由

今日推荐文章来自于相学长关于this的两道题,题目确实变态,涉及到了this的各个方面,把这两道题弄懂,基本上就可以在this的领域上笑傲江湖了。保重!

阅读笔记

上篇文章详细的分析了各种this的情况,看过之后对this的概念就很清晰了,没看过的点击查看。

【进阶3-1期】JavaScript深入之史上最全--5种this绑定全面解析

我们知道this绑定规则一共有5种情况:1、默认绑定(严格/非严格模式)

2、隐式绑定

3、显式绑定

4、new绑定

5、箭头函数绑定

其实大部分情况下可以用一句话来概括,this总是指向调用该函数的对象。

但是对于箭头函数并不是这样,根据外层(函数或者全局)作用域(词法作用域)来决定this。

题目1/**

* 非严格模式

*/

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,隐式绑定,this指向调用者 person1

person1.show1.call(person2) // person2,显式绑定,this指向 person2

person1.show2() // window,箭头函数绑定,this指向外层作用域,即全局作用域

person1.show2.call(person2) // window,箭头函数绑定,this指向外层作用域,即全局作用域

person1.show3()() // window,默认绑定,这是一个高阶函数,调用者是window

// 类似于`var func = person1.show3()` 执行`func()`

person1.show3().call(person2) // person2,显式绑定,this指向 person2

person1.show3.call(person2)() // window,默认绑定,调用者是window

person1.show4()() // person1,箭头函数绑定,this指向外层作用域,即person1函数作用域

person1.show4().call(person2) // person1,箭头函数绑定,

// this指向外层作用域,即person1函数作用域

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

最后一个person1.show4.call(person2)()有点复杂,我们来一层一层的剥开。1、首先是var func1 = person1.show4.call(person2),这是显式绑定,调用者是person2,show4函数指向的是person2。

2、然后是func1(),箭头函数绑定,this指向外层作用域,即person2函数作用域

题目2

这次通过构造函数来创建一个对象,并执行相同的4个show方法。/**

* 非严格模式

*/

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

personA.show1.call(personB) // personB,显式绑定,调用者是 personB

personA.show2() // personA,首先personA是new绑定,产生了新的构造函数作用域,

// 然后是箭头函数绑定,this指向外层作用域,即personA函数作用域

personA.show2.call(personB) // personA,同上

personA.show3()() // window,默认绑定,调用者是window

personA.show3().call(personB) // personB,显式绑定,调用者是personB

personA.show3.call(personB)() // window,默认绑定,调用者是window

personA.show4()() // personA,箭头函数绑定,this指向外层作用域,即personA函数作用域

personA.show4().call(personB) // personA,箭头函数绑定,call并没有改变外层作用域,

// this指向外层作用域,即personA函数作用域

personA.show4.call(personB)() // personB,解析同题目1,最后是箭头函数绑定,

// this指向外层作用域,即改变后的person2函数作用域

题目一和题目二的区别在于题目二使用了new操作符。使用 new 操作符调用构造函数,实际上会经历一下4个步骤:创建一个新对象;

将构造函数的作用域赋给新对象(因此this就指向了这个新对象);

执行构造函数中的代码(为这个新对象添加属性);

返回新对象。

所以与字面量创建对象相比,很大一个区别是它多了构造函数的作用域。

AAffA0nNPuCLAAAAAElFTkSuQmCC

AAffA0nNPuCLAAAAAElFTkSuQmCC

图片来自于推荐文章。

上期思考题解

依次给出console.log输出的数值。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();

答案有两种情况,分为严格模式和非严格模式。严格模式下,报错。TypeError: Cannot read property 'num' of undefined

非严格模式下,输出:1、3、3、4、4

解答过程:var num = 1;

var myObject = {

num: 2,

add: function() {

this.num = 3; // 隐式绑定 修改 myObject.num = 3

(function() {

console.log(this.num); // 默认绑定 输出 1

this.num = 4; // 默认绑定 修改 window.num = 4

})();

console.log(this.num); // 隐式绑定 输出 3

},

sub: function() {

console.log(this.num) // 因为丢失了隐式绑定的myObject,所以使用默认绑定 输出 4

}

}

myObject.add(); // 1 3

console.log(myObject.num); // 3

console.log(num); // 4

var sub = myObject.sub;//  丢失了隐式绑定的myObject

sub(); // 4

内容来自评论区:【进阶3-1期】JavaScript深入之史上最全--5种this绑定全面解析

本期思考题

分别给出console.log输出的内容。var obj = {

say: function () {

function _say() {

console.log(this);

}

console.log(obj);

return _say.bind(obj);

}()

}

obj.say()

参考从这两套题,重新认识JS的this、作用域、闭包、对象

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值