JavaScript笔记6: 作用域、预解析、对象

目录

一、作用域

1.作用域

1.1作用域

1.2全局作用域

1.3局部作用域

1.4JS没有块级作用域

2.变量的作用域

2.1全局变量

2.2局部变量

2.3全局变量和局部变量的区别

 3.作用域链

二、预解析

1.预解析相关概念

1.1预解析和代码执行

1.2 变量预解析(变量提升)

1.3函数预解析(函数提升)

案例:(案例4重点)

三、对象

1.对象

1.1对象是由属性和方法组成的

1.2为什么需要对象

2.创建对象的三种方式

2.1  利用字面量创建对象

2.2  利用new Object创建对象

2.3 利用构造函数创建对象

3.new关键字的作用(面试题)

4.遍历对象


一、作用域

1.作用域

1.1作用域

就是代码名字(变量)在某个范围内起作用和效果 ,目的是为了提高程序的可靠性,减少命名冲突。

  • ES6之前作用域有两种 全局作用域局部作用域(函数作用域)

1.2全局作用域

作用于所有代码执行的环境(整个 script 标签内部)或者一个独立的js文件

1.3局部作用域

作用于函数内部的代码环境,就是局部作用域。因为跟函数有关系,所以也被称为函数作用域

1.4JS没有块级作用域

  • 块作用域由 {} 包括

  • 在其他编程语言,if语句中,循环语句创建的变量,仅仅只能在本if语句,本循环语句中使用,如下

  if(true){
    int num = 123;
    System.out.print(num); //123
  }
  System.out.print(num);//报错
  • 以上java代码会报错,因为代码中 {}是一块作用域,其中声明的变量num,在{}之外不能使用,而JavaScript代码则不会报错

  • js在 es6 的时候新增的块级作用域(简而言之,变量在函数外可以调用)

  if(true){
    var num = 123;
    console.log(num); // 123
  }
  console.log(num);// 123

2.变量的作用域

在JavaScript中,根据作用域的不同,变量可以分为两种:

  • 全局变量

  • 局部变量

2.1全局变量

全局作用域下声明的变量(在函数外部定义的变量)

  • 全局变量在代码的任何位置都可以使用

  • 在在全局作用域下var声明的变量(在函数外部定义的变量)是全局变量

  • !!特殊情况下,如果在函数内部 没有声明(不使用var声明)直接赋值的变量也属于全局变量 (不建议使用)

2.2局部变量

局部作用域下声明的变量(在函数内部var声明的变量)

  • 局部变量只能在函数内部使用

  • 函数的形参也可以看做是局部变量

2.3全局变量和局部变量的区别

  • 全局变量:在任何一个地方都可以使用,只有在浏览器关闭时才会销毁,因此比较占内存

  • 局部变量:旨在函数内部使用,当其所在的代码块被执行时,才会被初始化;当代码块运行结束后,就会被销毁,因此更节省内存空间。

 3.作用域链

  • 只要是代码,就至少有一个作用域;
  • 写在函数内部的局部作用域,未卸载仍和行数内部即在全局作用域中;
  • 如果函数中还有函数,那么在这个作用域中就又可以诞生一个作用域;
  • 根据[内部函数可以访问外部函数变量] 的这种机制,用链式查找(一层一层往外查找即就近原则)决定哪些数据能被内部函数访问,就称作作用域链
  • 作用域链采取就近原则的方式来查找变量最终的值
        // 作用域链 : 内部函数访问外部函数的变量,采取的是链式查找的方式来决定取哪个值
        var num = 10;   //全局变量

        function fn() {  //外部函数
            var num = 20;   //局部变量
            num1 = 30;      // !!全局变量(如果在函数内部 没有声明直接赋值的变量也属于全局变量 )

            function fun() {   //内部函数
                console.log(num);   //num采取就近原则
            }
            fun();
        }
        fn();    //20
        console.log(num1);   // 30

案例:

        // 案例2:结果是几?
        function f4() {
            var num = 123;

            function f5() {
                console.log(num     // 站在目标出发,一层一层往外查找
            }
            f5();    // 123
        }
        var num = 456;
        f4()        // 无输出,要有输出还得调用函数f5

 

 

二、预解析

1.预解析相关概念

1.1预解析和代码执行

JavaScript代码是由浏览器中的JavaScript解析器来执行的。JavaScript解析器在运行JavaScript代码的时候分为两步:预解析和代码执行

  • 预解析在当前作用域下,JS代码执行之前,浏览器会默认把带有 var 和 function声明的变量在内存中进行提前声明或定义。预解析分为变量预解析(变量提升)和函数预解析(函数提升)

  • 代码执行  从上往下执行JS语句

预解析会把变量和函数的声明在代码执行之前完成,预解析也叫做变量、函数提升。

1.2 变量预解析(变量提升)

所有变量声明会被提升到当前作用域的最上面,变量的赋值不提升

1.3函数预解析(函数提升)

函数的声明会被提升到当前作用域的最上面,但是不会调用函数。

        // 1.
        console.log(num);    //报错
        // 2.先进行变量提升
        console.log(num);   //underfined
        var num = 10;   
        // 相当于执行力以下代码
        // var num;   // 先进行变量提升(所有变量声明会被提升到当前作用域的最上面,变量的赋值不提升)
        // console.log(num);
        // num = 10;
        

        //3. 函数提升(函数的声明会被提升到当前作用域的最上面,但是不会调用函数)
        fn();
        function fn() {
            console.log(11);    // 11
        }
        // 相当于执行力以下代码
        // function fn() {
        //     console.log(11);
        // }
        // fn();  


        // 4. 先进行变量提升
        fun();
        var fun = function() {
            console.log(22);     // 报错
            }
        // 相当于执行力以下代码
        // var fun;
        // fun();         // 因为fun并没有被赋值,调用时就肯定会报错
        // fun = function() {
        //     console.log(22);     
        // }

案例:(案例4重点)变量声明=函数声明>赋值=调用(同一级别看顺序)

        // 案例1
        var num = 10;
        fun();
        function fun() {
            console.log(num);     // underfined
            var num = 20;
        }
        // 相当于执行了以下操作
        var num;     // 变量提升(变量声明会被提升到当前作用域的最上面 !!!当前作用域)
        function fun() {
            var num;
            console.log(num);     // underfined
            num = 20;
        }
        num = 10;
        fun();

        // 案例2
        var num = 10;
        function fn() {
            console.log(num);     // underfined
            var num = 20;
            console.log(num);     // 20
        }
        fn();
        // 相当于执行了以下操作
        // var num;
        // function fn() {
        //     var num;
        //     console.log(num);     // underfined
        //     num = 20;
        //     console.log(num);     // 20
        // }
        // num = 10;
        // fn();

        // 案例3
        var a = 18;
        f1();
        function f1() {
            var b = 9;
            console.log(a);       // underfined
            console.log(b);       // 9
            var a = '123';
        }
        // 相当于执行了以下操作
        // var a;
        // function f1() {
        //     var b;
        //     var a;
        //     b = 9;
        //     console.log(a);       // underfined
        //     console.log(b);       // 9
        //     var a = '123';
        // }
        // a = 18;
        // f1();

        // 案例4
        f2();
        console.log(c);
        console.log(b);
        console.log(a);
        function f2() {
            var a = b = c = 9;
            // 相当于 var a = 9; b = 9; c = 9;       b和c直接赋值,没有var声明,当全局变量看
            // 集体声明 var a = 9, b = 9, c = 9;(此时a,b,c都用var声明了)
            console.log(a);
            console.log(b);
            console.log(c);
        }
        // 相当于执行了以下操作
        // function f2() {
        //     var a;
        //     a = b = c = 9;
        //     console.log(a);   // 9
        //     console.log(b);   // 9
        //     console.log(c);   // 9
        // }
        // f2();
        // console.log(c);      // 9
        // console.log(b);      // 9
        // console.log(a);      // 报错(因为a是局部变量)

三、对象

1.对象(一个具体的事物)

在JavaScript中,对象是一组无序的相关属性和方法的集合,所有的事物都是对象,例如字符串、数值、数组、函数等。

1.1对象是由属性方法组成的

  • 属性:事物的特征,在对象中用属性来表示(常用名词)

  • 方法:事物的行为,在对象中常用方法来表示(常用动词)

 

 

1.2为什么需要对象

  • 保存一个值时,可以使用变量,保存多个值(一组值)时,可以使用数组,如果保存一个的完整信息呢?

  • 为了更好地存储一组数据,对象应用而生;对象中为每项数据设置了属性名称,可以访问数据更语义化,数据结构清晰,表意明显,方便开发者使用。

2.创建对象(object)的三种方式

2.1  利用字面量创建对象

对象字面量:就是花括号 { } 里面包含了表达这个具体事物(对象)的属性和方法;{ } 里面采取键值对的形式表示
-:相当于属性名
-:相当于属性值,可以是任意类型的值(数字类型、字符串类型、布尔类型,函数类型等)

        // 1.利用对象字面量创建对象 {}
        //var obj = {};    // 创建了一个空的对象
        var obj = {
            uname: '漓曦',
            age: 18,
            sex: '女',
            sayHi: function() {
                console.log('hi~');
            }
        }
        // 1) 里面的属性或者方法采取键值对的形式  键(属性名):值(属性值)
        // 2) 多个属性或者方法中间用逗号隔开
        // 3) 方法冒号后面跟的是一个匿名函数
        
        // 2. 使用对象
        // 1)调用对象的属性,采取 对项名.属性名  “.”可以理解为“的”
        console.log(obj.uname);    // 漓曦
        // 2)调用属性还有一种方法  对象名['属性名']
        console.log(obj['age']);   // 18
        // 3) 调用对象的方法  对象名.方法名()    注意调用函数要加小括号
        obj.sayHi();     // hi~

变量、属性、函数、方法总结
变量:单独声明赋值,单独存在,使用时直接写变量名
属性:对象里面的变量称为属性不需要声明,用来描述该对象的特征。使用时必须 对象.属性
方法:方法是对象的一部分,函数不是对象的一部分,函数是单独封装操作的容器。对象里面的函数称为方法,方法不需要声明,使用"对象.方法名()"的方式就可以调用,方法用来描述该对象的行为和功能。
函数:单独存在的,通过"函数名()"的方式就可以调用。

2.2  利用new Object创建对象

         // 利用 new Object 创建对象  
        var obj = new Object();     // 创建了一个空的对象  object中的O要大写
        obj.uname = '漓曦';
        obj.age = 18;
        obj.sex = '女';
        obj.sayHi = function() {    
            console.log('hi~');
        }
        // 1) 利用 等号 = 赋值 的方法 添加对象的属性和方法
        // 2)每个属性和方法之间用 分号 结束
        console.log(obj.name);
        console.log(obj['sex']);
        obj.sayHi();

2.3 利用构造函数创建对象   构造函数——泛指一个大类,对象——一个具体的事物

构造函数是一种特殊的函数,主要用来初始化对象,即为对象成员变量赋初始值,它总与new运算符一起使用,我们可以把对象中一些公共的(相同的)属性和方法抽出来,然后封装到这个函数里面

// 为什么需要使用构造函数
// 就是因为前面两种创建对象的方式一次只能创建一个对象
        // 利用 构造函数 创建对象
        // 构造函数的语法格式
        // function 构造函数名() {
        //     this.属性 = 值;            // this表示当前的 必须添加
        //     this.方法 = function() {}
        // }
        // new 构造函数名();      // 调用构造函数  必须使用 new

        function Star(uname1,age1,sex1) {
            this.name = uname1;
            this.age = age1;
            this.sex =sex1;
            this.sing = function(sang) {
                console.log(sang);
            }
        }
        var ldh = new Star('刘德华',18,'男');
        // console.log(typeof ldh);    // object    调用函数返回的是一个对象
        console.log(ldh.name);         // 刘德华
        console.log(ldh['sex']);       // 男
        ldh.sing('冰雨');              // 冰雨
        // 1.构造函数名字 的首字母要大写
        // 2.构造函数不需要 return 就可以返回结果

        // 1.其他:构造函数如Stars(),抽取了对象的公共部分,封装到了函数里面,它泛指某一大类(class)
        // 2.创建对象,如new Stars();特指某一个,利用new关键字创建对象的过程,我们也称为对象实例化

3.new关键字 执行过程

  • 1.在构造函数代码开始执行之前,创建一个空对象

  • 2.修改this的指向,把this指向创建出来的空对象

  • 3.执行构造函数内的代码,给这个新对象添加属性和方法

  • 4.在函数完成之后,返回这个创建出来的新对象(所以构造函数里面不需要return)

4.遍历对象

  for...in 语句用于对数组或者对象的属性进行循环操作。

  其语法如下:
  for (变量 in 对象名字) {
      // 在此执行代码
  }
  语法中的变量是自定义的,它需要符合命名规范,通常我们会将这个变量写为 k 或者 key。
  

  var obj = {
        name: '漓曦',
        age: 18,
        sex: '女',
  }
  for (var k in obj) {
    console.log(k);      // k 变量 输出 得到的是属性名 (k不加引号)
    console.log(obj[k]); // obj[k] 得到的是属性值
  }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值