javascript 中 var let const 的区别

 

变量的命名

 

变量名称对大小写敏感 test和Test是不一样的,必须严格一样,才算是一个变量的;
如在javascript里,onclick 必须要写出onclick,不能写成onClick;)
如:var mood = "happy"; MOOD=“sad”; 他们是两个不同的变量进行赋值

变量不能是系统关键字和保留字 ,比如 true、if、while、class 等。 let class = 'houdunren';
变量名由:字母 ,
下划线,
$
数字
第一个字母必须是 “字母,下划线,或$”

正确命名:尽量取有意义的英文名或英文缩写
i
lvye_study
_lvye
$str
n123

通常驼峰格式是函数名,方法名,和对象属性命名的首选格式 var myMood = "hapy"



变量能保存的数据类型 很多种
变量:未知数 存储一个值 这个值可以发生改变
变量是松散型的,意思是变量可以保存任何类型的数据,每个变量只不过是一个用于 保存任意值的命名占位符

如数字 字符串
//当向变量分配文本值时,应该用双引号或单引号包围这个值。
//当向变量赋的值是数值时,不要使用引号。如果您用引号包围数值,该值会被作为文本来处理。
var pi=3.14;            //3.14
var person="John Doe"; //John Doe
var answer='Yes I am!';//Yes I am!

 

<script>
  // 在JS中变量类型由所引用的值决定    (弱类型)
var web = "hhhh";
console.log(typeof web); //string
web = 99;
console.log(typeof web); //number
web = {};
console.log(typeof web); //object
</script>
可通过typeof来检测;通过检测可以知道这个变量所代表的值是一个字符串类型的数据;
    var name=" 琪琪",
    gender;
    console.log(name,typeof name); //琪琪string
    console.log(gender,typeof gender); //undefined "undefined

 虽然关键字var不是必须的,但是最好每次声明一个新变量都加上;

 需要注意的是变量本身是没有意义的,只是数据的媒介(代号),我们说的变量默认是这个变量名所代表的数据,并不是这个变量名本身;这点需要注意的;



变量声明

javascript的变量都是由var 声明,

 

语法: var 变量名 = 值

 

复制代码
 <script>
    //因为变量的值是可以改变的,所以在变量声明和赋值的时候,后面的会覆盖前面的。  输出变量,一定不要加引号
    var a = 10;     document.write(a); //10     
    var b = 20;     b = b + 1;     document.write(b); //21  在原来的基础上+1    
    var c = 10;     c = 16;     document.write(c); //16 后面的会覆盖前面的    
    var d = 10;     d = d + 1;     d = d - 6;     document.write(d); //5   
    
    //可以同时声明多个变量
    var a=6,b=9;
    console.log(b);//9

     //变量可以更换不同类型的数据  
    var n= 'hhhhhh';
    console.log(typeof n);//string
    
    f = 18;
    console.log(typeof f);//number 
   </script>
复制代码

 

注意变量的声明和定义是两回事;

 

复制代码
复制代码
 var name;        //变量声明
    name="琪琪";     //变量定义
    var name="琪琪"; //变量声明+定义

    //分析var name="琪琪";  分两步走
    第一步 var name;先声明一个name的变量;
    第二步 name="琪琪" 创建数据"琪琪"这个字符串,
          并且把字符串"琪琪"这条数据赋值给name这个变量;
          在定义(赋值)变量的name值;
          
  这个时候name的类型就是所代表值的类型;
复制代码
复制代码

例子
创建了名为 carname 的变量,并向其赋值 "Matt",然后把它放入 id="demo" 的 HTML 段落中

<body>
    <p>点击这里创建变量,并显示结果</p>
    <button onclick="myFunction()">点我</button>
    <p id="demo"></p>

    <script>
        function myFunction(){
            var carmame="Matt";
            document.getElementById("demo").innerHTML=carmame;
        }
    </script>
</body>

 


Value = undefined

//未使用值来声明的变量,其值实际上是 undefined。
var a;
console.log(a);//undefined

 

 


 

 


变量提升   (函数声明和变量声明总是会被解释器悄悄地被"提升"到方法体的最顶部)
变量可以先使用后声明  不会报错   会显示undefinde

function foo(){
    console.log(age);
    var age=26;
}
foo();//undefinde

//等价于下面这个代码 
function foo(){
    var age;
    console.log(age);
    age=26;
}
foo(); //undefined
 function test(){
    console.log(value);
  }
  test();//undefined
  var value="123";
  test();//123

  //等价于下面这个代码
var value;
function test(){
  console.log(value);
}
test();
value="123";
test();
  function test(){
    console.log(value);//undefined
    var value="456";
    console.log(value);//456
  }
  var value="123";
  test();

  //等价于下面的写法
function test(){
  var value;
  console.log(value);
  value="456";
  console.log(value);
}
var value="123";
test();
function test(condition){
     if(condition){
       var value="123";
       console.log(value);
     }else{
       console.log(value);//undefined
     }
   }
   test(false);

 /*   condition为false,进入了test函数的else分支,此时并没有定义value,
   但是打印出来仍然是undefined,而不是报错,在预编译阶段,
   javascript引擎将上面的代码修改成下面这样, */

   function test(condition){
     var value;
     if(condition){
       value="123";
       console.log(value);
     }else{
       console.log(value);
     }
   }
   test(false);

 
在循环条件中声明的变量i,在循环体外面,仍然可以访问

 for(var i=0;i<5;i++){}
    console.log(i);//5

 
反复多次使用var声明同一个变量是可以的  值会后面的覆盖前面的

function foo(){
     var age = 16;
     var age=15;
     var age=9;
     console.log(age);//9
   }
   foo();

 


 

 

ES2015(ES6) 新增加了两个重要的 JavaScript 关键字: letconst

 

let 声明的变量只在 let 命令所在的代码块内有效。

 

const 声明一个只读的常量,一旦声明,常量的值就不能改变。

 

在 ES6 之前,JavaScript 只有两种作用域: 全局变量函数内的局部变量

在函数外声明的变量作用域是全局的: 在 JavaScript 程序的任何地方都可以访问。

<body>
    <p>全局变量在任何脚本和函数内均可访问</p>
    <p id="demo"></p>

    <script>
        
    var carname = "Matt";
    function myFunction(){
        document.getElementById("demo").innerHTML="我可以显示"+carname;
    }
    myFunction();

    </script>
  
</body>

 

 

在函数内声明的变量作用域是局部的(函数内): 函数内使用 var 声明的变量只能在函数内容访问,如果不使用 var 则是全局变量

<body>
    <p>局部变量在声明的函数外不可以访问</p>
    <p id="demo"></p>
    <script>
    document.getElementById("demo").innerHTML="carname的类型是" +typeof carname;
    function myFunction(){
        var carname = "Matt";
    }
    myFunction();

    </script>
</body>

 

let 声明
let有四大主要特性:存在块级作用域没有变量提升暂时性死区不允许重复声明。 这和var的变量特性都相反的

存在块级作用域
使用 var 关键字声明的变量不具备块级作用域的特性,它在 {} 外依然能被访问到。     在 ES6 之前,是没有块级作用域的概念的。  如果要实现块级作用域 借助立即执行匿名函数来实现

使用let 关键字来实现块级作用域。

 <script>
        {
          var a=1;
        }
       console.log(a);//1  可以使用变量a

       //如果要实现块级作用域,通常借助立即执行匿名函数来实现:
       (function(){
            var a = 1;
        }());
       console.log(a);//出错,not defined 

       //let 关键字来实现块级作用域。
      //let 声明的变量只在 let 命令所在的代码块 {} 内有效,在 {} 之外不能访问。
      {
       let a = 1;
      }
     console.log(a); //出错, not defined */

    </script>

 
没有变量提升

//var 关键字定义的变量可以先使用再声明 , 因为变量提升
console.log(a); //undefined
var a =1;

//let 关键字定义的变量必须需要先声明再使用。不可以先使用再声明会 这样会报错
console.log(a); //出错, not defined
let a = 1; 

 

 

 
暂时性死区

var a = 1;
if(true){
  a = 2; 
var a;
console.log(a);//var允许重复声明,而且变量提升,故a=2正常赋值
}

//在块级作用域内,若存在用let命令声明的变量,则所在区块对该变量形成封闭作用域,
//也就是该变量无视外部的同名变量。而又因为不存在变量提升,所以在该区块中,不能在声明前使用该变量。
var a  = 1;
if(true){
  a = 2; 
  let a; 
console.log(a);//出错 not defined
} 

 不允许重复声明

//var 关键字声明的变量在任何地方都可以修改 ,且后面的会覆盖前面的
var x = 2;//合法
var x = 3;//合法
console.log(x);//3


//let 不允许同一个块作用域中出现沉余声明 
let x = 2;       // 合法
let x = 3;       // 不合法

{
    let x = 4;   // 合法
    let x = 5;   // 不合法
}


// let var 在同一个块作用域中混用也会报错
var x = 2;       // 合法
let x = 3;       // 不合法

{
    var x = 4;   // 合法
    let x = 5   // 不合法
}

let x = 2;       // 合法
var x = 3;       // 不合法

{
    let x = 4;   // 合法
    var x = 5;   // 不合法
}


//let 关键字在不同作用域,或不同块级作用域中是可以重新声明赋值的:
let x = 2;       // 合法

{
    let x = 3;   // 合法
}

{
    let x = 4;   // 合法
}
//也就是嵌套使用相同的标识符不会报错 ,因为同一个块中没有重复声明
var name="LiLi";
   console.log(name);//LiLi
   if(true){
       var name="Mi";
       console.log(name);//Mi
   }

   let age=30;
   console.log(age);//30
   if(true){
       let age=26;
       console.log(age);//26
   } 

 



循环作用域

<body>
    <p id="demo"></p>
 <script>
//使用 var 关键字,它声明的变量是全局的,包括循环体内与循环体外。
var i=5;
for(var i=0;i<10;i++){
    //一些代码
}
document.getElementById("demo").innerHTML=i; //10

//使用 let 关键字, 它声明的变量作用域只在循环体内,循环体外的变量不受影响。 
let i=5;
for(let i=0;i<10;i++){
 //一些代码
}
document.getElementById("demo").innerHTML=i;//5

</script>
</body>

 

 

 

//for循环的计数器,就很合适使用let。
var a = [];
for (var i = 0; i < 10; i++) {
a[i] = function() {
console.log(i);
}
}
a[6](); // 10

//变量i是var声明的,在全局范围内有效,所以每次循环新的i值都会覆盖旧值,导致最后输出的是最后一轮的i的值。
var a = [];
for (let i = 0; i < 10; i++) {
a[i] = function() {
console.log(i);
}
}
a[5](); // 5
//使用let,声明的变量仅在块级作用域内有效,最后输出的是5。

 

/* 
输出: 
outer:0
    outer:1
    outer:2
    outer:3
index:4,msg:undefined
    index:4,msg:undefined
    index:4,msg:undefined
    index:4,msg:undefined

原因:
  setTimeout的执行方式是异步执行
  JavaScript 是单线程的,遇到setTimeout后会另开一条线程
  执行setTimeout里的代码时,同步代码for循环已经执行完成
  整个循环中只有一个i,i被for循环以及三个回调函数共用,循环结束后i=4,已经超出了原本数组的范围
把var 改成let
 */
 var msg = ["This", "is", "a", "test"];
for(var i=0;i<msg.length;i++){
  console.log("outer:"+i);
  setTimeout(function(){
     console.log("index:" +i+",msg:"+msg[i]);
  },0);
} 


 /* 
 输出:
  outer:0
  outer:1
  outer:2
  outer:3
  index:0,msg:This
  index:1,msg:is
  index:2,msg:a
  index:3,msg:test
原因:
let所声明的变量,只在let命令所在的代码块内有效,而且有暂时性死区的约束
暂时性死区:只要块级作用域内存在let命令,它所声明的变量就“绑定”(binding)这个区域, 不再受外部的影响
 */
 var msg = ["This", "is", "a", "test"];
for (let i = 0; i < msg.length; i++) {
    console.log("outer:"+i);
    setTimeout(function() {
        console.log("index:" + i + ",msg:" + msg[i]);
    }, 0);
}
  

 

HTML 代码中使用全局变量

在 JavaScript 中, 全局作用域是针对 JavaScript 环境。

在 HTML 中, 全局作用域是针对 window 对象。

var 在全局域中声明的变量会成为window对象属性
let  在全局作用域中声明的变量不会成为window对象属性

  var name="Matt";
  console.log(window.name);//Matt

  let age = 26;
  console.log(window.age);//undefined
 //但是let声明还是会在全局作用域中发生,相应的变量会在页面的生命周期内续存,
 //所以为避免报错,必须确保页面不会重复声明同一个变量

 

 



const声明的特点

const定义常量与使用let 定义的变量相似:
1.二者都是块级作用域
2.都不能和它所在作用域内的其他变量或函数拥有相同的名称

两者还有以下两点区别
1.const声明的常量必须初始化,而let声明的变量不用
2.const 定义常量的值不能通过再赋值修改,也不能再次声明。而 let 定义的变量值可以修改
//1、const定义的变量不会预解析,必须先声明再使用,否则会报错
 console.log(ccc);//err
const ccc=1; 

//2.const声明后立即初始化
const PI;
PI = 3.1415;
console.log(PI);//err   而是应该立即初始化,const PI=3.1415

//3.const定义的变量不允许修改
const aa=5;
aa=6; //err 

//4.不允许在相同作用域内重复声明同一个变量的
const PI = 3.1415;
console.log(PI);
const PI = 3.1415926;
console.log(PI);
//正确做法
const PI = 3.1415;
var s= 3*3*PI;
console.log(s);

//4.但在数组里面,const的值是允许被修改的,这是因为const存储的是地址,值的内容可以变化
const arr=[1,2,3,4,5];
arr[0]="cherry";
console.log(arr);//["cherry", 2, 3, 4, 5]

 

 

<body>
    <p id="demo"></p>
<script>
//并非真正的常量
//const 的本质: const 定义的变量并非常量,并非不可变,它定义了一个常量引用一个值。
//使用 const 定义的对象或者数组,其实是可变的。下面的代码并不会报错:

//创建常量对象
const car={name:"li",age:"30",color:"red"}
//修改属性
car.color="green";
//添加属性
car.fruit="apple";
console.log(car);//{name: "li", age: "30", color: "green", fruit: "apple"}
document.getElementById("demo").innerHTML=car.fruit; //apple

//创建数组
const cars=["red","yellow","blue","black"];
//修改元素
cars[1]="pink";
//添加元素
cars.push("green");
console.log(cars);//["red", "pink", "blue", "black", "green"]
//显示数组
document.getElementById("demo").innerHTML=cars;//red,pink,blue,black,green


//但都不能对常量对象 常量数组重新赋值 会报错
 try{
    const car={name:"li",age:"30",color:"red"};
    car={name: "li", age: "30", color: "green", fruit: "apple"};
}
catch(err){
    document.getElementById("demo").innerHTML = err;
}

try{
    const cars=["red","yellow","blue","black"];
    cars=["red", "pink", "blue", "black", "green"];
}
catch(err){
    document.getElementById("demo").innerHTML = err;
}
</script>
</body>

 

 



























posted @ 2021-01-21 11:11  沁莹  阅读(113)  评论(0)    收藏  举报