11 | this:从JavaScript执行上下文的视角讲清楚this
该思维导图由 AI 生成,仅供参考
- 深入了解
- 翻译
- 解释
- 总结
JavaScript中的this机制是一个常见的难点,本文通过深入浅出的方式介绍了JavaScript中this的机制及其应用。文章首先从作用域链和闭包的概念入手,通过代码示例展示了JavaScript中的作用域链和C++中的区别。然后详细介绍了全局执行上下文中的this和函数执行上下文中的this,并指出了this的设计缺陷,并提出了相应的应对方案。文章还提到了箭头函数的特性,以及如何解决嵌套函数中this指向的问题。总结时强调了在使用this时需要注意的三点,并提出了对箭头函数的应用。整体而言,本文通过具体的代码示例和对比,帮助读者快速了解JavaScript中this的机制及其应用。
《浏览器工作原理与实践》,新⼈⾸单¥59
全部留言(96)
- 最新
- 精选
- ytd// 修改方法一:箭头函数最方便 let userInfo = { name:"jack.ma", age:13, sex:'male', updateInfo:function(){ // 模拟 xmlhttprequest 请求延时 setTimeout(() => { this.name = "pony.ma" this.age = 39 this.sex = 'female' },100) } } userInfo.updateInfo() setTimeout(() => { console.log(userInfo) },200) // 修改方法二:缓存外部的this let userInfo = { name:"jack.ma", age:13, sex:'male', updateInfo:function(){ let me = this; // 模拟 xmlhttprequest 请求延时 setTimeout(function() { me.name = "pony.ma" me.age = 39 me.sex = 'female' },100) } } userInfo.updateInfo() setTimeout(() => { console.log(userInfo); },200) // 修改方法三,其实和方法二的思路是相同的 let userInfo = { name:"jack.ma", age:13, sex:'male', updateInfo:function(){ // 模拟 xmlhttprequest 请求延时 void function(me) { setTimeout(function() { me.name = "pony.ma" me.age = 39 me.sex = 'female' },100) }(this); } } userInfo.updateInfo() setTimeout(() => { console.log(userInfo) },200) let update = function() { this.name = "pony.ma" this.age = 39 this.sex = 'female' } 方法四: 利用call或apply修改函数被调用时的this值(不知掉这么描述正不正确) let userInfo = { name:"jack.ma", age:13, sex:'male', updateInfo:function(){ // 模拟 xmlhttprequest 请求延时 setTimeout(function() { update.call(userInfo); // update.apply(userInfo) }, 100) } } userInfo.updateInfo() setTimeout(() => { console.log(userInfo) },200) // 方法五: 利用bind返回一个新函数,新函数被调用时的this指定为userInfo let userInfo = { name:"jack.ma", age:13, sex:'male', update: function() { this.name = "pony.ma" this.age = 39 this.sex = 'female' }, updateInfo:function(){ // 模拟 xmlhttprequest 请求延时 setTimeout(this.update.bind(this), 100) } }
作者回复: 很赞,总结的很全,这个可以做参考答案
2019-08-299201 - WilliamsetTimeOut() 函数内部的回调函数,this指向全局函数。修复:在外部绑this或者使用箭头函数。 ``` let userInfo = { name:"jack.ma", age:13, sex: "male", updateInfo:function(){ let that = this; // 模拟 xmlhttprequest 请求延时 setTimeout(()=>{ that.name = "pony.ma" that.age = 39 that.sex = "female" },100) } } userInfo.updateInfo() ``` ``` let userInfo = { name:"jack.ma", age:13, sex: "male", updateInfo:function(){ // 模拟 xmlhttprequest 请求延时 setTimeout(()=>{ this.name = "pony.ma" this.age = 39 this.sex = "female" },100) } } userInfo.updateInfo() ```
作者回复: 非常好! 补充下解释: 如果被setTimeout推迟执行的回调函数是某个对象的方法,那么该方法中的this关键字将指向全局环境,而不是定义时所在的那个对象。 如果是严格模式,那么this会被设置为undefined。 这一点很容易让人混淆!!!
2019-08-29726 - 悬炫关于箭头函数,文章中说其没有自己的执行上下文,难道箭头函数就像let定义的变量一样是哥块级作用域吗?其内部定义的变量都是存储在词法环境中是吗?
作者回复: 箭头函数在执行时比块级作用域的内容多,比函数执行上下文的内容少,砍掉了很多函数执行上下文中的组件。 不过在箭头函数在执行时也是有变量环境的,因为还要支持变量提升!所以变量环境的模块还是砍不掉的
2019-08-29824 - 风一样的浪漫老师请问下outer的位置是在变量对象内还是外,第10节描述是在内部的,可是11节的图outer放在变量对象外面了
作者回复: 是在里面的,11为了图简单点,调整到外面了
2019-09-05214 - 李懂文章只是简单讲了下this的几种场景,不像前面变量申明,可以很清晰的知道在执行上下文的位置,也没有画图,看完还是不知道不能深入理解,更多的是一种记忆,这种是指向window,那种是指向对象。能不能深入到是如何实现this,才能知道缺陷的原因,这里一直是没理解的难点!
作者回复: this的缺陷并不是浏览器实现机制导致的,而是浏览器按照标准来实现的。 其实浏览器说我可以实现得更好,但是标准摆在这儿,大家都只认标准!
2019-08-2956 - pyhhou思考题,有两种方法 1. 将 setTimeout 里面的函数变成箭头函数 2. 在 setTimeout 外将 this 赋值给其他的变量,setTimeout 里面的函数通过作用域链去改变 userInfo 的属性 很不错的文章,受益匪浅,感谢老师。这里有一个疑问就是,关于箭头函数,文章中说其没有自己的执行上下文,这里指的是箭头函数并不会创建自己的执行上下文变量并压栈,其只是被看作是一个块区域吗?那么在实际的开发中如何在普通函数和箭头函数之间做选择?关于这一点,老师有没有相关推荐的文章呢?谢谢老师
作者回复: 箭头要展开了得话一节来讲,关于箭头函数的最佳实践网上应该有不少资料,可以查查!
2019-08-296 - 朱维娜🍍之前看到一种说法:this指向的永远是调用它的对象。按照这种说法,嵌套函数的调用者是window,与文中所述的“showThis调用内部函数不能继承this”有所出入,想请老师解答一下这种说法是否正确?
作者回复: 调用者是对象,函数内部是调用的地方,不能说是调用者。 obj.showThis() 这里的obj是调用者,通过点操作符来实现的
2019-08-3134 - 潘启宝let userInfo = { name:"jack.ma", age:13, sex:'male', updateInfo:function(){ // 模拟 xmlhttprequest 请求延时 setTimeout(function(){ this.name = "pony.ma" this.age = 39 this.sex = 'female' }.bind(this),100) } } userInfo.updateInfo()
作者回复: 使用bind没有问题
2019-08-2962 - 子曰let userInfo = { name:"jack.ma", age:13, sex:"male", updateInfo:function(){ // 模拟 xmlhttprequest 请求延时 setTimeout(()=>{ this.name = "pony.ma" this.age = 39 this.sex = "female" },100) } } userInfo.updateInfo()
作者回复: 箭头函数没问题
2019-08-291 - mfist延时函数更新此时的this对象指向了window全局对象。 解决方法就是文章老师提到的两种方法。 1 this保存给self变量,通过变量作用域机制传递给嵌套函数。 2箭头函数去锁定函数定义时候的this对象,箭头函数没有上下文,它会继承函数初始化对应上下文。 思考: 1 能否通过bind和apply改变箭头函数this指向? 回头试一下,然后好好理理这几节内容
作者回复: 建议看看其他老铁的留言
2019-08-291