/*
* 匿名函数 !== 闭包
* 闭包:可以访问另一作用域的变量的函数
* 常见创建方式:在一个函数内部创建另一个函数。
*
* */

function createComparisonFunction(propertyNmae) {

return function (object1,object2) {
let value1 = object1[propertyNmae];
let value2 = object2[propertyNmae];

if (value1 <value2){
return -1;
}else if (value1 > value2){
return 1;
}else{
return 0;
}
};
}

var person1 = {
name : "AA"
};

var person2 = {
name : "A"
};

// console.log(person1["name"]);//AA
// console.log(person1.name);//AA
//调用返回参数的函数的两种方式
// 1:
//console.log(createComparisonFunction("name")(person1,person2));//1
//2:
var comparison = createComparisonFunction("name");
var result = comparison(person1,person2);
console.log(result);//1

/*
* 当某个函数被调用时,会创建一个执行环境及相应的作用域链。
* 使用arguments和其他命名参数的值来初始化函数的活动对象。
* 在作用域链中,外部函数的活动对象始终处于第二位置,外部函数的外部函数处于第三位置,...直到作为作用域链终点的全局执行环境。
*
* 后台每一个执行环境都有一个表示表示变量的对象--变量对象。
* 全局环境的变量始终存在,某一函数的变量对象在局部环境中,只有在函数执行时才存在。
* */


function compare(value1,value2) {
if (value1 <value2){
return -1;
}else if (value1 > value2){
return 1;
}else{
return 0;
}
}
var result = compare(5,10);
console.log(result);

/*

  • 创建一个函数时:
  • 1,预先创建一个包含全局变量对象的作用域链(保存在[[Scope]]属性中)
  • 调用这个函数时:
  • 1,创建一个执行环境
  • 2,复制函数的[[Scope]]属性中的对象,构建起执行环境的作用域链.
  • 3,创建活动对象(函数的arguments和参数存放在其中),并推入执行环境作用域链的前端。

  • 以上面compare函数为例:
  • compare的执行环境中有作用域链,作用域链中包含两个元素:全局变量对象和compare的活动对象
  • 全局变量对象中有result和compare compare指向compare的执行环境
  • compare的活动对象中有arguments:【5,10】,value:5 ,value2 : 10

*无论什么时候在函数中访问一个变量时,就会从作用域链中搜索具有相应的名字的变量。

  • 一般,当函数执行完毕后,局部活动对象就会销毁,内存中仅保存全局作用域(全局执行环境的变量对象)。
  • 但是,闭包有所不同:
  • 在另一个函数内部定义的函数会将包含函数(即外部函数)的活动对象添加到它的作用域链中。
  • 因此,才createComparisonProperty()函数内部定义匿名函数的作用域链中,会包含外部函数createComparisonProperty()的活动对象(arguments),
  • var comparison = createComparisonFunction(“name”);
  • var result = comparison(person1,person2);
  • 这两行代码是在,内部函数从外部函数中返回后,内部函数的作用域链被初始化为包含外部函数的活动对象和全局变量的作用域链,
  • 这样匿名函数就可以访问外部函数中定义的所有变量。
  • 更重要的是外部函数执行完后,其活动对象也不会销毁,因为匿名函数的作用域链仍然在引用这个活动对象(参数),不过执行环境的作用域链会被销毁,活动对象仍在内存中;
  • 直到外部函数被销毁后,外部的活动对象才会销毁:comparison = null
  • */