五、作用域和递归

一、作用域

  1. 作用域的概念:变量或函数或数据或功能,作用的区域,生效的区域,可被使用的区域
  2. 作用域的分类:
    • 全局作用域:不属于任何函数的语句,叫全局作用域。全局作用域内的变量,叫全局变量。
    • 局部作用域:属于某个函数内部的区域,叫局部作用域。局部作用域内的变量,叫局部变量。
  3. 作用域之间数据的访问规则(作用域嵌套后)
    • 父作用域不能使用子作用域内部的数据(父不能拿子)
    • 子作用域可以使用父作用域内部的数据(子可以拿父)
      var a = 10;
      function fn(){
              
              
          var b = 20;
          console.log(a);		// 10
          console.log(b);		// 20
      }
      fn();
      console.log(a);		// 10
      console.log(b);		// Error: b is not defined
      
  4. 多层作用域嵌套后,变量的读写规则
    • 读(使用):
      • 先在自身作用域查找,找到了就使用并停止查找
      • 找不到,依次向上层作用域查找
      • 任意一层找到了,都使用并停止查找
      • 直到顶层都没找到,报错!
    • 写(赋值):
      • 先在自身作用域查找,找到了就修改并停止查找
      • 找不到,依次向上层作用域查找
      • 任意一层找到了,都修改并停止查找
      • 直到顶层都没找到,直接声明成全局,再做修改!(非严格模式,严格模式下,报错)
  5. 不同作用域内变量的特点
    • 全局变量:跟随全局环境,在内存中一直存在,占内存
    • 局部变量:根据局部环境,局部作用域创建,变量存在,局部作用域结束,变量被删除,省内存
    • 建议:尽量少用全局,可以使用匿名函数,生成一个大的新的作用域,将要使用的数据和多个功能再次包裹
      ;(function(){
              
              
          var a = 10;
          function box1(){
              
              
              console.log(a);		// 10
          }
          function box2(){
              
              
              a = 20;
              console.log(a);		// 20
          }
          function box3(){
              
              
              console.log(a);		// 20
          }
          box1();
          box2();
          box3();
      })();
      

二、声明提升

  • 所谓声明提升,就是js解析器在解析js代码时,会先将当前作用域内的变量声明和函数声明,都提前到作用域最开始的位置执行,这样做是为了在内存中提前创建好对应空间,以便将来程序可以直接进行使用。
  • 但,这其实是js语言现存的一个bug,提前声明带来的优势非常小,反而在没有块级作用域概念时,会造成各种作用域空间的污染。所以在之后的版本ES6的新特性中,变量的声明提升被禁止了。
  1. 声明变量的提升
    • var声明的变量,都会提前到作用域最开始的位置声明,原位赋值
      console.log(a);		// undefined
      var a = 10;
      console.log(a);		// 10
      
  2. 声明函数的提升
    • function声明的函数,会整体提升到作用域最开始的位置
      console.log(fn);		// function fn(){...}
      function fn(){
              
              
          console.log(1)
      }
      console.log(fn);		// function fn(){...}
      
  3. 当var遇到function
    • 赋值式创建函数:var fn = function(){}
      • 提升的是变量,并没有提升函数
        console.log(fun);			// undefined
        var fun = function(){
                  
                  
            console.log(2)
        }
        console.log(fun);			// function(){...}
        
    • 当var的变量名和function的函数名重名时,var先提升,所以function生效
      • 注意:重名,本来就是不被允许的!
        console.log(b);		// function b(){...}
        var b = 20;
        function b(){
                  
                  
            console.log(3);
        }
        console.log(b);		// 20
        

三、递归

  1. 递归:在函数的内部,执行自身。滥用递归会造成类似于死循环的现象,造成程序崩溃,计算机死机,内存溢出
    • 利用递归的思想,解决程序中的问题,要配合函数的结束语句,适当时跳出递归
    • 就算是正常递归,也会消耗大量性能
    • 必须使用时尽量少用,能少用时尽量不用
  2. 递:
    • 不断执行自身的过程
  3. 归:
    • 不断向外返回数据的过程
  4. 使用递归计算阶乘,如:5! = 54321
// 已知:
// 5! = 5 * 4 * 3 * 2 * 1
// 5! = 5 * 4!
//          4! = 4 * 3!
//                   3! = 3 * 2!
//                            2! = 2 * 1!
//                                     1
// 可推算计算任意数的阶乘公式为:
// fn(n) = n * fn(n-1);
// ...
// fn(5) = 5 * fn(4);
// fn(4) = 4 * fn(3);
// fn(3) = 3 * fn(2);
// fn(2) = 2 * fn(1);
// 计算最小数字1的阶乘为:
// fn(1) = 1;
function fn(n){
    
    
	if(n === 1){
    
    
		return 1;
	}else{
    
    
		return n * fn(n-1);
	}
}
console.log( fn(5) );		// 120

四、对象介绍

  1. 对象:一种对客观事物的描述,将客观事物以逻辑数据的形式进行描述的过程

    • 无序数据的打包,object对象,标志是{}
    • 有序数据的打包,array对象,标志是[]
  2. 对象的本质(组成)

    • 键值对。键(key)和值(value)一一对应,成对出现
    • 键和值之间使用冒号连接,键值对之间使用逗号隔开。伪代码:{ 颜色:红色, 身高:180, 体重:150, 发型:板寸 }
  3. 对象的意义(作用):存储数据,编程

  4. 对象的创建

    • 字面量:var obj = {}
    • 构造函数:var obj = new Object()
  5. 任何情况下,两个对象都不相等;如果相等了,表示这俩就是一个对象。

    var obj1 = {
          
          };
    var obj2 = new Object();
    var obj3 = {
          
          }
    var obj4 = obj1;
    console.log(obj1);		// {}
    console.log(obj2);		// {}
    
    console.log(obj1 === obj2);		// false
    console.log(obj1 === obj3);		// false
    console.log(obj4 === obj1);		// true
    
  6. 对象的操作语法

    • 点语法:当对象的属性是具体的值时
    • 中括号语法:当对象的属性是变量时
      var a = "world";
      var obj = {
              
              
          title:"对象的操作",
          number:18,
          [a]:"啊哈哈哈"
      }
      var str = "number";
      console.log( obj.str );			// undefined
      console.log( obj[str] );		// 18
      console.log( obj.a );			// undefined
      console.log( obj.world );		// 啊哈哈哈
      console.log( obj["title"] );	// 对象的操作
      console.log( obj[title] );		// Error: title is not defined
      
  7. 对象的操作

    var person = {
          
          name:"张三", age:18};
    
    • 增:
      person.sex = "男";
      person["sex"] = "男";
      
    • 删:
      delete person.age;
      delete person["age"];
      
    • person.sex = "女";
      person["sex"] = "女";
      
    • console.log(person.name)
      console.log(person["name"])
      
  8. 对象的分类(了解)

    • 宿主对象:windowdocument
    • 本地对象:构造函数,需要new执行后才能得到具体的对象:ObjectNumberStringBoolean
    • 内置对象:官方提供的可直接使用的对象:Math

五、练习

  1. 编写函数,利用递归解决
    • 当n为偶数时,调用函数,求1/2+1/4+…+1/n
    • 当n为奇数时,调用函数,求1/1+1/3+…+1/n
  2. 利用递归求两个数字最大公约数
  3. 利用递归求斐波那契数列的第n位(1, 1, 2, 3, 5, 8, 13, 21, …)

猜你喜欢

转载自blog.csdn.net/weixin_41636483/article/details/116140104