了解闭包前还需要先理解js编译原理、变量查询以及作用域。 1.基础知识 1.1 编译原理 尽管通常将 JavaScript 归类为“动态”或“解释执行”语言,但事实上它是一门编译语言。...1.2 关于变量的查找 变量查询分为LHS查询和RHS查询,上面赋值操作将进行LHS查询。 当变量出现在赋值操作的左侧时进行 LHS 查询,出现在右侧时进行 RHS 查询。...最小授权或最小暴露原则:在软件设计中,应该最小限度地暴露必 要内容,而将其他内容都“隐藏”起来,比如某个模块或对象的API 设计。 作用域的好处: 规避冲突 全局命名空间易与第三方库发生变量冲突。...); } })(); 倒置代码的运行顺序,将需要运行的函数放在第二位。...块作用域是一个用来对之前的最小授权原则进行扩展的工具,将代码从在函数中隐藏信息 扩展为在块中隐藏信息 当使用 var 声明变量时,它写在哪里都是一样的,因为它们最终都会属于外部作用域。
介绍本期介绍作用域和闭包的知识点和题目。包括作用域,自由变量,闭包,this 等部分。作用域是 “JS 三座大山” 之二,不知道闭包的话,面试通过概率不大。主要内容什么是作用域?什么是自由变量?...闭包会用在哪里?this 有几种赋值情况关键字作用域闭包this----什么是作用域?...,不是在执行的地方闭包会用在哪里?...场景一:采用函数引用方式的setTimeout调用场景二:回调场景三:函数防抖场景四:封装私有变量 实际开发中闭包多用于隐藏数据 ,只提供API进行修改数据this 有几种赋值情况作为普通函数被调用,指向的是...'arg2']); // {a: '这是obj'}fn.bind(obj, 'arg1', 'arg2')(); // {a: '这是obj'}原理:3个方法第一个参数为新的执行环境,所以是一个对象将当前执行环境赋值给新环境的某个属性使用新环境调用当前执行环境
既然是直接调用那么就是访问当前上文作用域内的叫getName的函数,所以这里应该直接把关注点放在4和5上,跟1 2 3都没什么关系。当然后来我问了我的几个同事他们大多数回答了5。...● 而用函数表达式创建的函数是在运行时进行赋值,且要等到表达式赋值完成后才能调用 所以可以分解为这两个简单的问题来看清楚区别的本质 这个区别看似微不足道,但在某些情况下确实是一个难以察觉并且“致命“的陷阱...当然我们给一个总结:Javascript中函数声明和函数表达式是存在区别的,函数声明在JS解析时进行函数提升,因此在同一个作用域内,不管函数声明在哪里定义,该函数都可以进行调用。...而函数表达式的值是在JS运行时确定,并且在表达式赋值完成后,该函数才能调用。...此处实际上是将外层作用域内的getName函数修改了。
然后将导出和导入变量全部放到内存中。我们称之为链接。 赋值:执行代码,将变量值添加到内存中。 之所以说 ES 模块是异步的,正是因为 ES 模块将这三个步骤划分开。...将文件转化为一个模块记录 在我们加载文件后,我们需要将它转化为一个模块记录。这会让浏览器理解模块的不同部分。一旦模块记录被创建,就会被放在一个模块映射中。...在浏览器中你只要将 type="module" 放在 script 标签上。这会通知浏览器这个文件应该被转化为一个模块。同样,只有模块才能够被导入,浏览器也就知道了模块中有哪些引用。...赋值 最后一步就是填充内存空间。JS 引擎通过执行顶层的代码来完成,也就是函数外的代码。如果遇到类似异步调用的情况,还可能会出现一些负面的影响。 由于这种负面影响,赋值得到的结果可能是不相同的。...JS 引擎会为本地变量分配内存空间,并且将值赋为 undefined。
词法作用域 词法作用域(其实就是静态作用域)是由你在写代码时将变量和块作用域写在哪里来决定的。 作用域会在查找到第一个匹配的标识符时停止,从最内层的向全局作用域查询,会有屏蔽效应。...现以o1为词法作用域,进行a的LHS查询,然后赋值为2。再以o2为词法作用域,进行LHS查询,没有找到向上查询也没有找到,所以创建了一个全局变量。 性能影响 js引擎在编译阶段进行多项性能优化。...其中有些优化依赖于根据代码的词法进行静态分析,并预先确定所有变量和函数的定义位置,才能在执行过程中快速找到标识符。...词法作用域意味着作用域是由书写代码是函数声明的位置决定的。编译的词法分析阶段基本能够知道全部标识符是在哪里以及如何声明的,从而能预测在执行过程中如何对它进行查找。...函数作用域的含义是指: 属于这个函数的全部变量都可以在整个函数的范围内使用及复用(事实上在嵌套的作用域中也是可以的) 隐藏内部实现 其实就是把代码用函数声明对他进行包装,不让外部用于他的访问权限,变成类似于私有的
存储方面解释:作用域链在JS内部中是以数组的形式存储的,数组的第一个索引对应的是函数本身的执行期上下文,也就是当前执行的代码所在环境的变量对象,下一个索引对应的空间存储的是该对象的外部执行环境,依次类推...,与函数在哪里被调用无关 })()}show(fun)由于变量的查找是沿着作用域链来实现的,所以也称作用域链为变量查找的机制。...变量只能在特定的区域内才能被访问,外部环境不能访问内部环境的任何变量和函数,即可以向上搜索,但不可以向下搜索, 有了作用域我们就可以避免在程序其它位置意外对某个变量做出修改导致程序发生事故。...,与函数在哪里被调用无关 })()}show(fun)由于变量的查找是沿着作用域链来实现的,所以也称作用域链为变量查找的机制。...变量只能在特定的区域内才能被访问,外部环境不能访问内部环境的任何变量和函数,即可以向上搜索,但不可以向下搜索, 有了作用域我们就可以避免在程序其它位置意外对某个变量做出修改导致程序发生事故。
可以不保存,也可以保存在隐藏域、Cookie、Session等地方。...默认保存在隐藏域里面 //这里设置为不保存 PagerSQL.SaveLocation = JYK.Common.SaveViewStateLocation.NoSave...Viewstate里面的东东谁然看起来乱七八糟的,但是很容易就可以把它变成能够看懂的信息,那么如果把表名、字段名这些敏感的信息放在Viewstate里面显然是不安全的,所以我就自己写了一个类库,可以把信息保存在隐藏域...2、保存了什么信息,又保存在了哪里? ...保存的信息就是各个属性的值,保存的位置您可以自由选择,可以选择不保存,可以选择保存在隐藏域(web控件的时候需要),也可以保存在Cookie、Session、Cache等地方。
但是在严格模式下,并不是自动创建一个全局变量,而是会抛出 ReferenceError 异常 补充JS几种常见的错误类型[1] 简单总结如下: 作用域是一套规则,用于确定在哪里找,怎么找到某个变量。...词法作用域 词法作用域是你在写代码时将变量写在哪里来决定的。编译的词法分析阶段基本能够知道全局标识符在哪里以及是如何声明的,从而能够预测在执行过程中如果对他们查找。...,并预先确定所有变量和函数的定义位置,才能在执行过程中快速找到识别符,eval, with会改变作用域,所以碰到它们,引擎将无法做优化处理。...关于 块级作用域和变量提升的内容之前在 从JS底层理解var、let、const这边文章中详细介绍过,这里不再赘述。...参考 深入理解JavaScript作用域和作用域链[2] 深入理解javascript原型和闭包系列[3] 作用域和词法作用域[4] 《你不知道的JavaScript (上卷)》 参考资料 [1]JS几种常见的错误类型
_a = 0; return 0; } 继承中的作用域 不管是基类还是派生类它都有独立的作用域,都在该类域里面。 当基类中的成员和派生类中的成员名相同的时候,此时基类中的该成员隐藏。...要显示基类的类域才可以访问,没有显示类域默认访问派生类中的。 注意:只要名字一样就构成隐藏。..._a << endl; cout << "A中:" << x.A::_a << endl;//访问A中的_a要指定类域 return 0; } 成员函数构成的隐藏 cppclass A { public...这样才能保证先析构派生类,再析构基类 构造函数 1.当基类有默认的构造函数的时候,可以只初始化派生类新的成员变量,也可以自己调用基类的默认构造,看自己的心情。...现在有个问题,对于son1,son2他们怎么找到_f在哪里的?
但是将变量引入程序会引起几个很有意思的问题:这些变量储存在哪里?最重要的是,程序需要时如何找到它们? 这些问题说明需要一套设计良好的规则来存储变量,并且之后可以方便地找到这些变量。...词法作用域就是定义在词法阶段的作用域。换句话说,词法作用域是由你在写代码时将变量和块作用域写在哪里来决定的,因此当词法分析器处理代码时会保持作用域不变(大部分情况下是这样的)。...换句话说,可以把变量和函数包裹在一个函数的作用域中,然后用这个作用域来“隐藏”它们。 为什么“隐藏”变量和函数是一个有用的技术? 有很多原因促成了这种基于作用域的隐藏方法。...a); // 3 console.log(global.a); // 2 })(window); console.log(a); // 2 IIFE 还有一种变化的用途是倒置代码的运行顺序,将需要运行的函数放在第二位...块作用域是一个用来对最小授权 原则进行扩展的工具,将代码从在函数中隐藏信息扩展为在块中隐藏信息。
result + i; } return result;}console.log(add(100));函数表达式函数表达式和函数声明非常相似,它们甚至有相同的语法,不过,要记住的是,函数调用必须放在表达式赋值之后...param] [..., param]) { statements }//函数表达式var say = function() { alert("Nian糕");}函数提升我们在上面提到,函数调用必须放在表达式赋值之后...,那函数的调用是不是也要放在函数声明之后呢,我们来试试看在上面的这个例子中,我们先调用了函数,然后再对函数进行声明,而函数确实能够调用,并执行了里面的函数,至于为什么会这样,是因为在 JS 当中,不管函数在哪个位置...,都默认将函数整体提升到作用域顶部,该作用域包括全局作用域、函数作用域,同样提升的还有变量,但是函数整体在变量整体的后面,不过,只有声明式函数才会被提升,字面量函数不会被提升我们在定义左图的变量及函数时...,它实际上的解析顺序是像右图那样的,先对变量进行声明,然后再赋值,并非声明的同时就赋值我们再来看一个例子练习接下来我们来设计一个函数,使其能够判断某一年份是否为闰年,符合下面两个条件之一的年份就是闰年:
变量出现在赋值左侧,所以采用LHS查询,如果变量出现在赋值右侧或者是单纯引用如console.log(a)则采用RHS查询1.3作用域嵌套作用域是根据变量名称查询变量的一套规则,JS分为全局作用域、局部...其中有些优化依赖于能够根据代码的词法进行静态分析,并预先确定所有变量和函数的定义位置,才能在执行过程中快速找到标识符。...,所以在全局作用域下调用自然会查找失败,全局作用域不会向foo作用域去申请访问或者是查询,变量a,b在foo作用域下,c在bar作用域下,同理在foo函数下去访问c变量一样会报错;3.2隐藏内部实现定义...:先声明一个函数,在函数中定义变量或函数,利用函数作用域隐藏代码。...隐藏变量或函数的好处是什么?
下面的代码会告诉浏览器你的 Service worker 脚本放在哪里 if (navigator.serviceWorker) { // 注册Service Worker...需要说明的是 service-worker.js 文件被放在这个域的根目录下,这意味着 service worker 是跟网站同源的。...换句话说,这个 service worker 将会获取到这个域下的所有 fetch 事件。...service-worker.js 文件,我建议是放在网站的跟目录下,scope 不作修改,这样 service worker 拥有最大的使用范围。...注意:将 service-worker.js 放到域的根目录下哦,这样 Service worker 才能拥有最大的使用范围。
3)赋值操作符会导致LHS查询,=操作符或调用函数时传入参数的操作都会导致关联作用域的赋值操作。...,即词法作用域是由写代码时将变量和块作用域写在哪里来决定的,大部分情况下,词法分析器处理代码时会保持作用域不变; 3)作用域查找会在找到第一个匹配的标识符时停止; 4)全局变量会自动成为全局对象的属性,...3.1.1 隐藏内部实现 把变量和函数包裹在一个函数的作用域中,然后用这个作用域来“隐藏”它们。这种方法大都是从最小特权/最小授权/最小暴露原则中引申出来的。...=== undefined){ console.log('Undefined is safe here'); } })(); IIFE还有一种变化的用途是倒置代码的运行顺序,将需要运行的函数放在第二位...块作用域是一个用来对之前的最小授权原则进行扩展的工具,将代码从在函数中隐藏信息扩展为在块中隐藏信息。
当对一个变量执行RHS查询时,如果遍历该变量所在处的词法作用域未能找到这个变量,JS引擎就会抛出ReferenceError错误如果成功查询到了这个变量,但是对这个变量执行不合理操作,比如对一个非数组的变量执行下标取值...不过这种语言与传统的编译语言还是有点不同,它不是提前编译的,编译结果也不能在分布式系统上进行移植,做过前端项目部署的同学,也会发现,我们将项目编译完成之后是个dist文件,之后将这整个文件直接放在web...答,3个LHS和3个RHS LHS 函数里面隐藏的people = 'naug'(隐式变量分配),当调用together('naug')时,需要将实参naug赋值给形参people,所以对people需要进行...LHS操作 对于girlFriend = people ,中,girlFriend在赋值操作的左边,即将该变量往该作用域空间所在内存区间储值,也就是进行LHS操作 luckyGirl = ......对于作用域的分析可以看一下这篇文章关于JS中的作用域中的沉思,这里想说的是LHS和RHS都会在当前执行作用域中开始,如果有需要(也就是说他们没有找到所需的标识符),就会向上级作用域继续查找目标标识符,依次上升一次作用域
只不过在高级语言中,把指针隐藏了,直接用变量代替指针。 所以一个简单的赋值,其在计算机底层实现上,都是很复杂的。...(4)将字符串变成真正的 JS 代码 每一个函数调用,都会在函数上下文堆栈中创建帧。栈是一个基本的数据结构。 为什么函数执行要在栈中执行呢?...第二步:将存储的字符串复制一份到新开辟的栈内存中,使其变为真正的 JS 代码。 第三步:先对形参进行赋值,再进行变量提升,比如将 var function 变量提升。...不像 lisp 那种在运行时才能确定作用域。 3、执行环境,上下文环境是一种什么样的存在 执行环境的数据结构是栈结构,其实本质上是给一个数组增加一些属性和方法。...6、作用域链的本质是链表 通过比较 A 图和 B 图的 scopeChain ,可以确定的是: 作用域链本质就是链表,执行哪个函数,链表就初始化为哪个函数的作用域,然后将该函数的 [scope] 放在表头
全局作用域有个弊端:如果我们写了很多行 JS 代码,变量定义都没有用函数包括,那么它们就全部都在全局作用域中。这样就会 污染全局命名空间, 容易引起命名冲突。...因为放在里面的所有变量,都不会被外泄和暴露,不会污染到外面,不会对其他的库或者 JS 脚本造成影响。这是函数作用域的一个体现。...在块语句中定义的变量将保留在它们已经存在的作用域中。...); // logs 'Hammad' JS 的初学者经常需要花点时间才能习惯变量提升,而如果不理解这种特有行为,就可能导致bug 。...——要到创建 fn 函数的那个作用域中取,无论 fn 函数将在哪里调用。 所以,不要在用以上说法了。相比而言,用这句话描述会更加贴切: “要到创建这个函数的那个域”。
将数据和行为捆绑为有一个充满想象力的名字:封装。...正如第 6 章讨论的,这是因为我们关心的是值的可变性,值可变是值本身的特性,不在于在哪里或者如何被赋值的。...私有 当对比分析闭包和对象时可能你思考的第一个区分点就是闭包通过词法作用域提供“私有”状态,而对象将一切做为公共属性暴露。这种私有有一个精致的名字:信息隐藏。...Change Control 变更控制 如果词法变量被隐藏在一个闭包中,只有闭包内部的代码才能自由的重新赋值,在外部修改 x 是不可能的。...词法(作用域)在重新赋值上的局部就近原则是为什么我不认为 const 是一个有帮助的特性的一个重要原因。作用域(例如闭包)通常应该尽可能小,这意味着重新赋值只会影响少许代码。
作用域(scope)的分类 在这门语言中,采用词法作用域;也就是当你在写代码时将变量和块级作用域写在哪里来决定的。(ps:可理解为静态作用域)。 与静态作用域相对的是动态作用域。...function foo(){ innerValueB=4 //会先在window对象上创建一个innerValueB属性再赋值 console.log('foo'...局部变量 a function next(){ var b=a; console.log(b); } } 函数作用域会隐藏内部的实现...当函数执行完毕,内部变量的生命周期也会随之结束(ps:闭包除外)不会污染外部作用域。 块级作用域 块级作用域在ES5是没有这样的概念的,但ES6的一些语法为js新增色彩。...这也验证了js是静态作用域的概念。它和执行上下文是两个不同的概念。(ps:勿混淆) 执行上下文是根据在哪里调用执行确定执行上文,它是动态的。切记切记!!
JavaScript 解释器中存在一种变量声明被提升的机制,也就是说函数声明会被提升到作用域的最前面,即使写代码的时候是写在最后面,也还是会被提升至最前面。...而用函数表达式创建的函数是在运行时进行赋值,且要等到表达式赋值完成后才能调用 var getName//变量被提升,此时为undefined getName()//oaoafly 函数被提升...当然我们最后要给一个总结:Javascript中函数声明和函数表达式是存在区别的,函数声明在JS解析时进行函数提升,因此在同一个作用域内,不管函数声明在哪里定义,该函数都可以进行调用。...而函数表达式的值是在JS运行时确定,并且在表达式赋值完成后,该函数才能调用。这个微小的区别,可能会导致JS代码出现意想不到的bug,让你陷入莫名的陷阱中。
领取专属 10元无门槛券
手把手带您无忧上云