乐趣区

关于程序员:解析es6中let和const并模拟实现私有变量

应用 let 和 const 申明变量早曾经司空见惯了。笔者作为面试官面试过上百人,能精确了解 let/const 块级作用域以及的候选人有余一二。本文将深入研究 let 和 const 的实现原理,以及多种形式来模仿公有变量,心愿本文能给初中级前端小伙伴们一点帮忙。

一、letconst 的实现原理

1.1 JavaScript 的作用域链

在深刻理解 letconst 前,让咱们首先回顾一下 JavaScript 中的作用域。作用域是一个决定变量可见性和拜访性的概念。JavaScript 具备两种次要的作用域:全局作用域和函数作用域。

全局作用域是整个程序的顶层作用域,其中申明的变量能够在程序的任何中央拜访。函数作用域限定了变量的作用范畴,只有在函数外部能力拜访这些变量。

1.2 词法环境和变量对象

JavaScript 引擎应用词法环境来治理变量和函数的作用域。词法环境包含两个重要局部:词法环境记录和对外部词法环境的援用。

词法环境记录是一个外部数据结构,用于存储变量和函数申明。全局环境的词法环境记录蕴含全局变量和函数,而函数环境的词法环境记录蕴含局部变量和参数。

1.3 letconst 的块级作用域

ES6 引入了 letconst,它们引入了块级作用域的概念。块级作用域容许咱们在 {} 外部创立独立的作用域,使得变量仅在该块内无效。

if (true) {
  let x = 10;
  const y = 20;
}
console.log(x); // 报错:x is not defined
console.log(y); // 报错:y is not defined

在下面例子中,xy 只在 if 语句块内可见,内部无法访问它们。

1.4 letconst 的长期死区

letconst 引入了“长期死区”(Temporal Dead Zone,TDZ)的概念。TDZ 是指在变量申明之前,变量无奈被拜访或赋值的状态。

console.log(x); // 报错:Cannot access 'x' before initialization
let x = 10;

在下面例子中,因为 x 在申明之前被拜访,触发了 TDZ,导致报错。

1.5 const 的不可变性

const 申明的变量是不可变的,一旦赋值后不能再从新赋值。但须要留神的是,对于援用类型的变量,尽管变量自身不可从新赋值,但其属性依然能够批改。

const pi = 3.14159;
pi = 3.14; // 报错:Assignment to constant variable.

const person = {name: 'John'};
person.name = 'Alice'; // 可行 

在下面例子中,pi 因为是根本数据类型,不能被从新赋值。而 person 是一个对象,尽管不能从新赋值 person,但能够批改其属性。

二、模仿公有变量

2.1 闭包的基本原理

闭包是 js 中的一个概念,它容许函数拜访其内部作用域的变量,即便内部作用域曾经执行结束。闭包通过将外部函数援用到内部函数的变量来实现。

function createCounter() {
  let count = 0;

  // 外部函数 increment 闭包了内部函数 createCounter 的变量 count
  function increment() {
    count++;
    console.log(count);
  }

  return increment;
}

const counter = createCounter();
counter(); // 输入 1
counter(); // 输入 2

在下面例子中,createCounter 函数返回了一个外部函数 increment,该外部函数可能拜访并批改内部函数的 count 变量。这就是闭包的基本原理。

2.2 应用函数闭包

通过函数闭包,咱们能够封装变量并模仿实现公有变量的行为。咱们能够创立一个函数,该函数蕴含了须要爱护的变量,并返回用于拜访和批改这些变量的办法。

function createPrivateVariable(initialValue) {
  let value = initialValue;

  return {getValue: function () {return value;},
    setValue: function (newValue) {value = newValue;},
  };
}

const privateVar = createPrivateVariable(42);
console.log(privateVar.getValue()); // 输入 42
privateVar.setValue(100);
console.log(privateVar.getValue()); // 输入 100

在下面例子中,createPrivateVariable 函数返回了一个对象,该对象蕴含了两个办法 getValuesetValue,用于拜访和批改公有变量 value。这样,咱们胜利地模拟出了一个公有变量的成果,内部无奈间接拜访或批改它。

2.3 模块模式

模块模式是一种常见的实现公有变量的形式,特地实用于大型应用程序的模块化设计。模块模式利用了函数作用域和闭包的个性,将公有变量和办法封装在一个函数外部,并返回一个蕴含私有办法的对象。

const myModule = (function () {
  // 公有变量
  let privateVar = 0;

  // 公有办法
  function privateFunction() {
    // 能够拜访 privateVar
    privateVar++;
  }

  // 私有办法
  return {increment: function () {privateFunction();
    },
    getValue: function () {return privateVar;},
  };
})();

myModule.increment();
console.log(myModule.getValue()); // 输入 1

在下面例子中,myModule 是一个立刻执行函数,它创立了一个闭包,蕴含了公有变量 privateVar 和公有办法 privateFunction。而后,通过返回一个蕴含私有办法的对象,咱们能够拜访和操作公有变量,同时将其封装起来,不会受到内部的烦扰。

2.4 ES6 中的 Symbol

ES6 引入了 Symbol 数据类型,它能够用于创立惟一的属性键,从而实现公有属性。每个 Symbol 值都是惟一的,不会与其余属性键抵触。

const privateVariable = Symbol('privateVar');

const obj = {[privateVariable]: 42,
};

console.log(obj[privateVariable]); // 输入 42

在这个示例中,咱们应用 Symbol 创立了一个公有属性键 privateVariable,而后将其作为对象的属性。这个公有属性对外部是不可见的,只能通过应用雷同的 Symbol 能力拜访。

三、总结

深刻了解 js 的 letconst 变量申明以及模仿实现公有变量的办法,咱们能够更好地把握 JavaScript 的外围概念。
本文咱们探讨了 js 的作用域、块级作用域、闭包、letconst 的行为,以及模仿公有变量的多种形式, 心愿可能帮忙读者更好的了解 js 的外围概念。如果本文对你有帮忙,记得点赞关注我哦~

退出移动版