一、声明提前
javaScript在执行代码的时候会将所有的var声明的变量,放在作用域的顶部集中创建,赋值留在原地Tip:function声明函数的优先级最高,放在最顶部,再是声明的变量
**
- 把变量的声明提升到当前作用域的最前面,只会提升声明,不会提升赋值。
- 把函数的声明提升到当前作用域的最前面,只会提升声明,不会提升调用。
- 函数声明和变量声明都会置顶,但是变量声明位于函数声明之后**
实战题
(1)
var a = 100;
function a(){
console.log("hello")
}
a();
//报错
(2)
var a = 100;
var a = function(){
console.log("hello world")
}
a()
//hello world
(3)
var a = 100;
function bar(){
console.log(a)
if(!a){
var a = 20;
}
console.log(a)
}
bar()
//undefined
//20
Tip:{}里面为一个作用域
//console.log(a);
//var a = 20;
//function a(){
console.log("a");
}
//console.log(a);
拆分:
var a = function(){
console.log("a")
}
var a;
console.log(a); 变量a输出undefined,不会覆盖函数,输出函数
a = 20;
console.log(a); 变量a赋值后,将函数覆盖,输出20
a();
二、作用域
在 JavaScript 中, 对象和函数同样也是变量。
在 JavaScript 中, 作用域为可访问变量,对象,函数的集合。
JavaScript 函数作用域: 作用域在函数内修改。
2-1 局部变量
变量在函数内声明,变量为局部变量。
局部变量:只在固定的代码片段内可访问到的变量
// 此处不能调用 carName 变量
function myFunction() {
var carName = "Volvo";
// 函数内可调用 carName 变量
}
2-2 全局变量
变量在函数外定义,即为全局变量。
在任何地方都可以访问到的变量就是全局变量,对应全局作用域。在函数外声明。
var carName = " Volvo";
// 此处可调用 carName 变量
function myFunction() {
// 函数内可调用 carName 变量
}
如果变量在函数内没有声明(没有使用 var 关键字),该变量为全局变量。
以下实例中 carName 在函数内,但是为全局变量。
// 此处可调用 carName 变量
function myFunction() {
carName = "Volvo";
// 此处可调用 carName 变量
}
2-3 HTML 中的全局变量
在 HTML 中, 全局变量是 window 对象: 所有数据变量都属于 window 对象。
//此处可使用 window.carName
function myFunction() {
carName = "Volvo";
}
2-4 块级作用域
- 从es6开始,js引入了块级作用域的概念,所谓块级作用域,就是声明在{}里面的变量
- 只有let const声明的变量才有块级作用域,var 声明的变量是没有块级作用域的
- 在同一个块里面,let的变量只能声明一次
{
let a = 1; //局部变量
}
{
//使用const声明的常量他的内存地址不可以被修改
const b = {name:"haha"}; //局部变量
b.name = "xx";
}
{
var kk = 123; //全局变量
}
console.log(kk); //123
console.log(a); //a is not defined
2-5 作用域链
- 只有函数可以制造作用域结构。凡是代码中有函数,那么这个函数就构成另一个作用域。如果函数中还有函数,那么在这个作用域中就又可以诞生一个作用域。
- 将这样的所有的作用域列出来,可以有一个结构: 函数内指向函数外的链式结构。就称作作用域链。
- 作用域链: 变量的使用,从里向外,层层的搜索,搜索到了就可以直接使用了。层层搜索,搜索到0级作用域的时候,如果还是没有找到这个变量,结果就是报错
案例:
// 案例2
function f1() {
var num = 123;
function f2() {
console.log( num );
}
f2();
}
var num = 456;
f1();