webveuje/js/kejian/zuoyongyu.md
2021-03-23 10:58:10 +08:00

4.5 KiB
Raw Blame History

作用域

练习

var color = "blue";

function changeColor() {
  let anotherColor = "red";

  function swapColors() {
    let tempColor = anotherColor;
    anotherColor = color;
    color = tempColor;

    // 这里可以访问color、anotherColor和tempColor
  }

  // 这里可以访问color和anotherColor但访问不到tempColor
  swapColors();
}

// 这里只能访问color
changeColor();

分析上面的作用域链:

展开查看
  • window
    • color
    • changecolor()
      • anothercolor
      • swapcolors()
        • tempcolor

垃圾回收机制

优化内存占用的最佳手段就是保证在执行代码时只保存必要的数据。如果数据不再必要那么把它设置为null ,从而释放其引用。这也可以叫作解除引用 。这个建议最适合全局变量和全局对象的属性。 局部变量在超出作用域后会被自动解除引用 即 全局变量(GO) 不会被销毁,但是局部变量(AO)函数执行完后会被销毁 也可以手动销毁变量即赋值为null

如下面的例子所示:

function createPerson(name){
  let localPerson = new Object();
  localPerson.name = name;
  return localPerson;
}

let globalPerson = createPerson("Nicholas");

// 解除globalPerson对值的引用

//globalPerson = null;

解析:

展开查看 在上面的代码中变量globalPerson 保存着createPerson() 函数调用返回的值。在createPerson() 内部localPerson 创建了一个对象并给它添加了一个name 属性。然后localPerson 作为函数值被返回并被赋值给globalPerson 。localPerson 在createPerson() 执行完成超出上下文后会自动被解除引用不需要显式处理。但globalPerson 是一个全局变量,应该在不再需要时手动解除其引用,最后一行就是这么做的。

不过要注意,解除对一个值的引用并不会自动导致相关内存被回收。解除引用的关键在于确保相关的值已经不在上下文里了,因此它在下次垃圾回收时会被回收。

闭包

闭包是指有权访问另一个函数作用域中的变量的函数。创建闭包的常见方式,就是在一个函数内部创建另一个函数。


function a() {
    var x = 0;
    return function(y) {
        x = x + y;
        // return x;
        console.log(x);
    }
}
var b = a();
b(1); //1
b(1); //2

练习1

function fn() {
    var max = 10;
    return function bar(x) {
        if (x > max) {
            console.log(x);
        }
    };
}
var f1 = fn();
f1(15);

练习2

function init() {
    var name = "Mozilla"; // name 是一个被 init 创建的局部变量
    function displayName() { // displayName() 是内部函数,一个闭包
        alert(name); // 使用了父函数中声明的变量
    }
    displayName();
}
init();

init() 创建了一个局部变量 name 和一个名为 displayName() 的函数。displayName() 是定义在 init() 里的内部函数,并且仅在 init() 函数体内可用。请注意displayName() 没有自己的局部变量。然而,因为它可以访问到外部函数的变量,所以 displayName() 可以使用父函数 init() 中声明的变量 name 。
hrefs: https://blog.csdn.net/weixin_43586120/article/details/89456183

http://www.ruanyifeng.com/blog/2009/08/learning_javascript_closures.html


(function() { 
  var m = 0; 
  function getM() { return m; } 
  function seta(val) { m = val; } 
  window.g = getM; 
  window.f = seta; 
})(); 
f(100);
console.info(g()); 


function fn(){
  var arr = [];
  for(var i = 0;i < 5;i ++){
	arr[i] = (function(i){
		return function (){
			return i;
		};
	})(i);
  }
  return arr;
}
// 立即执行函数  每调用一次完成后就自动销毁

var list = fn();
for(var i = 0,len = list.length;i < len ; i ++){
  console.log(list[i]());
}  //0 1 2 3 4

function fn(){
   var arr = [];
   for(var i = 0;i < 5;i ++){
	 arr[i] = function(){
		 return i;
	 }
   }
   return arr;
}
var list = fn();
for(var i = 0,len = list.length;i < len ; i ++){
   console.log(list[i]());
}  //5 5 5 5 5

var lis = document.getElementsByTagName("li");
for(var i=0;i<lis.length;i++){
  (function(i){
      lis[i].onclick = function(){
           console.log(i);
      };
  })(i);       //事件处理函数中闭包的写法
}  


   var  li = document.getElementsByTagName( "li" );
   for ( var  i = 0; i < li.length; i++) {
   li[i].addEventListener( "click" , function  () {
   console.log(i);
   })
}