javaScript-执行上下文-作用域链-this-闭包

执行上下文-作用域链-this-闭包:我觉得这几个概念应该不能独立分开讲,他们是有联系的。

  1. 函数
    如何定义一个函数:

1.1 函数声明:

function 函数名称(参数) {方法体}

1.2 函数表达式

var x = function 函数名称(可省) (参数){函数体}

var x = new Function(’ ');

1.3 另一个概念:变量提升:
虽然javascript 是解释语言,边解释边运行,但是实质上它会预解释,也就是所谓的变量提升。

 console.log(x); //undefined
        console.log(x2); //undefined
        x3(); //1
        x2(); //not a function 


        var x = 1;
        var x2 = function() {

        }

        function x3() {
            console.log(1);
        }

为啥会这样,看下去。

  1. 执行上下文(Execution Contexts)或者叫执行环境。
    它是一个抽象的概念。
    一个函数执行前后的两个阶段。
    分为全局上下文,函数上下文,eval(略)。

可以想象它为一个栈,javascript 刚开始运作,把全局上下文压入栈底,运行全局上下文的步骤,遇到运行新的函数执行,创建新的函数执行上下文,压入栈中,运行后弹出。

一个函数的执行(函数上下文)分为两个阶段。
2.1. 创建阶段(上文)代码执行前

函数环境会初始化创建Arguments对象(并赋值)
函数声明(并赋值)
变量声明,(未赋值)
函数表达式声明(未赋值)

2.2 执行阶段

变量对象赋值
变量赋值

函数表达式赋值 调用函数

顺序执行其它代码

这能解决变量提升问题。(为下面作用域链做铺垫)

那么如何抽象一个函数上下文呢?
2.3 函数上下文的抽象结构。
可以抽象为如下结构:把它当作一个对象
在这里插入图片描述
图源:https://www.cnblogs.com/TomXu/archive/2012/01/12/2308594.html

  • 2.3.1 variable object 变量对象 简称VO

A variable object is a scope of data related with the execution context.
It’s a special object associated with the context and which stores variables and function declarations are being defined within the context.

变量对象(variable object) 是与执行上下文相关的 数据作用域(scope of data) 。
它是与上下文关联的特殊对象,用于存储被定义在上下文中的 变量(variables) 和 函数声明(function declarations) 。

2.3.2 作用域链

A scope chain is a list of objects that are searched for identifiers appear in the code of the context.

作用域链是一个 对象列表(list of objects) ,用以检索上下文代码中出现的 标识符(identifiers) 。
说白了先在自己作用域找变量找不到就找父亲的。

2.3.3 this

在一个函数上下文中,this由调用者提供,由调用函数的方式来决定。如果调用括号()的左边是引用类型的值,this将设为引用类型值的base对象,在其他情况下(与引用类型不同的任何其它属性),这个值为null。不过,实际不存在this的值为null的情况,因为当this的值为null的时候,其值会被隐式转换为全局对象。注:第5版的ECMAScript中,已经不强迫转换成全局变量了,而是赋值为undefined。

  1. 闭包,一个磨人的小妖精。(ps,这个我尝试性解释它的原理)

网上互联网对于闭包的定义乱七八糟,
说一下个人的定义:“定义在一个函数内部的函数”
说白了所有的函数都是全局的闭包.

  function fn() {
            var i = 1;
            return function() {
                console.log(i);
                i++;
            }
        }

        var fn1 = fn();
        fn1(); //1
        fn1(); //2
        var fn2 = fn();
        fn2(); //1

特点:
3.1 函数外部不能访问内部的属性,内部可以访问外部属性.
3.2 个是前面提到的可以读取函数内部的变量,另一个就是让这些变量的值始终保持在内存中。
第一点十分好解释,用上面的函数作用域链可以解释.
第二点:我尝试解释一下.

我上一篇的垃圾回收篇中:

假定设置一个叫做根(root)的对象(在Javascript里,根是全局对象)。垃圾回收器将定期从根开始,找所有从根开始引用的对象,然后找这些对象引用的对象……从根开始,垃圾回收器将找到所有可以获得的对象和收集所有不能获得的对象。

var fn1 = fn(); 这行执行时 导致了存在了引用,导致fn()产生的scope 保留了下来,变量也没有被垃圾回收给清掉.

这个解释目前我决定还是有点牵强但是能解决挺多问题.

来个算法题:

var num = 10;
        var obj = {
            num: 20
        };
        obj.fn = (function(num) {

            this.num = num * 3;
            num++;
            return function(n) {
                this.num += n;
                num++;
                console.log(num);
            }
        })(obj.num)
    // var fn = obj.fn; //w-num = 60 a-num = 21
    // fn(5); // w-num = 65 a-num = 22 log 22
    // obj.fn(10); //obj-num = 30 a-num =23 log 23 
    // console.log(num, obj.num); //65 30 

结果 22 23 65 30

注意一点:只用函数执行才有函数上下文.

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值