一通百通,其实函数执行上下文、作用域链、闭包、this、箭头函数是相互关联的,他们的特性并不是孤立的,而是相通的。因为内部函数可以访问外层函数的变量,所以才有了闭包的现象。箭头函数内没有 this 和 arguments,所以内部调用了 this,会去上层函数作用域中查找 this 的指向。这些内容都是相通的。我们要融会贯通全面理解,而不是死记硬背哦。

大厂面试题分享 面试题库

前后端面试题库 (面试必备) 推荐:★★★★★

地址:前端面试题库

变量定义

  • var 声明变量

  • 变量未声明直接使用

这两种方式都可以声明变量,但是该变量会是全局变量,绑定在 window 对象上。同时 var 会有声明提升的作用。

console.log(a);  // undefined;并不会报错var a;
复制代码
  • let 声明变量

  • const 声明变量

let 和 const 是 ES6 新增的关键字,let 和 const 声明的变量不会有声明提前的特点。同时,let 和 const 声明之前的执行瞬间被称为”暂时性死区“,在此阶段引用任何后面才声明的变量都会抛出 ReferenceError。

let 和 const 在全局作用域中声明的变量不会成为 window 对象的属性。

const 声明变量时必须同时初始化变量。

最佳实践:

  • 不使用 var

  • const 优先,let 次之

函数定义

与变量不同,函数定义会提前;变量只是声明提前。

say()  // Hello worldfunctionsay(){console.log('Hello world')}
复制代码

但是使用变量声明函数,函数定义不会提前,同 var 变量声明一样,只是声明会提前。

console.log(say)  // undefinedvar say = function(){console.log('Hello world')}
复制代码

原因是在执行 js 代码之前会进行变量提升和函数定义。

函数执行

作用域 规定了如何查找变量,也就是确定当前执行代码对变量的访问权限。

执行上下文:当我们执行一个方法时,JavaScript 会生成一个与这个方法对应的执行环境(context),又叫执行上下文。这个执行环境中有这个方法的私有作用域、上层作用域的指向、方法的参数(arguments)、私有作用域中定义的变量以及 this 对象。这个执行环境被添加到一个栈中,这个栈就是执行栈。

如果在这个方法的代码中执行到了一行函数调用语句,那么 JavaScript 会生成这个函数的执行环境并将其添加到执行栈中,然后进入这个执行环境继续执行其中的代码。执行完毕后返回结果后,JavaScript 会退出执行环境并把这个执行环境从栈中销毁,回到上一个方法的执行环境。这个过程反复进行,直到执行栈中的代码全部执行完毕。这个执行环境的栈就是执行栈。

执行上下文分全局上下文、函数上下文和块级上下文。

内层函数 fn 内有 arguments 对象、 this 对象、变量;以及函数 Fn 上层作用域的指向。fn 可以访问上层 Fn 的变量,但是不能访问 Fn 的 this 和 arguments 对象。

JavaScript 采用词法作用域,也就是静态作用域。

var value = 1;functionfoo() {console.log(value);
}functionbar() {var value = 2;foo();
}bar();
复制代码

JavaScript采用的是词法作用域,函数的作用域基于函数创建的位置。

块级作用域(ES6新增)

for(let i=0;i<10;i++){// i 只能在这里使用
}
复制代码
functionf(flag){if(flag){var x = 10;}return x;
}
console.log(f(false));  //不会报错, undefined复制代码

闭包和 this

闭包(closure)指的是那些引用了另一个函数作用域中变量的函数,通常是在嵌套函数中实现的。注意:只有引用了另一个函数作用域中的变量,才称为闭包,如果一个函数 A 内部返回了另一个函数 B,内部函数 B 并没有引用 A 的作用域中的变量是不会形成闭包的。博客

javascript - 理解闭包与内存泄漏 - 前海拾贝 - SegmentFault 思否 已验证。

闭包和执行上下文以及作用域是相通的,那就是内部函数可以访问外部函数的变量,但是不能访问外部函数的 this 和 arguments 对象。如下的例子:

window.identity = 'The Window';
let object = {identity: 'My Object',getIdentityFunc() {let code = 'closure'returnfunction() {console.log(code)returnthis.identity;};}
};
console.log(object.getIdentityFunc()()); // 'The Window'复制代码

第6行的匿名函数调用了外部函数 getIdentityFunc 函数作用域中的变量 code,我们称之为闭包,由于内部函数并不能访问外部函数的 this 和 arguments 对象,所以 this 对象并不是 object , 而是全局函数的 this window。

对于普通函数调用时的 this 指向:在全局函数中调用 this,this 等于 window;如果作为某个对象的方法调用,则 this 等于这个对象。先判断谁调用了这个函数,然后再判断 this 指向。

对于箭头函数 this 指向:因为箭头函数内部没有 this 和 arguments 对象,所以箭头函数的 this 指向该函数所在的作用域指向的对象。符合作用域查找逻辑,箭头函数本身没有 this 定义,会沿着作用域链查找。这时的 this 相当于一个变量,按照词法作用域逻辑查找。修改上面的例子:

window.identity = 'The Window';
let object = {identity: 'My Object',getIdentityFunc() {let code = 'closure'return() => {console.log(code)returnthis.identity;};}
};
console.log(object.getIdentityFunc()()); // 'My Object'复制代码

此时,内部函数修改为箭头函数,我们知道箭头函数内部没有自己的 this,所以会沿着作用域链查找上层函数 getIdentityFunc 的 this 指向。由于是 object 调用的 getIdentityFunc,所以 getIdentityFunc 的 this 指向 object 对象。再复杂一点:

window.identity = 'The Window';
let object = {identity: 'My Object',getIdentityFunc() {let code = 'closure'return() => {console.log(code)returnthis.identity;};}
};
const callObject = {identity: 'call object'}
console.log(object.getIdentityFunc.call(callObject)()); // 'call object'复制代码

这里调用的时候,使用了 call 改变了 getIdentityFunc 了 this 指向 callObject, 那么箭头函数在调用的时候,会沿着作用域链找到 getIdentityFunc 的 this 指向为 callObject 对象。

大厂面试题分享 面试题库

前后端面试题库 (面试必备) 推荐:★★★★★

地址:前端面试题库

【面试题】闭包是什么?this 到底指向谁?相关推荐

  1. this到底指向谁?

    this关键字是JavaScript函数内部的一个对象,this是一个指针,指向调用函数的对象.看似简单的定义但却由于在解析this引用过程中可能涉及到执行上下文.作用域链.闭包等复杂的机制,导致th ...

  2. 从一道面试题谈起,大厂到底看重程序员的什么能力?

    唐磊,他谦逊的自我介绍,是"在阿里云打工的清华学渣". 上周的一篇<字符串比较,居然暗藏玄机>,我最早是在唐磊<这10行比较字符串相等的代码给我整懵了>里看 ...

  3. JS面试题-闭包异步-变量提升-引用传值-this

    闭包面试题和异步的题目 var name = "The Window";var object = {name: "My Object",getNameFunc: ...

  4. 栈顶指针到底指向哪_被称为“程序员试金石”的指针真的没有那么难!不信的话你来看看

    很多朋友放弃C语言都是因为指针,说什么指针的*号很讨厌啦.分不清址与值啦,当然了,最烦的还是链表结点,本来链表操作就让人烦了,再加上指针这个东西真是让初学的朋友苦不堪言,最后放弃了C语言转投其他语言的 ...

  5. 面试题不会做,到底应不应该上网查?

    今天同学去面试,对我说题目有点不会做,脑子有点懵.后来她看到其他面试者直接上网查答案了,她说早知道她也这样子了. 我分享一下我的观点,我不认同这种做法哦! 每一场面试之前做好充足的准备,你可以自己在面 ...

  6. JavaScript中this面试题, 四道题彻底清楚this指向问题

    this面试题一 如果不清楚this绑定规则可以看上一篇有详细说明 var name = "window";var person = {name: "person&quo ...

  7. this到底指向哪里

    this指向调用它的对象 首先要明确,this指向调用方,谁调用,this指向谁. 直接调用 举个栗子: var test = 'window' ; function testThis () {var ...

  8. javaScript基础面试题 ---闭包

    闭包 1.闭包是什么? 2.闭包可以解决什么问题? 3.闭包的缺点 1.闭包是什么? 闭包是一个函数加上到创建这个函数的作用域的链接,就是一个作用域可以访问到另一个作用域的变量,闭包'关闭'了函数的自 ...

  9. this:它到底指向哪里!箭头函数的this又是啥?

    文章目录 JavaScritp 中的 this 总结一句话(永真给的信) 默认绑定(指向少主window) 严格模式(变若之子) 隐式绑定(苇名弦一郎) 隐式丢失(赤鬼 + 鬼庭形部雅孝) 显式绑定( ...

最新文章

  1. netty 之 telnet HelloWorld 详解
  2. SAMBA服务和FTP服务讲解(week3_day1)--技术流ken
  3. Python函数中4种参数的使用
  4. VMware虚拟机上安装Linux系统
  5. mysql视图中调用函数写法_从视图中调用函数
  6. 保护个人信息需出“重典”
  7. 按Sybase的PowerDesigner工具设计的数据库模型 --- 解析生成能兼容多种数据库的相应的C#底层代码...
  8. request 和response 中的setCharacterEncoding区别
  9. usb转ttl测试软件,usb转ttl驱动
  10. c语言编译器pellc,单片机C语言程序的设计实训100例_基于8051+PROTEUS仿真1
  11. “谈了四年的男友寒心了,我已是接近30的老女人”
  12. 数模【Mathematica(安装、入门方法、基本计算、基本图形、创建互动模型、利用数据、幻灯片演示、完整实例)】
  13. codelite14中文语言包_Windows下CodeLite支持中文的正确设置方法
  14. lms全称是什么意思_LMS是什么意思
  15. 《中国合伙人》经典台词:一个人迫于无奈之下的选择,往往是正确的。。。
  16. WFP实现侧边栏导航菜单
  17. Leetcode初学——跳跃游戏
  18. STM32使用SPI方式读写SD 卡
  19. PDF中在指定位置插入图片
  20. CVPR2022:将X光图片用于垃圾分割,探索大规模智能垃圾分类

热门文章

  1. 计算机二级第38套excel,38套EXCEL 仪表盘
  2. echarts 仪表盘 文字位置_ECharts 使用series.title.offsetCenter设置仪表盘标题位置
  3. 大学计算机基础学生实验报告经验总结,安卓作业实验报告心得体会
  4. Linux下使用vim 编写c语言程序
  5. python编程超市购物系统_淘淘购物系统 (Python)
  6. linux 星际争霸,让星际争霸在Linux操作系统下转起来
  7. 回文判断 【问题描述】 回文是正读和倒读都一样的句子。读入一个最大长度不超过50个字符的句子,判断其是否是回文。 【输入形式】 输入一个最大长度不超过50个字符的句子 【输出形式】 Yes/No
  8. user_agreement
  9. Simulink永磁同步电机控制仿真系列五:使用滑模观测器的反电动势法位置估计
  10. 空气动力学基本知识(二)