美文网首页码农的世界程序员
你不知道的JavaScript(二)|作用域和闭包

你不知道的JavaScript(二)|作用域和闭包

作者: xpwei | 来源:发表于2017-09-25 18:02 被阅读29次

词法阶段
简单地说,词法作用域就是定义在词法阶段的作用域。换句话说,词法作用域是由你在写代码时将变量和块作用域写在哪里来决定的,因此当词法分析器处理代码时会保持作用域不变(大部分情况下是这样的)。


以上,[1]包含着整个全局作用域,其中只有一个标示符:foo。[2]包含着foo所创建的作用域,其中有三个标示符:a、bar、b。[3]包含着bar所创建的作用域,其中只有一个标示符:c。
注意,以上的气泡是严格包含的。没有任何函数的气泡可以(部分地)同时出现在两个外部作用域的气泡中,就如同没有任何函数可以部分地同时出现在两个父级函数中一样。
作用域查找会在找到第一个匹配的标示符时停止。在多层的嵌套作用域中可以定义同名的标示符,这叫做“遮蔽效应”(内部的标示符“遮蔽”了外部的标示符)。抛开遮蔽效应,作用域查找始终从运行时所处的最内部作用域开始,逐级向外或者说向上进行,直到遇见第一个匹配的标示符为止。

欺骗词法
如果词法作用域完全由写代码期间函数所声明的位置来定义,怎样才能在运行时来“修改”(也可以说欺骗)词法作用域呢?
欺骗词法作用域会导致性能下降。
【方法一:eval】

function foo(str, a) {
  eval( str ); // 欺骗!
  console.log( a, b );
}
var b = 2;
foo( "var b = 3;", 1 ); // 1, 3

但在严格模式的程序中,eval(..)在运行时有其自己的词法作用域,意味着其中的声明无法修改所在的作用域。

function foo(str) {
  "use strict";
  eval( str );
  console.log( a ); // ReferenceError: a is not defined
}
foo( "var a = 2" );

【方法二:with】
可以有很多方法来解释with,在这里选择从这个角度来解释它:它如何同被它所影响的词法作用域进行交互。
with通常被当做重复引用同一个对象中的多个属性的快捷方式,可以不需要重读引用对象本身。如:

var obj = {
  a: 1,
  b: 2,
  c: 3
};
// 单调乏味的重复"obj"
obj.a = 2;
obj.b = 3;
obj.c = 4;
// 简单的快捷方式
with (obj) {
  a = 3;
  b = 4;
  c = 5;
}

但实际上这不仅仅是为了方便地访问对象属性。考虑如下代码:

function foo(obj) {
  with (obj) {
  a = 2;
  }
}
var o1 = {
a: 3
};
var o2 = {
  b: 3
};
foo( o1 );
console.log( o1.a ); // 2
foo( o2 );
console.log( o2.a ); // undefined
console.log( a ); // 2——不好,a 被泄漏到全局作用域上了!

eval(..)函数如果接受了含有一个或多个声明的代码,就会修改其所处的词法作用域,而with声明实际上是根据你传递给它的对象凭空创建了一个全新的词法作用域。
另外一个不推荐使用eval(..)和with的原因是会被严格模式所影响(限制)。with被完全禁止,而在保留核心功能的前提下,间接或非安全地使用eval(..)也被禁止了。

人生不相见,动如参与商

相关文章

  • 2018-01-07 关于javascript闭包和作用域的理解

    关于 javascript 闭包的一些思考 作用域 词法作用域 函数作用域 块作用域 闭包 什么是作用域? 作用域...

  • 学习JavaScript闭包和作用域笔记

    JS JavaScript闭包和作用域 闭包 JavaScript高级程序设计中对闭包的定义:闭包是指有权访问另外...

  • 技术栈

    一、HTML、CSS基础、JavaScript语法基础。 二、JavaScript语法进阶。包括:作用域和闭包、t...

  • 2020前端技术栈

    一、HTML、CSS基础、JavaScript语法基础。二、JavaScript语法进阶。包括:作用域和闭包、th...

  • JavaScript 函数闭包(colsure)

    理解闭包,你首先必须理解JS的变量作用域,JavaScript作用域和作用域链。 ES6之前,变量的作用域分为全局...

  • 你不可不知道的 JavaScript 作用域和闭包

    原文出处:JavaScript Scope and Closures 作用域和闭包是 JavaScript 中重要...

  • 作用域和闭包

    目录 概述 作用域编译过程词法作用域全局作用域函数作用域 闭包循环和闭包闭包的用途性能 总结 概述 作用域和闭包一...

  • JavaScript中的闭包

    1.什么是闭包 要理解什么是闭包,就得先理解变量的作用域。在JavaScript中,有两种作用域,全局作用域和函数...

  • 2018-07-11

    深入理解闭包: 一、变量的作用域 要理解闭包,首先必须理解Javascript特殊的变量作用域。 变量的作用域无非...

  • 作用域、作用域链、闭包、面向对象、执行上下文

    作用域 作用域链 函数的提前声明 闭包 JavaScript 闭包与类(原型链)之间的开发方式 构造函数和普通函数...

网友评论

    本文标题:你不知道的JavaScript(二)|作用域和闭包

    本文链接:https://www.haomeiwen.com/subject/sbsdextx.html