关于变量提升,形参赋值,函数提升与赋值的一些认识

本文详细解析了JavaScript中的全局作用域与闭包概念,包括变量提升、预解释过程及函数执行时的作用域创建机制。并通过具体示例代码演示了如何理解变量提升、闭包的形成以及作用域链。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  • 在js中,当我们把窗口打开,就形成了一个大的作用域,我们称之为全局作用域,这个全局作用域也是一个栈内存,而它的堆内存就是window本身。
  • 在打开浏览器窗口之后,形成了一个不销毁的大的作用域,可能也是一个闭包把,因为这个作用域也是不销毁的,只有当浏 览器关闭的时候才会销毁,所以我认为全局作用域本身也是一个闭包。作用域形成之后,开始进行变量提升,首先浏览器寻找带关键词 var 的变量,进行变量声明,变量声明做的事情就是在window这个大对象下书写了一个键值对中的键而没有进行赋值,所以我们在 var 变量之前调用这个变量,浏览器给出的值是undefined。而函数则不同,函数是提前声明,并且直接赋值,当浏览器打开后,看到了一个函数比如fn,浏览器就把fn提升到最上面,并为其开辟出一个堆内存,把堆内存的地址附加给fn这个变量.浏览器做的这些事情,我们称之为浏览器的预解释。而且在预解释的时候,浏览器无视条件判断。除非带 var 的变量在另一个堆内存里,或者函数在等号右边,这时,浏览器不会把这个在堆内存里的 var 和等号右边的函数进行预解释,其他情况都要进行预解释。
  • 变量提升之后,浏览器开始执行代码,机制是从上到下依次执行,遇到带= 号的,如果=右边是个基本数据类型,那么就把这个基本数据类型的值附加给= 左边的变量。 如果 = 右边是引用数据类型,那么就把这个引用数据类型开辟的堆内存的地址附加给= 左边的变量,这个过程我们成为变量赋值。
  • 当一个函数执行时,浏览器为这个函数开辟了一个新的栈内存,这个栈内存相当于一个小型的浏览器,而且也按照上述机制进行预解释,然后代码一行一行执行,只是函数多了一个形参赋值,所谓形参赋值,就是函数在预解释的时候,把形参var 一下,并且赋值,在函数自己的作用域里,带var 的都是自己的私有变量,所以,形参也是一个私有变量,如果全局里有一个变量名字和形参的名字一样,在函数执行的作用域里,这个变量的值发生了改变,改变的都是这个函数私有的这个变量,对全局变量不会产生影响。

    var num=1;
    var obj={
        num:2
    };
    obj.fn=(function (num) {
        this.num=num*2;
        num++
        return function (n) {
            this.num+=n;
            num++
            console.log(num);
        }
    })(obj.num)


    var fn=obj.fn; 
    fn(10); 
    obj.fn(20)
    console.log(num, obj.num);


复制代码
  • 下面来分析一下这个题,首先浏览器加载之后进行预解释,就是变量的声明与提升。全局下声明了一个num ,声明了一个obj,为这个obj开辟了一个堆存,声明了一个fn 并且fn是一个自执行函数的执行结果,可以看到这个自执行函数返回了一个函数,也就是一个堆内存的地址,fn通过这个地址指向这个堆内存。
  • 接下来代码执行,自执行函数执行,开辟了一个新的栈内存,然后进行自执行函数的预解释。在这个自执行函数中,没有var,没有function ,只有形参,所以预解释只进行形参赋值 -----》var 一个num =obj.num 既var num=2,并且这个num是自己私有的变量,跟传进来的obj.num已经没关系了,我称它为arguments.num=2,因为是传参进来的。。。自执行该函数预解释完毕,代码执行,this.num=num*2 这里的this指的是window,而=右边的num指的是自己的私有变量num跟obj.num和window.num没有关系,所以this.num=2*2 也就是window.num=4. 然后arguments.num++ =3然后返回了一个函数,被fn接收。!!注意,这里以为返回的值是一个地址,并且被外界的变量fn所接收,所有这个自执行的函数形成的作用域栈内存并不会销毁,一直作为fn接收的这个地址的父级作用域而存在,这就是闭包,----》在某个作用域里产生的引用数据类型被外界所占用,如果这个作用域消失了,外界就找不到这个地址了,所以这个作用域一直存在,形成了一个闭包。
  • 然后fn(10)执行,形成了一个新的作用域,预解释只有形参赋值,既var n=10 ,然后代码执行 this.num指的是window下的num既window.num=window.num+n=4+10=14 ,然后num++ 这个作用域里没有num,往父级作用域找,找到了那个未被销毁的闭包,里面有个num,他的值++那就是arguments.num++ 等于4 ,输出arguments.num那么就是4.所以fn(10)=4.
  • 然后obj.fn(20)执行,就是返回的那个函数执行穿进去的参数是n=20 ;this.num+=n,就是obj。num+=n,所有obj.num=22, num++,自己没有就往父级找,又找到了arguments.num,所以arguments·.num=5,输出arguments.num 既obj.fn(20)=5;
  • 最后一行输出num ,obj。num 既window.num 和 obj.num 一个是14 ,一个是22。 所以整个题目的答案是 4,5,14,22
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值