david2tdw / blog

学习记录
1 stars 1 forks source link

[JS] 分享-闭包 #168

Open david2tdw opened 4 years ago

david2tdw commented 4 years ago

作用域

通过这段代码可以看出函数会形成局部作用域,在局部声明的变量是不会挂载到全局中。在全局中的函数声明会直接挂载到window上。 弊端:如果大量的函数声明在全局中会出现全局污染,命名冲突等问题

关于全局污染的问题,常用的方式有:

  (function print1 (){
    var a = 1
    console.log(a)
  })()
  console.log(window.print1)

闭包

闭包的基础用法

- 基础用法
```js
function makeFunc() {
    var name = "Mozilla";
    function displayName() {
        alert(name);
    }
    return displayName;
}

var myFunc = makeFunc();
myFunc();
function makeAdder(x) {
  return function(y) {
    return x + y;
  };
}

var add5 = makeAdder(5);
var add10 = makeAdder(10);

console.log(add5(2));  // 7
console.log(add10(2)); // 12

add5 = null
add10 = null

makeAdder 是一个函数工厂 — 他创建了将指定的值和它的参数相加求和的函数 add5 和 add10 都是闭包。它们共享相同的函数定义,但是保存了不同的词法环境

在javascript中,如果一个对象不再被引用,那么这个对象就会被垃圾回收机制回收;

如果两个对象互相引用,而不再被第3者所引用,那么这两个互相引用的对象也会被回收。

console.log(Counter.value()); / logs 0 / Counter.increment(); Counter.increment(); console.log(Counter.value()); / logs 2 / Counter.decrement(); console.log(Counter.value()); / logs 1 /


```js
var makeCounter = function() {
  var privateCounter = 0;
  function changeBy(val) {
    privateCounter += val;
  }
  return {
    increment: function() {
      changeBy(1);
    },
    decrement: function() {
      changeBy(-1);
    },
    value: function() {
      return privateCounter;
    }
  }  
};

var Counter1 = makeCounter();
var Counter2 = makeCounter();
console.log(Counter1.value()); /* logs 0 */
Counter1.increment();
Counter1.increment();
console.log(Counter1.value()); /* logs 2 */
Counter1.decrement();
console.log(Counter1.value()); /* logs 1 */
console.log(Counter2.value()); /* logs 0 */

使用闭包常见的问题

function setupHelp() { var helpText = [ {'id': 'email', 'help': 'Your e-mail address'}, {'id': 'name', 'help': 'Your full name'}, {'id': 'age', 'help': 'Your age (you must be over 16)'} ];

for (var i = 0; i < helpText.length; i++) { var item = helpText[i]; document.getElementById(item.id).onfocus = function() { showHelp(item.help); } } }

setupHelp();

我们会发现不论点击那个input框得到结果都是最后一个的值

- 闭包中this的指向

```js
var name = 'window'
var obj = {
  name: 'obj',
  getName: function () {
    return function () {
      return this.name
    }
  }
}
console.log(obj.getName()())
function MyObject (name, message) {
  this.name = name.toString();
  this.message = message.toString();
  this.getName = function() {
    return this.name;
  };

  this.getMessage = function() {
    return this.message;
  };
}

var a = new MyObject('zhang', 'hello')
console.log(a.getMessage())
console.log(a.getName())

这段代码导致每次构造器被调用时,方法都会被重新赋值一次。没有使用到闭包的好处

如果不是某些特定任务需要使用闭包,在其它函数中创建函数是不明智的,因为闭包在处理速度和内存消耗方面对脚本性能具有负面影响

function MyObject (name, message) {
  this.name = name.toString();
  this.message = message.toString();
}
MyObject.prototype.getName = function() {
    return this.name;
  };

MyObject.prototype.getMessage = function() {
    return this.message;
  };
var a = new MyObject('zhang', 'hello')
console.log(a.getMessage())
console.log(a.getName())

[鲍老师的分享]()

david2tdw commented 4 years ago

index.html

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>module.exports</title>
</head>
<body>
  <p id="help">Helpful notes will appear here</p>
  <p>E-mail: <input type="text" id="email" name="email"></p>
  <p>Name: <input type="text" id="name" name="name"></p>
  <p>Age: <input type="text" id="age" name="age"></p>

   <script src="./test.js"></script>
   <script src="./test1.js"></script>
</body>
</html>

test.js

function showHelp(help) {
  document.getElementById('help').innerHTML = help;
}

function setupHelp() {
  var helpText = [
      {'id': 'email', 'help': 'Your e-mail address'},
      {'id': 'name', 'help': 'Your full name'},
      {'id': 'age', 'help': 'Your age (you must be over 16)'}
    ];

  for (var i = 0; i < helpText.length; i++) {
    var item = helpText[i];
    document.getElementById(item.id).onfocus = function() {
      showHelp(item.help);
    }
  }
}

setupHelp();