JS笔记0--常量/变量/预解析/作用域

1.常量

ES6新增:自定义常量

const 常量名称 = 常量取值; //常量一经定义不可修改
const NUM = 666;
console.log(NUM); // 666

2.变量

ES6之前:var 变量名;

  1. 如果定义了同名变量,则后定义的变量会覆盖先定义的变量
    <script>
        var num = 1;
        var num = 2;
        console.log(num) //2
    </script>
  1. 可以先使用变量,再定义变量(预解析)
    <script>
		console.log(num);
		var num = 123;
		预处理之后的代码:
		var num;
		console.log(num); // undefined
		num = 123;
    </script>

ES6之后:let 变量名;

  1. 不能重复定义同名变量
   let num =1;
   let num =2;//报错:Identifier 'num' has already been declared
  1. 不能先使用变量,再定义变量(不会预解析)
    console.log(num)
    let num =1;//Cannot access 'num' before initialization

3.预解析

由于JavaScript是一门解释型的语言, 会边解析边执行, 浏览器在解析JavaScript代码之前还会进行一个操作–预解析(预处理)
预解析(预处理)步骤:
将当前JavaScript代码中所有变量的定义和函数的定义放到所有代码的最前面

 <script>
        /*
        1.什么是预解析?
        浏览器在执行JS代码的时候会分成两部分操作:预解析以及逐行执行代码
        也就是说浏览器不会直接执行代码, 而是加工处理之后再执行,
        这个加工处理的过程, 我们就称之为预解析

        2.预解析规则
        2.1将变量声明和函数声明提升到当前作用域最前面
        2.2将剩余代码按照书写顺序依次放到后面

        3.注意点
        通过let定义的变量不会被提升(不会被预解析)
        */
        /*
        // 预解析之前
        console.log(num); //undefined
        var num = 123;
        // 预解析之后
        var num;
        console.log(num);
        num = 123;
        */
        /*
        // 不会预解析之前
        console.log(num); // 报错
        let num = 456;
        */

        // ES6之前定义函数的格式
        /*
        console.log(say);
        say();
        // ES6之前的这种定义函数的格式, 是会被预解析的, 所以可以提前调用
        function say() {
            console.log("hello it666");
        }
        */
        /*
        // 预解析之后的代码
        function say() {
            console.log("hello it666");
        }
        say();
        */

        /*
        console.log(say);
        say(); // say is not a function
        // 如果将函数赋值给一个var定义的变量, 那么函数不会被预解析, 只有变量会被预解析
        var say = function() {
            console.log("hello itzb");
        }
        */
        /*
        var say; //undefined
        say();
        say = function() {
            console.log("hello itzb");
        }
        */

        // ES6定义函数的格式
        say(); // say is not defined
        let say = () => {
            console.log("hello itzb");
        }

    </script>
<script type="text/javascript">	
	/*
	* 函数的声明提前:
	* 1.使用函数声明创建的函数function 函数名() {}
	*  会在所有的代码执行前被创建,所以可以在函数声明前被调用
	* 2.使用函数表达式创建的函数 var 函数名= function(){} 
	*   不会被提前创建,所以不能在声明前调用
	*/ 
    fun1();//输出是 fun1函数
	//函数声明.会被提前创建
    function fun1()
	{
		console.log("fun1函数");
	}
	fun2(); //输出是 Uncaught TypeError: fun2 is not a function
	//函数表达式,不会被提前创建
	var fun2=function(){
		console.log("fun2函数");
	}
</script>

预解析练习

   <script>
        // 1.下列程序的执行结果是什么?
        var num = 123;
        fun();
        function fun() {
            console.log(num);
            var num = 666;
        }
        /*
        var num;
        function fun() {
           var num;
           console.log(num); // undefined
           num = 666;
        }
        num = 123;
        fun();
        */
    </script>
    <script>
        // 1.下列程序的执行结果是什么?
        var a = 666;
        test();
        function test() {
            var b = 777;
            console.log(a);
            console.log(b);
            console.log(c);
            var a = 888;
            let c = 999;
        }
        /*
        var a;
        function test() {
           var b;
           var a;
           b = 777;
            console.log(a); // undefined
            console.log(b); // 777
            console.log(c); // 报错
            a = 888;
            let c = 999;
        }
        a = 666;
        test();
        */
    </script>

4.作用域

在ES6之前,没有块级作用域的概念。只有全局作用域和局部作用域(函数作用域)

        {
            // 块级作用域
            var num = 123; // 全局变量
        }
        console.log(num);

在局部作用域中,通过var定义的变量是局部变量

       {
            // 块级作用域
        }
        if(false){
            // 块级作用域
        }
        while (false){
            // 块级作用域
        }
        for(;;){
            // 块级作用域
        }
        do{
            // 块级作用域
        }while (false);
        switch () {
            // 块级作用域
        }
        function say() {
            // 局部作用域
        }

4.1 全局作用域

<script type="text/javascript">
	/*
	* 作用域
	* 1.全局作用域:定义在script标签中,在页面打开时创建,关闭时销毁
	* 在全局作用域中有一个全局对象window(浏览器的一个窗口,由浏览器创建),可以直接使用
	* 在全局作用域中,创建的变量都会作为window对象的属性保存
	*/
    var a = 10;
	console.log(window.a); //a是window的属性
	
	/*
	* 变量的声明提前:使用var关键字声明的变量,会在所有的代码执行前被声明(但是不会赋值)
	*/ 
    console.log(b); //输出是 undefined
	var b= 123;
	
	//不使用var关键字,则该变量不会被提前声明
	console.log(c); //Uncaught ReferenceError: c is not defined
	c = 123;
</script>

4.2 函数作用域

<script type="text/javascript">	
	/* 函数作用域
	* 调用函数时创建函数作用域,函数执行完毕后作用域销毁
	* 每调用一次函数会创建一个函数作用域,他们之间相互独立
	* 在函数作用域中,可以访问全局变量
	* 在全局作用中,无法访问函数作用域中的变量
	* 当在函数作用域中操作一个变量中,会先在自身作用域中寻找,如果有就直接使用
	* 如果没有,就在上一级作用域中寻找,直到在全局作用域中寻找
	* 如果在全局作用域中依然没有找到,报错
    * 在函数作用域中寻找全局变量,使用window.变量名
	*/ 
    
	//变量a在全局作用域和函数作用域中都有定义,在函数中局部变量的优先级更高
    var a = 1;
    function fun1()
	{
		var a = "fun1函数中的a";
		console.log(a);
	}
    fun1(); //输出是:fun1函数中的a

    //调用函数fun2访问变量a,没有找到,向上一级寻找
	var a = 1;
	function fun1()
	{
		var a = "fun1函数中的a";
		function fun2()
		{
			console.log(a);
		}
		fun2();
	}
	fun1(); //输出是:fun1函数中的a

    //调用函数fun2访问变量a,一直向上一级寻找,在全局作用域中也没有找到,报错
	function fun1()
	{
		function fun2()
		{
			console.log(a);
		}
		fun2();
	}
	fun1(); //输出是:  Uncaught ReferenceError: a is not defined

    //在函数作用中寻找全局变量,使用window.变量名
	var a = "全局变量a";
	function fun1()
	{
		var a = "fun1中的a";
		function fun2()
		{
			var a = "fun2中的a";
			console.log(window.a);
		}
		fun2();
	}
	fun1(); //输出是:  全局变量a
</script>
  1. 函数作用域中也有变量和函数的提前声明
<script type="text/javascript">	
	/* 
	* 在函数作用域中使用var声明的变量,会在函数的所有代码被执行之前声明,但没有赋值
	* 函数声明也会在该函数的所有代码执行前执行
	*/ 
	var a = "全局变量a";
	function fun1()
	{
		console.log(a); 
		var a = "fun1中的a";
	}
	fun1(); //输出是: undefined
</script>
  1. 在函数作用域中 有var VS 没有var:
<script type="text/javascript">	
	/* 
	* 在函数作用域中使用var声明的变量,会在函数的所有代码被执行之前声明,但没有赋值
	* 函数声明也会在该函数的所有代码执行前执行
	*/ 
	var a = "全局变量a";
	function fun1()
	{
		//没有使用var,在函数作用域中不会对a进行提前声明,在函数中找不到a,向上一级寻找
		console.log(a); //找的是局部变量a,没有找到,输出全局变量a,此时的值还是"全局变量a"
		//在函数中没有使用var,此时的a还是全局变量a,相当于对全局变量a进行重新赋值
		a = "fun1中的a"; //此时全局变量a的值已经是"fun1中的a"
	}
	fun1(); //输出是: 全局变量a
	
	//在全局作用域中寻找a,找到的是全局变量a,在fun1中已经对全局变量a的值进行修改
	console.log(a);  //输出是: fun1中的a
</script>
  1. 在函数作用域中定义某个变量,但不使用var关键字,此时该变量为全局变量

<script type="text/javascript">	
	function fun1()
	{
		b = "没有var的局部变量b";
		// b没有使用var关键字,设置为全局变量
	}
	fun1(); 
	//在全局寻找b
	console.log(b);  //输出是: 没有var的局部变量b
</script>
  1. 如果变量和函数同名,函数的优先级高于变量
    <script>
        console.log(value); // 会输出函数的定义
        var value = 123;
        function value() {
            console.log("fn value");
        }
        console.log(value); // 会输出123
        以上代码在预解析之后:
        /*
        function value() {
            console.log("fn value");
        }
        console.log(value);
        var value;
        value = 123;
        console.log(value);
        */
    </script>

4.3 块级作用域

ES6开始,如果{}没有和函数名结合在一起,就是块级作用域

  1. 在块级作用域中,通过var定义的变量是全局变量
        {
            // 块级作用域
            var num = 123; // 全局变量
        }
        console.log(num); // 123
  1. 在局部作用域中,通过var定义的变量是局部变量
    <script>
        function test() {
            var value = 666; // 局部变量
        }
        test();
        console.log(value); // value is not defined
    </script>
  1. 无论是在块级作用域还是在局部作用域, 省略变量前面的let或者var就会变成一个全局变量
    <script>
        function test() {
            num = 123; // 全局变量
        }
        test();
        console.log(num);// 123
    </script>
    <script>
        {
            num = 678; // 全局变量
        }
        console.log(num);//678
    </script>
  1. let 和var
无论是var还是let定义在{}外面都是全局变量
var定义的变量放到一个单独的{}里面, 还是一个全局变量
        {
            var num = 123;
        }
        console.log(num);  //不会报错
let定义的变量放到一个单独的{}里面, 是一个局部变量
        {
            let num = 123;
        }
        console.log(num);  //会报错

4.4 作用域练习

	/*
	* 计算一下代码的执行结果:
	*/ 
5.   var a = 123;
	function fun()
	{
		console.log(a); //在函数作用域中没有找到变量a,向上一级寻找
	}
	fun(); //123


6.	var a = 123;
	function fun()
	{
		console.log(a);
		var a = 456;
		//使用var关键字在函数作用域中对局部变量a进行提前声明,但没有赋值
	}
	fun(); //undefined
	console.log(a); //查找全局变量,a=123

7.  var a = 123;
	function fun()
	{
		console.log(a); //a 还是全局变量123
		a = 456;
		//在函数作用域中没有使用var关键字声明a,所以将全局变量a修改成456
	}
	fun(); //123
	console.log(a); //456

8.  var a = 123;
	function fun(a) //定义形参a=声明局部变量a
	{
		console.log(a); //123
		a = 456; //改变的是局部参数a,没有改变全局变量
	}
	fun(); //没有传递实参,相当于在函数内没有对局部变量a赋值,输出undefined
	console.log(a);//123

9.	var a = 123;
	function fun(a) //定义形参a=声明局部变量a
	{
		console.log(a); 
		a = 456; //改变的是局部参数a,没有改变全局变量
	}
	fun(123); //123
	console.log(a);//123
    <script>
        // 1.找出下列哪些是全局变量,哪些是局部变量
        /*
        var num1 = 123; // 全局变量
        function test() {
            var num2 = 456; // 局部变量
        }
        {
            var num3 = 789; // 全局变量
        }
        function test() {
            num4 = 666; // 全局变量
        }
        */

        // 2.找出下列哪些是全局变量,哪些是局部变量
        /*
        let num1 = 123; // 全局变量
        function test() {
            let num2 = 456; // 局部变量
        }
        {
            let num3 = 789; // 局部变量
        }
        function test() {
            num4 = 666; // 全局变量
        }
        */

        // 3.下列代码运行是否会报错
        /*
        var num = 123;
        var num = 456; // 不会报错
        */
        /*
        {
           var num = 123;
            {
                var num = 456; // 不会报错
            }
        }
        */
        /*
        console.log(num); // 不会报错
        var num = 123;
        */

        // 4.下列代码运行是否会报错
        /*
        let num = 123;
        let num = 456; // 会报错
        */
        /*
        {
           let num = 123;
            {
            // 注意点: 在不同的作用域范围内, 是可以出现同名的变量的
                let num = 456; // 不会报错
            }
        }
        */
        /*
        console.log(num); // 会报错
        let num = 123;
        */

        // 5.下列代码运行是否会报错
        /*
        // 注意点: 只要出现了let, 在相同的作用域内, 就不能出现同名的变量
        let num = 123;
        var num = 456; // 会报错
        */
        /*
        var num = 123;
        let num = 456; // 会报错
        */
    </script>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值