Javascript中声明变量和变量的作用域

202 1 年前
Javascript 的变量是松散类型的,所谓松散类型就是可以用来保存任何类型的数据。换句话说,每个变量仅仅是一个用于保存值的占位符而已。

在说变量之前我们先了解 Javascript 中的作用域(Scope)

JavaScript 作用域

Javascript 作用域为在某执行上下文可以访问的所有标识符(变量,对象,函数等)的集合。有全局作用域局部作用域块级作用域

JavaScript 全局作用域

该作用域下的标识符在当前整个执行上下文中都可以访问

JavaScript 局部作用域

该作用域下的标识符只在当前局部执行上下文中可以访问,比如函数内部

JavaScript 块级作用域

块级作用域是ES6引入的概念,表示只在当前代码块内能访问 { }

JavaScript 作用域链

当查找某个变量的时候,会先从当前上下文(执行环境)的变量对象中查找,如果没有找到,就会从父级执行上下文的变量中查找,一直找到全局上下文的变量对象,也就是全局对象。这样构成的链表就叫做作用域链。

大致看完作用域后我们来了解一下变量以及声明变量的相关东西

声明变量

声明变量就是定义变量,变量就是一个标识符查看标识符的定义,用于存储信息的"容器"。 使用 var let const 关键词来声明变量 大部分编程语言都是先声明变量再使用,但在javascript里并不完全如此 在函数定义之外声明的变量是全局变量,它的值可在整个程序中访问和修改。 在函数定义内声明的变量是局部变量。 每当执行函数时,都会创建和销毁该变量,且无法通过函数之外的任何代码访问该变量。使用 let const 可以声明块级作用域变量

语法

var varname1 [= value1 [, varname2 [, varname3 ... [, varnameN]]]];
var tomato;//声明变量,但没有初始化,此时carname为undefined
var carname="Volvo";//声明并初始化变量
var lastname="Doe", age=30, job="carpenter";

使用 var 声明

用 var 声明的变量作用域都是当前执行环境(全局或局部)。 用 var声明变量,不管发生在那里,声明都会提升到当前执行环境前处理(只有声明,不涉及赋值),就是传说中的声明提升。 用 var 声明的变量可以重复声明 用 var 声明变量,赋值发生在代码执行到该处时完成

console.log(a);//undefined
var a = 100;
console.log(a);100

上面代码执行等同于

var a;
console.log(a);//undefined
a = 100;
console.log(a);100
var a = 1;
function fn(a) {
    console.log(a);//1
    var a = 2;
    console.log(a);//2
}
fn(a)

上面代码先声明全局变量 a 。当fn函数执行时,建立了局部执行上下文。在这个局部执行上下文里:第一步:形参赋值(声明局部变量a,并给a赋值为1),第二步:变量声明提升(var a;)(这里允许重复声明),第三步:函数从上到下依次执行。第三步:销毁。 fn执行的过程等同于:

var a;//形参
a=1;//形参赋值
var a;//变量提升
console.log(a);//1
a = 2;
console.log(a);//2

使用 let 声明

使用 let 声明的变量为块级作用域变量,它的用法类似于var,只在当前代码块内可见。 使用 let 声明变量,不存在变量声明提升。 使用 let 声明变量,不允许重复声明。 使用 let 声明变量,声明之前该变量就在当前块作用域内锁定,不允许在声明之前使用(暂时性死区)。

var tmp = 123;
if (true) {
  tmp = 'abc'; // ReferenceError
  let tmp;
}
// 报错
function func() {
  let a = 10;
  var a = 1;
}
// 报错
function func() {
  let a = 10;
  let a = 1;
}
function f1() {
  let n = 5;
  if (true) {
    let n = 10;
  }
  console.log(n); // 5
}

使用 const 声明

const声明变量类似 let 声明,不过const声明的是一个只读的常量。一旦声明,常量的值就不能改变。

const PI = 3.1415;
PI // 3.1415

PI = 3;
// TypeError: Assignment to constant variable.

实际上 const 声明的变量并不是值不得改动,而是变量指向的那个内存地址所保存的数据不得改动。

const a = [];
a.push('Hello');// 可执行
a.length = 0;// 可执行
a = ['Dave'];//a指向另一个数组,保存的地址得修改,所以报错

其他方式声明

ES5 只有两种声明变量的方法:var命令和function命令。ES6 除了添加letconst命令,其实还有另外两种声明变量的方法:import命令和class命令。所以,ES6 一共有 6 种声明变量的方法。

更多关于 ES6 的知识请查看 阮一峰 老师的 《ECMAScript 6 入门》一书


在一个执行上下文里,函数声明和定义都会提升,但函数表达式只提升变量,如下:

function test(arg){
    console.log(arg); // [Function: arg]
    var arg = 'hello';
    function arg(){
        console.log('hello world')
    }
    console.log(arg); // hello
}
test('hi');
function fn(arg){
    console.log(arg);  // hi
    var arg = 'hello';
    var arg = function (){
        console.log('hello world')
    }
    console.log(arg); [Function: arg]
}
fn('hi');

对未声明的变量赋值,该变量会自动变成全局变量 未声明的变量不存在声明提升,只在赋值后才存在 未声明的变量变为全局后可以使用 delete 删除

var num1 = 1;
num2 = 2;
// delete num1;  无法删除
// delete num2;  删除
分类栏目
© 2018邮箱:11407215#qq.comGitHub沪ICP备12039518号-6