New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

闭包 #29

Open
paddingme opened this Issue Aug 22, 2015 · 0 comments

Comments

Projects
None yet
1 participant
@paddingme
Owner

paddingme commented Aug 22, 2015

闭包的两个特点:

  1. 闭包作为与函数成对的数据,在函数执行过程中处于激活(即可访问)状态;
  2. 闭包在函数运行结束后,保持运行过程的最终数据状态。

总的来说,函数闭包决定了:闭包所对应的函数代码如何访问数据,以及闭包内的数据何时销毁。

// 没有函数实例产生
function myFunc(){
}

var f1 = myFunc;
var f2 = myFunc;

alert(f1 === f2)
function MyObject(){
}

MyObject.prototype.method = function(){}

var obj1 = new MyObject();
var obj2 = new MyObject();

alert( obj1.method === obj2.method)

// 对象的实例只持有原型中的方法的一个引用,因为也不产生(方法)函数的实例。
function MyObject(){
    this.method = function(){}
}

var obj1 = new MyObject;
var obj2 = new MyObject;
alert( obj1.method === obj2.method)
//false
//构造器函数

function MyObject(){
    var instance_data = 100;
    this.getInstanceData = function(){
        return instance_data;
    }

    this.setInstanceData = function(v) {
        instance_data = v;
    }
}

// 使用一个额匿名函数去修改构造器的原型 MyObject.prototype,以访问该匿名函数中的 upvalue

void function(){
    var class_data = 5;

    this.getClassData = function(){
        return class_data;
    }

    this.setClassData = function(v){
        class_data = v;
    }
}.call(MyObject.prototype);

var obj1 = new MyObject();
var obj2 = new MyObject();

// obj1 与 obj2 的 getInstance 是不同函数实例,因此访问的是不同闭包的 upvalue
obj1.setInstanceData(10);
console.log(obj2.getInstanceData());

// obj1 与 obj2 的 getClassData 是同一个函数实例,因此在访问相同 的 upvalue. 
obj1.setClassData(20);
console.log(obj2.getClassData());
function aFunc(){
    function MyFunc(){}
    return myFunc;
}

var f1 = new aFunc();
var f2 = new aFunc();
console.log(f1===f2)
//FALSE
//foo & bar 产生函数实例
function foo(){
    var  MyFunc = function(){}
    return MyFunc;
}

function bar(){
    return function(){

    };
}
//返回同一个实例

var aFun3 = function(){
    var foo = function(){
        console.log(111)
    };

    return function(){
        return foo;
    }
}()

var f3 = aFun3();
var f4 = aFun3();
console.log(f3 === f4)

调用对象:

  1. 对象属性与变量没有本质属性;
  2. 全局变量其实是“全局对象”的属性;
  3. 局部变量其实是“调用对象”的属性

“调用对象”的局部变量维护规则

  1. 在函数开始执行时,varDecls 中所有值将被置为 undefined。 因此我们无论如何访问函数,变量初始值总为 undefined。
  2. 函数执行结束并退出时,varDecls 不会被重置,即有了函数能够提供“在函数内保存数据”。
  3. 函数内部数据持续的生存周期,取决于该函数实例是否存在活动引用——如果没有,则调用对象被销毁。

“全局对象”的变量维护规则

  1. 由于该函数从来不被再次进入,因此不会被重新初始化;
  2. 由于该函数仅有一个个被系统持有的实例,因此他自身和内部数据总不被销毁。

函数闭包 与 “调用对象”的生存周期

在运行期改函数实例有一个函数闭包,在执行时,引擎会:

  • 创建一个函数实例;
  • 为该函数实例创建一个闭包;
  • 为改函数实例(及其闭包)的运行环境从 ScriptObject(调用对象) 复制一个调用对象。
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment