了解JavaScript中的作用域、上下文、对象引用和实例化
在本文中,我想解释 JavaScript 中的一些棘手概念,这些概念可能会让人非常困惑,具体取决于您在开发过程中所处的位置。 也就是说,我将讨论 JavaScript 中的对象引用、范围、上下文和实例化。 它应该可以帮助您理解一些在 JavaScript 中看起来很奇怪的行为。
首先,一个例子来说明这一点:
[] === [] // false
哇,刚刚发生的空数组不等于空数组。 JavaScript,你能有多混乱!
对象参考
对象引用的概念可能非常棘手,例如让我们检查一下 object1
和 object2
是否相同:
let object1 = { value:10 }; let object2 = object1; let object3 = { value: 10};
object1 === object2 //true
我们得到了正确的结果,因为 object1
和 object2
都指向内存中的相同参考数据。 如果我们检查 object1
和 object3
是否相同:
object1 === object3 // false
有趣的! 它们都具有相同的值,但为什么它们不一样。 这是因为 object3
在内存中创建了另一个引用,这与 object1
不同,因此 JavaScript 将这两个对象视为不同的对象。
为了进一步解释,假设 object1
被创建为内存中的一个地址,然后 object2
指向同一地址的 object1
。 而 object3
是内存中的另一个地址。 object1
地址不能与 object3
地址相同。
数组参考
回到最初的例子:
[] === [] // false
在 Javascript 中,数组实际上是幕后的对象,因此 JavaScript 将第一个 []
视为一个新对象并将引用存储在内存中,然后将第二个 []
作为不同的引用存储在内存中,所以当检查是否相等,事实证明它们不能相同。
范围和上下文
上下文总是与范围混淆。 遇到大括号时总是会创建一个范围。 例如,如果我们创建一个函数,则会创建一个新作用域:
function sampleScope() { let a = 'a'; console.log(a); }
如果我们要从 sampleScope
函数外部引用变量 a
,它将无法被识别,因为该变量是在 sampleScope
函数范围内定义的。
语境
上下文与范围不同,它告诉您我们当前正在引用的当前对象。 使用 this 关键字 访问上下文。 例如,如果我们使用以下内容从浏览器的控制台记录我们所处的当前上下文:
console.log(this); // Window {postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, parent: Window, …}
它告诉我们当前在 window
对象中。 this
是 Javascript 的一个特殊关键字,它指向当前对象或上下文:
this.alert('hello'); window.alert('hello);
上面的两行本质上是相同的,因为 this
关键字引用了 window
对象,因为那是当前上下文。
如果我们像这样创建一个新对象:
const object4 = { a: function() { console.log(this); } } object4.a(); // {a: ƒ}
我们看到它注销了当前上下文,即 object4
上下文。
实例化
假设我们想通过记录他们的姓名和性别来跟踪教室里的学生,所以我们模拟了一个如下所示的 class:
class Student { constructor(name, gender){ console.log(this); this.name = name; this.gender = gender; } introduceStudent() { console.log(`${this.name}, ${this.gender}`); } }
我们创建了一个接受 name
和 gender
的类,并且还可以访问记录学生姓名的函数。
现在假设我们要创建一个类代表,而不必复制相同的代码并添加额外的信息,我们可以扩展 Student
类,同时为类代表创建一个新类,如下所示:
class Rep extends Student{ constructor(name, gender){ super(name, gender); } introduceClassRep() { console.log(`${this.name}, ${this.gender}, and I'm a class rep`); } }
extends
关键字告诉 JavaScript 将类扩展的任何属性添加到当前类。 每当我们扩展一个类时,我们还需要调用它的构造方法,super
给了我们这样做的能力。
现在让我们创建两个类的实例:
const student1 = new Student('jane', 'female'); const student2 = new Rep('cole', 'male');
创建这些新实例后,您会看到两个控制台输出不同。 这仅仅是因为它们是不同类的实例。
结论
使用 JavaScript,对象的行为一开始可能看起来很复杂,但理解下划线概念可以给你很大的力量,并揭示下划线的简单性。
我们已经了解了对象引用、上下文、范围和实例如何在 JavaScript 中发挥作用,并展示了如何使用它们。 希望您现在对这些更高级的概念有更好的理解! 🏋