js基础----this、调用栈、闭包

107 阅读3分钟
  • 函数的调用栈规定了js的代码执行顺序,栈底永远都是全局上下文,栈顶则是当前正在执行的上下文。
  • 全局上下文在浏览器关闭窗口后出栈。
  • 遇到return会直接终止当前上下文代码执行,将当前上下文弹出栈。
  • 函数在执行时才会创建执行上下文。

函数被调用时(执行上下文)时的生命周期分为两个阶段:

创建阶段:生成变量对象,确认作用域链,确定this指向
执行阶段:变量赋值,函数引用,执行其他代码。
执行完毕后出栈,等待被回收

上下文在创建阶段确认变量对象,就是获取变量名,并赋值undefined,在执行阶段才会完成赋值工作,就是变量声明提前

函数声明的执行优先级(也就是创建阶段)会比变量声明的优先级高。所以在执行阶段同名的函数会被同名的变量重新赋值。因为函数优先声明,声明后被变量重新赋值了。

image.png

image.png

开发过程中可以通过单例模式与闭包,完成代码层面或者业务层面的模块分离。通过定义函数,return函数内变量的get和set方法来控制私有变量。

当前函数的this是在函数被调用执行时候才确定的。(在哪里调用,this就指向谁)

在一个函数的执行上下文中,this由该函数的调用者提供,由调用函数的方式来决定其指向。

题目1

var a = 20

var obj ={ 
    a: 40
}

function fn() { 
    
    console.log ('fn this: ',this);
    
    function foo() { 
        
        console.log(this.a);
        
    }
    
    foo()
    
}

fn.call(obj)

fn()

输出为 fn this: obj对象 this.a = 20 fn this: window this.a = 20 疑惑的是第一个输出this都已经是obj了,为啥 this.a还是20,不是obj的a

因为foo是独立调用的,谁.foo() this就是.前面那个对象。前面没.的话this就是window

题目2

function foo () {
    
    console.log(this.a)
}

function active(fn) { 
    fn();
}

var a =20; 
var obj = {

    a: 10,
    getA: foo, 
    active: active

}

active(obj.getA);
obj.active(obj.getA); 

输出为两个20 套用一下

active(obj.getA); //等于下面的代码 
active(function foo () {
    
    console.log(this.a)
}) //等于下面的代码 

function active(function foo () {console.log(this.a)}) { 
    function foo () {console.log(this.a)}
    foo()
}
//调用的时候是在active里面调用的,active里面的foo前面没点,所以this是window 所以this.a是20

obj.active(obj.getA); //等于下面的代码 
obj.active(function foo () {
    
    console.log(this.a)
})  //等于下面代码

active(fn) { 
    fn();  //这里的fn等于function foo () {console.log(this.a)}
}
//原理同上 fn在调用时候没有点,所以this就是window,所以this.a是20


题目3

var n ='window';
var object = {
    n: 'object',
    getN: function() {
        return function() { 
            return this.n;
        } 
    }
}
console.log(object.getN()()) 

输出是window,因为最后return的时候方法调用时候前面没点,所以就是window

改一下

var n ='window';
var object = {
    n: 'object',
    getN: function() {
        console.log(this.n)  //object
        return function() { 
            return this.n;
        } 
    }
}
console.log(object.getN()()) //window

再改一下

var n ='window';
var object = {
    n: 'object',
    getN: function() {
        console.log(this.n) // object
        var that = this //闭包,所以 里面return的this还是object
        return function() { 
            return that.n; // object
        } 
    }
}
console.log(object.getN()()) 

闭包

闭包的意义在于js在执行完垃圾回收机制时,保留一些有用的变量或方法