JavaScript闭包理解及使用场景

本文介绍了JavaScript中闭包的概念,如何使用它保护变量和模拟私有方法。同时讨论了柯里化的概念及其在函数优化中的应用。并对比了将属性和方法定义在对象原型或构造器中的优缺点,强调了内存管理和代码组织的最佳实践。
摘要由CSDN通过智能技术生成

我的理解:函数内部定义的函数:在一个函数内部定义另一个函数,内部函数就形成了闭包。

内部函数可以访问和操作外部函数的变量和参数

使用场景

  • 保护变量

  • 延长变量生命周期

模拟私有变量和私有方法

在JavaScript中并没有支持声明私有变量,但我们可以通过闭包来模拟私有方法

let text = "cat, bat, sat, fat";
let pattern = /.at/g;
let matches = text.search(pattern);
console.log(matches); 
​
//使用闭包模拟私有化方法和私有方法
const Counter = () => {
  let count=0
  function Add(val){
    count+=val
    console.log(count)
  }
  return {
    Add:function(){
      Add(1)
    },
    Minus:function(){
      Add(-1)
    }
  }
}
const counter = Counter()
counter.Add()
counter.Minus()

上述中有个私有方法Add,它可以访问到私有变量count并改变其值,外部则无法访问到该私有方法和私有变量count,只能利用暴露出来的Add和Minus函数

柯里化函数

柯里化的意义在于避免频繁调用相同参数的函数的同时,又能轻松重用

下面写一个curry用于柯里化函数

​
function cum(a,b,c){
  console.log(a+b+c)
}
​
function curry(fn){//柯里化函数
  return function curried(...args){
    if(args.length>=fn.length){//如果参数个数达到length,执行原函数
      return fn.apply(this,args)
    }else{
      return function(...args2){
        return curried.apply(this,args.concat(args2))
        //如果参数没有达到length,返回新函数,继续接收参数
      }
    }
  }
}
​
let _sum = curry(sum) //转化为柯里化函数
let function1 = _sum(1)
let function2 = function1(2)
function2(3) //print 6

注意事项

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

例如,在创建新的对象或者类时,方法通常应该关联于对象的原型,而不是定义到对象的构造器中。

原因在于:

关联到对象的原型上:

  1. 共享性:将属性或方法定义在对象的原型上可以实现共享,即所有通过该构造函数创建的对象实例都可以访问和共享这些属性和方法。

  2. 内存占用:对象的原型是在内存中共享的,而不是每个实例都有一份独立的拷贝,因此能够节省内存。

  3. 动态性:可以在运行时动态地为原型添加或修改属性和方法,对已创建的对象实例产生影响。

  4. 继承:对象实例通过原型链继承原型上的属性和方法。

定义到对象的构造器中:

  1. 实例特有:将属性或方法定义在构造函数中会使得每个对象实例拥有自己的一份属性和方法,不会共享给其他对象实例。

  2. 内存占用:每个对象实例都有自己的属性和方法,因此可能会占用更多的内存。

  3. 静态性:构造函数中定义的属性和方法在对象实例被创建后无法修改,除非在构造函数中重新定义或重新赋值。

  4. 不继承:构造函数内部定义的属性和方法是属于构造函数自身的,它们不会被对象实例直接继承。每次使用构造函数创建新对象实例时,这些属性和方法都会被重新创建。

// 将属性和方法关联到对象的原型上
function Person(name) {
  this.name = name;
}
​
Person.prototype.sayHello = function() {
  console.log('Hello, my name is ' + this.name);
};
​
var person1 = new Person('Alice');
var person2 = new Person('Bob');
​
// 所有通过 Person 构造函数创建的对象实例共享原型上的 sayHello 方法
person1.sayHello(); // 输出: Hello, my name is Alice
person2.sayHello(); // 输出: Hello, my name is Bob
​
// 定义属性和方法到对象的构造器中
function Car(make) {
  this.make = make;
  this.start = function() {
    console.log(this.make + ' is starting...');
  };
}
​
var car1 = new Car('Toyota');
var car2 = new Car('Honda');
​
// 每个对象实例有自己的 start 方法,不共享给其他对象实例
car1.start(); // 输出: Toyota is starting...
car2.start(); // 输出: Honda is starting...

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值