每日一题(十八)var foo = function bar (){ return 12; } console.log(typeof bar());

本文通过一个具体的JavaScript代码示例,深入探讨了命名函数表达式的作用域问题,解释了为什么直接调用函数名会引发'bar is not defined'错误,并阐述了函数作用域的有效范围。

题目描述:写出执行结果并解释原因

var foo = function bar (){
    return 12;
}

console.log(typeof bar());

答案:

//报错
Uncaught ReferenceError: bar is not defined

解析:

  • 这种命名函数表达式函数只能在函数体内有效
<think>我们正在讨论JavaScript中的`var`和`function`关键字。根据用户的问题,他们想了解这两个关键字的含义。同时,我们需要注意用户提供的引用内容(引用[1]到[引用4])以及之前的对话历史(关于`const`的详细解释)。 首先,我们整理一下关于`var`关键字的要点(根据引用内容): 1. var关键字用于声明变量,是ES5及之前版本的常用方式。 2. var的作用域是函数作用域(function scope),即在函数内部声明的变量只在该函数内部有效。 3. var存在变量提升(hoisting)现象:变量可以在声明之前被访问,但值为undefined。 4. 在全局作用域中,使用var声明的变量会成为window对象的属性(在浏览器环境中)。 5. 在非严格模式下,省略关键字直接赋值会创建全局变量(不推荐)。 然后,关于`function`关键字: 在JavaScript中,`function`关键字用于声明函数。函数声明也有提升现象,且提升的是整个函数(包括函数体)。 我们需要将这两个关键字的含义、特性、区别以及注意事项进行清晰说明。 回答结构建议: 1. 分别解释`var`和`function`关键字的含义和基本用法。 2. 详细说明它们的特性(如作用域、提升等)。 3. 对比它们之间的异同点(如果有)。 4. 提供示例代码说明。 5. 给出一些注意事项和最佳实践。 根据引用内容(特别是引用[2]和[引用3]),我们可以补充细节。 另外,由于用户之前询问了`const`,我们可以适当提及`var`与`let`/`const`的区别(但重点在`var`和`function`)。 最后,生成相关问题。 注意:用户要求使用中文回答,并且在回答中引用的段落末尾自然地添加引用标识。同时,数学表达式和公式按照要求处理(虽然本问题可能涉及不多,但如果有的话要注意格式)。 开始构建回答: 第一部分:var关键字 - 含义:用于声明变量,可以是局部变量(函数作用域)或全局变量。 - 特性: 1. 函数作用域:在函数内部声明的变量,只能在该函数内部访问。 2. 变量提升:var声明的变量会被提升到所在作用域的顶部,但赋值不会提升(所以提前访问得到undefined)。 3. 全局变量:在全局作用域中用var声明的变量会成为window对象的属性(浏览器环境)。 4. 重复声明:允许重复声明同一个变量名,不会报错。 5. 省略关键字:在非严格模式下,未声明直接赋值会创建全局变量(严格模式下会报错)。 第二部分:function关键字 - 含义:用于声明函数,有两种形式:函数声明和函数表达式。 - 函数声明:function 函数名(参数) { 函数体 } - 函数表达式:将函数赋值给一个变量(此时变量的声明方式可以是var、let、const等)。 - 特性: 1. 函数声明提升:函数声明会被提升到作用域顶部,因此可以在声明之前调用。 2. 作用域:函数有自己的作用域,在函数内部声明的变量(使用var)在函数外部不可访问。 3. 函数表达式不会提升:如果使用函数表达式,则变量声明会提升(如果是var则提升为undefined),但函数赋值不会提升,因此在赋值前调用会报错。 第三部分:varfunction的关联 - 在函数内部,可以使用var声明变量,使用function声明函数,它们都会发生提升,但函数提升优先于变量提升。 - 示例:在同一个作用域内,函数声明和var声明同一个标识符,函数声明会覆盖变量声明(但注意,如果变量被赋值,则赋值会覆盖函数)。 第四部分:注意事项和最佳实践 - 由于var的函数作用域和提升特性可能导致一些问题(如循环中的变量泄露到外部),ES6引入了let和const,推荐使用块级作用域。 - 函数声明和函数表达式的选择:函数声明适用于需要提升的场景(但通常建议先声明后使用),函数表达式更灵活(如可以赋值给变量,可以作为参数传递等)。 - 在严格模式下('use strict')使用JavaScript,避免省略关键字导致的全局变量。 示例代码: 1. var的变量提升: ```javascript console.log(a); // 输出: undefined var a = 10; ``` 2. 函数声明提升: ```javascript foo(); // 输出: "Hello" function foo() { console.log("Hello"); } ``` 3. 函数表达式不会提升: ```javascript bar(); // 报错: bar is not a function var bar = function() { console.log("World"); }; ``` 4. 函数提升优先于变量提升: ```javascript console.log(typeof myFunc); // 输出: "function" var myFunc; function myFunc() {} ``` 5. var在循环中的问题: ```javascript for (var i = 0; i < 3; i++) { setTimeout(function() { console.log(i); }, 100); } // 输出:3, 3, 3 (因为i是函数作用域,循环结束后i=3,所有回调都引用同一个i) ``` 对比使用let的循环(块级作用域): ```javascript for (let j = 0; j < 3; j++) { setTimeout(function() { console.log(j); }, 100); } // 输出:0, 1, 2 ``` 最后,生成相关问题。 注意:在回答中适当引用用户提供的引用内容(如引用[2]和[引用3]中提到的作用域和提升)。 </think>### JavaScript 中 `var` 和 `function` 关键字的含义详解 #### 一、`var` 关键字(变量声明) `var` 是 JavaScript ES5 及之前版本声明变量的主要方式,具有以下核心特性: 1. **函数作用域** 使用 `var` 声明的变量仅在**函数内部有效**(函数作用域),在函数外部访问会报错[^2][^3]: ```javascript function test() { var message = "Hello"; } test(); console.log(message); // ❌ ReferenceError: message is not defined ``` 2. **变量提升(Hoisting)** `var` 声明的变量会被提升到作用域顶部,但**仅提升声明而不提升赋值**,导致访问未赋值变量返回 `undefined`[^3][^4]: ```javascript console.log(x); // ✅ 输出: undefined (不会报错) var x = 10; // 实际执行顺序: // var x; // 声明提升到顶部 // console.log(x); // undefined // x = 10; // 赋值保留原位 ``` 3. **全局作用域特性** 在全局作用域或函数内省略 `var` 时,变量会**自动成为全局变量**(严格模式下禁止)[^3]: ```javascript function createGlobal() { globalVar = "I'm global!"; // 未用 var 声明 } createGlobal(); console.log(globalVar); // ✅ 输出: "I'm global!" ``` 4. **重复声明与覆盖** 允许重复声明同名变量,且不会报错[^3]: ```javascript var a = 1; var a = 2; // ✅ 允许 console.log(a); // 输出: 2 ``` #### 二、`function` 关键字(函数声明) `function` 用于声明函数,具有独特的行为特征: 1. **函数提升(完整提升)** 函数声明整体提升到作用域顶部,**包括函数体**,可在声明前调用[^1]: ```javascript greet(); // ✅ 输出: "Hello!" (正常执行) function greet() { console.log("Hello!"); } ``` 2. **创建独立作用域** 函数内部形成独立作用域,保护内部变量不被外部访问: ```javascript function counter() { var count = 0; // 受保护的变量 return function() { return ++count; }; } const c = counter(); console.log(c()); // 输出: 1 console.log(count); // ❌ ReferenceError (外部不可访问) ``` 3. **函数声明 vs 函数表达式** `function` 关键字可用于两种形式: ```javascript // 函数声明(整体提升) function sum(a, b) { return a + b; } // 函数表达式(仅变量提升) var multiply = function(a, b) { return a * b; }; console.log(multiply(2,3)); // ✅ 输出: 6 console.log(multiply); // ❌ 声明前访问: undefined ``` #### 三、`var` 与 `function` 的关键差异 | 特性 | `var` | `function` | |--------------------|--------------------------------|---------------------------------| | **作用域** | 函数作用域 | 函数作用域 | | **提升行为** | 仅声明提升(赋值不提升) | 整体提升(声明+函数体) | | **重复声明** | 允许且覆盖原有值 | 允许且覆盖原有函数 | | **全局属性** | 成为 `window` 对象的属性 | 成为 `window` 对象的方法 | | **块级作用域支持** | ✗ 不受 `{}` 块限制 | ✗ 不受 `{}` 块限制 | #### 四、注意事项与最佳实践 1. **避免使用 `var`** 因变量提升和函数作用域易导致逻辑错误(如循环计数器泄露)[^3]: ```javascript for (var i = 0; i < 3; i++) { setTimeout(() => console.log(i), 100); } // 输出: 3, 3, 3 (而非预期的 0,1,2) ``` 2. **优先使用函数声明** 需在定义前调用函数时,函数声明更安全: ```javascript // ✅ 函数声明安全调用 initPage(); function initPage() { /* ... */ } // ❌ 函数表达式导致错误 setup(); var setup = function() { /* ... */ }; // TypeError ``` 3. **严格模式约束** 启用 `'use strict'` 可禁止隐式全局变量: ```javascript 'use strict'; function test() { undeclaredVar = 10; // ❌ ReferenceError } ``` --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值