2020-08-28---函数(下)

52 篇文章 0 订阅

一、作用域及作用域链

作用域:作用的范围
作用域链:在子级作用域中使用一个变量,如果当前作用域没有,会向上一级作用域寻找,如果还没有,一次向上一级的上一级寻找,这个过程就叫做作用域链。(一级一级向上查找的过程就叫做作用域链)
script : 全局作用域

  • 声明在全局作用域中的变量,叫做全局变量,同时也是window对的属性,在全局范围中有效;生存时间,从程运行开始开辟空间,到退出程序释放空间。
  • 声明在函数中的函数,叫做全局函数,同时也是window对象的方法。

function :函数作用域(局部作用域)

  • 声明在函数中的变量或形参,叫做局部变量,只在所在的函数中有效;生存时间,从调用函数开始开辟空间,到函数调用结束释放空间。

一旦进入作用域,浏览器就会启动js解析器,就会执行下面的两步
第一步 预解析 (寻找var function 形参)

  1. 如果在作用域中找到了var 或形参,会将后面的变量名放到内存中,并且给它初始化一个值为undefined。
  2. 如果在作用域中找到了function,会将函数名提取到内容中,并将整个函数块赋值给这个变量。
  3. 如果变量与函数名同名时,丢变量,保函数。(同类型覆盖,不同类型选择)
  4. 一个页面中有多个script作用域时,从上到下依次解析script,所以上面script中声明的东西,下面可以使用。下面声明的,上面的使用报错。建议所有声明的东西放到第一个script中。(声明的东西会都放在内存中,所以上面声明的,下面在内存中能找见。)

第二步 逐行解析代码(如果遇到的是声明函,则直接跳过)

  1. 执行表达式
  2. 函数调用(函数也是一个作用域
    一、预解析(寻找var function 形参)
    二、逐行解析代码(如果遇到的是声明函数,则直接跳过)
    1. 执行表达式
    2. 函数调用(函数也是一个作用域)
<script>
        /*
        一、预解析 var 形参 function
            如果在作用域中找到了var或形参,会将后面的变量名放到内存中,并赋一个初值为undefined
            a = undefined
            如果在作用域中找到了function,会将函数名提取到内存中,并赋值为整个函数块
            fn = function fn(){}
        二、逐行解读代码
            alert(a)  a=undefined
            a=1
            alert(a)  a=1
            如果遇到函数声明,则跳过
        */
        alert(a);//undefined
        var a = 1;
        alert(a); //1
        function fn(){
            alert(2);
        }
    </script>
<script>
        /*
        一、预解析
        a=function a(){}
        如果函数名和变量名相同,丢变量,保函数。(同类型覆盖。不同类型选择)
        二、逐行解析
        

        */
        alert(a); //a=function a(){alert(4);}
        var a = 1;
        alert(a); //a=1
        function a(){
            alert(2);
        }
        var a = 3;
        alert(a);  //a=3
        function a(){
            alert(4);
        }
        alert(a); //a=3
    </script>
<script>
        /*
        第一个script
        一、预解析
        fn = function fn(){}
        二、逐行解析

        第二个script
        一、预解析
        a = undefined
        二、逐行解析


        第一个script预解析完进行逐行解析的时候,内存中还没有a,会报错
        第二个script预解析完进行逐行解析的时候,调用第一个script中的fn(){},因为fn()已经在内存中了。
        */
        alert(a); //报错
        function fn(){
           alert(2);
        }
    </script>
    <script>
        var a = 1; //a=1
        fn(); //a= 2
    </script>
<script>
        /*
        一、预解析
        a = undefined
        fn = function fn(){}
        二、逐行解析

        函数作用域
            预解析
            逐行解析
        在子级作用域使用一个变量,如果当前作用域没有,就依次向上级寻找。找到就使用。
        同样在子级作用域给一个变量赋值,如果当前作用域没有,就依次向上级寻找,找到就修改。
        */
        alert(a); //a = undefined
        var a = 1;
        alert(a); //a = 1
        function fn(){
           alert(a);  //a = 1
           a = 2;
        }
        fn(); //a = 1  a = 2
        alert(a); //a=2
    </script>
 <script>
        /*
        一、预解析
        a = undefined
        fn = function fn(a){}
        二、逐行解析

        函数作用域 
            a=undefined
        */
        var a = 1;
        alert(a);//a=1
        function fn(a){
           alert(a); //a = undefined
           a = 2;//a = 2
        }
        fn();
        alert(a); //a = 1  这里是全局的a
    </script>
<script>
        /*
        一、预解析
        a = undefined
        fn = function fn(){}
        二、逐行解析

        函数作用域
            预解析
            a = 1   实参传递过来的值
            逐行解析

        */
        var a = 1;
        alert(a);  //1
        function fn(a){
           alert(a);  //1
           a = 2;
        }
        fn(a);
        alert(a); // 1
    </script>
<script>
        /*
        一、预解析
            a = undefined
            fn = function fn(){}
        二、逐行解析

            函数作用域
                预解析
                    a = 1
        */
        var a = 1;
       alert(a); //1
       function fn(a){
            alert(a); //1
           var a = 3;
           alert(a); //3
           a = 2;
           alert(window.a); //1  全局的a
       }
       fn(a);
       alert(a); //1
    </script>
<script>
        /*
        一、预解析
            fn = function(){}
        二、逐行解析
            预解析
                a = 3 
                隐式声明的变量会在全局作用域中自动生效
        */
        function fn(){  
           a = 3;
           alert(a);//3
           a = 2;
           alert(window.a);  //2
        }
        fn();
        alert(a); //2
    </script>

二、递归 : 自己调用自己。

本质 : 循环(初始值,条件,步长)
<script>
        //利用递归实现 输出10次helloworld
        function fnRe(n){
            if( n === 0){
                return 0;
            }else{
                console.log('HelloWorld!');
                fnRe(n-1);
            }
        }

        //递归 1-100的和
        function fnSum(n){
            if(n===0){
                return 0;
            }else{
                return n + fnSum(n-1);
            }
        }

        //递归 n的阶乘
        function fnMulti(n){
            if(n===1){
                return 1;
            }else{
                return n * fnMulti(n-1);
            }
        }
    </script>

三、匿名函数

匿名函数,是没有名字函数

  1. 将匿名函数赋值给一个变量
  2. 通过事件绑定
  3. 函数的自我执行
  4. 匿名函数传参
  5. 可以有返回值
<script>
        /*
        匿名函数,是没有名字的函数
        function(){
            alert('匿名函数');
        }
        */
        // 1.将匿名函数赋值给一个变量
        // var fn = function(){
        //     alert('匿名函数');
        //     alert('将匿名函数赋值给一个变量');
        // }

        //2.通过事件绑定
        //点击页面即可触发
        // document.onclick = function(){
        //     alert('匿名函数');
        //     alert('通过事件绑定');
        // }

        //3.函数自我执行
        // (function(){
        //     alert('匿名函数');
        //     alert('函数的自我执行');
        // })()

        //4.匿名函数传参
        // (function(a,b){
        //     alert('匿名函数');
        //     alert('匿名函数传参');
        //     alert(a);
        // })(3,4)

        //5.可以有返回值
       var fn = (function(a,b){
            alert('匿名函数');
            alert('可以有返回值');
            return a + b;
        })(3,5)
        console.log(typeof fn);//number
        // console.log(fn()); 
        // console.log(fn);
        
    </script>

三、如何创建对象?

  1. 字面量的方式: { key : value,key : value} 当只需要一个对象的时候。
  2. new 内置构造函数() : new Object();
  3. new 自定义构造函数() : new 函数名(); 批量创建对象时
构造函数语法:
function 函数名([参数]){
    this.属性 = 值;
    this.方法 = function(){
        。。。。
    }
}
<script>
        /*
        如何创建对象
        */
        //1.字面量的方式:
        // {key : value,key : value,……}
        var obj = {
            name : '张三',
            age : 18,
            showName : function(){
                return this.name;
            }
        }
        
        //工厂模式,批量生产
        //2.new 内置构造函数() : 
        //new object();
        function creatObj(){
            //原材料
            var obj = new Object();
            //加工
            obj.name = name;
            obj.age = age;
            obj.showName = function(){
                return this.name;
            }
            //出厂
            return obj;
        }
        var obj1 = new Object('张三',18);
        var obj2 = new Object('二哈',7);
        console.log(typeof obj1,typeof obj2)
       
       //工厂模式的缺点
       //1. 无法分辨对象具体属于哪一类的对象。
       //2.不符合程序员创建对象的习惯

       //3.new 自定义构造函数()
    //    new 函数名(); 批量创建对象时
        function Person(){
            this.name = '张三';
            this.age = 18;
            this.shouName = function(){
                this.name;
            }
        }
        function Dog(){
            this.name = '二哈';
            this.age = 7;
            this.shouName = function(){
                this.name;
            }
        }

        //构造函数中的this代表:new出来的对象
        //new做了哪些是(面试)1.在构造函数中会自动创建一个对象 2.会自动返回这个对象 所以 new内置构造函数中要var 对象,并且要return 对象;而自定义构造函数中不需要。
        var per1 = Person('张三',18);
        var dog1 = Dog('二哈',7);
        console.log(typeof per1,typeof dog1);


        //instanceof : 判断一个对象是否属于某个类
        console.log(per1 instanceof Person , dog1 instanceof Dog);
    </script>

四、如何访问对象中的属性和方法

1. 对象.属性   对象.方法()
2. 对象['属性']   对象['方法']()
<script>
        function Dog(name,age){
            this.name = name;
            this.age = age;
            this.showAge = function(){
                return this.age;
            }
            this.showName = function(){
                return this.name;
            }
        }
        var dog1 = new Dog('小黄',5);

        // var dog = new Dog('大黄',7);

        // console.log(dog.name,dog.showName());

        console.log(dog1.age,dog1.showName(),this.age);
    </script>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值