章节索引 :

JavaScript with

with 语句就可以扩展一个语句的作用域链。——MDN

with 可以指定代码块的作用域,特别是在访问对象成员时,它使得代码非常简洁。

1. 基本语法

with (表达式) {
  代码块;
}

表达式通常会直接给定一个对象。

var person = {
  name: '小明',
  age: 666,
  major: 'english',
};

with (person) {
  console.log(name); // 输出:"小明"
  console.log(age); // 输出:666
  console.log(major); // 输出:"english"
}

可以看到,with 代码块内输出的变量,实际上是 person 对象的属性。

在 with 语句中,访问变量会先去看这个变量是不是在给定的对象中作为属性存在,如果存在,则取对象中属性的值,否则继续往上层找。

2. 不推荐使用 with

尽管 with 很方便,但 with 会造成诸多的问题。

2.1 造成语义不明

先看这段代码:

function fn(block, height) {
  with (block) {
    console.log(height);
  }
}

这样的代码,有点让阅读代码的人难以理解具体含义。

阅读代码的时候,无法确定 height 要取 block 下的属性,还是要取形参 height。

2.2 造成污染

function fn(obj) {
  with (obj) {
    b = 1;
  }
}

这个场景其实和上面的类似,假如 obj 中没有属性 b ,则会造成上层作用域的污染。

图片描述


事实上很少有前端开发者会使用 with,在很长篇幅的代码中,with 会让代码逻辑变得不清晰,需要反复确认作用域。

尽可能的避免使用 with ,使用短变量名和合理的空行来使代码变得整洁易懂。

var family = [
  {
    seniority: '子',
    name: '小明',
    detail: {
      birth: '1192/01/22',
      sex: 'man',
      hand: 8,
      leg: 44,
      deposit: 9999,
    },
  },
];

// 不好的表述形式
family[0].detail.birth = '1122/22/11';
family[0].detail.sex = '?';
var deposit = family[0].detail.family[0].detail;


// 取出要操作的数据 并控制空行
var detail = family[0].detail;

detail.birth = '2312/22/33';
detail.sex = '未知性别';

var deposit = detail.deposit;

3. 小结

with 的使用需要谨慎,尽量在可控范围内使用。

使用 with 常见的遇到问题的情况,都是恰巧污染了上层作用域,又恰巧污染的是同名的变量,这也产生的 bug 定位也相对困难。

前端框架 Vue 将 template 转化成 render 函数的时候就用到了 with。

前置知识
什么是JavaScript 开发与学习环境准备 调试方案
基础
JavaScript 变量 JavaScript 数据类型 JavaScript if 语句 JavaScript for 语句 JavaScript 算数运算符 JavaScript 比较运算符 JavaScript 逻辑运算符 JavaScript 表达式 JavaScript 函数 JavaScript 对象 JavaScript 字符串 JavaScript 数字 JavaScript 数组 JavaScript switch 语句 JavaScript while 语句 JavaScript break与continue JavaScript with document.cookie
内置对象
JavaScript Function JavaScript Math JavaScript Date JavaScript RegExp JavaScript JSON
JavaScript 与 DOM
什么是DOM DOM和JavaScript的关系 获取和操作 DOM 节点 JavaScript DOM与事件 JavaScript DOM 事件绑定 JavaScript DOM 事件对象 JavaScript DOM 事件流 JavaScript DOM 事件优化 JavaScript DOM 自定义事件
表单处理
使用 JavaScript 校验表单
BOM
BOM window 对象 常用的 BOM 相关对象 BOM 常用属性和方法
AJAX
JavaScript AJAX
进阶知识
JavaScript 异常处理 JavaScript 三元运算符 JavaScript 逗号操作符 JavaScript void JavaScript typeof JavaScript delete JavaScript debugger JavaScript getter &setter JavaScript 原型 JavaScript new操作符和构造函数 JavaScript instanceof JavaScript this JavaScript 严格模式 JavaScript 作用域 JavaScript 闭包 JavaScript 变量提升 JavaScript 对象包装器
常用库
jQuery Lodash moment.js swiper
进阶指南
ECMAScript6 Node.js Babel CSS 预处理器 代码规范 TypeScript Web Components 小程序 Vue / React / Angular JavaScript 关键字
常见疑点与误区
分号问题 对象属性访问问题 this 使用问题 浮点数精度问题 独一无二的 NaN 避免全局污染 控制台观察对象问题 根据环境选择语言特性
扩展
相关资源