ZetCode

JavaScript with() 方法

最后修改于 2025 年 4 月 4 日

在本文中,我们将展示如何在 JavaScript 中使用 with 语句。with 语句为语句扩展作用域链。

with 语句

with 语句为代码块扩展作用域链。它允许您访问对象的属性,而无需重复对象引用。语法为:with (expression) statement

虽然它可以使代码更短,但在现代 JavaScript 中不建议使用 with 语句。它使代码更难以优化,并且可能导致令人困惑的作用域问题。在严格模式下,不允许使用 with 语句。

with 语句将给定的对象添加到作用域链的头部。当查找变量名时,JavaScript 首先检查此对象。如果未找到该属性,它将继续搜索正常的作用域链。

基本 with 示例

以下示例演示了 with 语句的基本用法。

main.js
const person = {
    firstName: 'John',
    lastName: 'Doe',
    age: 30
};

with (person) {
    console.log(firstName);  // John
    console.log(lastName);   // Doe
    console.log(age);        // 30
}

我们创建一个 person 对象,并使用 with 来访问其属性。在代码块内,我们可以直接引用属性,而无需对象名称。首先在 person 对象中查找属性。

$ node main.js
John
Doe
30

with 语句和变量作用域

with 语句会影响变量查找,但不会改变作用域。

main.js
const settings = { color: 'blue' };
const color = 'red';

with (settings) {
    console.log(color);  // blue (from settings)
    console.log(window.color);  // red (global)
}

console.log(color);  // red (global)

我们演示了 with 如何影响变量查找。在代码块内,color 指的是 settings 属性。在外部,它指的是全局变量。要访问内部的全局变量,我们使用 window.color

$ node main.js
blue
red
red

with 语句和函数调用

with 代码块内的函数调用可能会产生意想不到的行为。

main.js
const utils = {
    log: function(message) {
        console.log('Utils:', message);
    }
};

function log(message) {
    console.log('Global:', message);
}

with (utils) {
    log('Hello');  // Which log function is called?
}

我们在 utils 对象和全局作用域中都有一个 log 函数。在 with 代码块内,JavaScript 首先检查 utils 对象是否有 log。由于它存在于那里,因此调用该版本,而不是全局版本。

$ node main.js
Utils: Hello

with 语句和赋值

with 代码块内的赋值可能模棱两可。

main.js
const config = { debug: false };

with (config) {
    debug = true;  // Modifies config.debug
    verbose = true; // Creates global variable!
}

console.log(config.debug);  // true
console.log(config.verbose); // undefined
console.log(verbose);       // true (global)

我们展示了赋值在 with 代码块中的工作方式。如果属性存在于对象上,则对其进行修改。如果不是,则创建一个全局变量(在非严格模式下)。这种行为可能导致错误,这也是不鼓励使用 with 的原因之一。

$ node main.js
true
undefined
true

嵌套 with 语句

可以嵌套多个 with 语句,内部语句优先。

main.js
const outer = { prop: 'outer' };
const inner = { prop: 'inner' };

with (outer) {
    console.log(prop);  // outer
    
    with (inner) {
        console.log(prop);  // inner
    }
    
    console.log(prop);  // outer
}

我们演示了嵌套的 with 语句。内部代码块的对象在属性查找时具有优先权。在内部代码块结束后,查找将恢复到使用外部对象。这表明 with 如何暂时影响作用域链。

$ node main.js
outer
inner
outer

来源

with 语句 - 语言参考

在本文中,我们演示了如何在 JavaScript 中使用 with 语句。虽然它可以缩短代码,但由于潜在的作用域和性能问题,通常不建议使用它。

作者

我叫 Jan Bodnar,是一位热衷于编程并拥有丰富编程经验的程序员。自 2007 年以来,我一直在撰写编程文章。到目前为止,我撰写了 1,400 多篇文章和 8 本电子书。我拥有十多年教授编程的经验。

列出 所有 JS 数组函数。