返回

携手共探原型奥秘,链锁之上的奇妙世界

前端

在编程的世界中,原型(Prototype)是一个关键概念,它相当于一个模具,用来生产实例对象。每个实例对象都有一个指向原型对象的指针,而原型对象又有一个指向构造函数的指针,如此一来就形成了一条原型链,最终指向null

原型链是JavaScript实现继承的方式。当一个函数被用作构造函数时,它会创建一个新的原型对象,该原型对象继承自其父类的原型对象。这样,子类的实例对象就可以访问父类的属性和方法。

作用域是JavaScript中另一个重要的概念。它决定了变量和函数的可见性范围。作用域链是一个由当前作用域及其所有父作用域组成的链条。当在当前作用域中查找变量或函数时,会沿着作用域链逐级向上查找,直到找到为止。

闭包是JavaScript中的一种特殊函数,它可以访问其创建时所在的作用域中的变量。闭包的创建方式是在函数内部定义另一个函数,而内函数引用了外函数中的变量。

原型、原型链、作用域和作用域链、闭包这些概念共同构成了JavaScript编程语言的核心。掌握这些概念对于理解JavaScript的运行机制至关重要。

现在,让我们通过一些实例来加深对这些概念的理解。

原型:

function Person(name) {
  this.name = name;
}

Person.prototype.sayHello = function() {
  console.log("Hello, my name is " + this.name);
};

const person1 = new Person("John");
person1.sayHello(); // Hello, my name is John

在上面的示例中,Person函数是一个构造函数,它创建了Person类型的对象。Person.prototype是一个原型对象,它包含了所有Person类型对象的共有属性和方法。person1是一个Person类型的实例对象,它继承自Person.prototype。当调用person1.sayHello()方法时,JavaScript会在person1对象中查找sayHello方法,如果没有找到,就会沿着原型链向上查找,直到在Person.prototype对象中找到sayHello方法。

原型链:

function Person(name) {
  this.name = name;
}

Person.prototype.sayHello = function() {
  console.log("Hello, my name is " + this.name);
};

function Employee(name, department) {
  Person.call(this, name);
  this.department = department;
}

Employee.prototype = Object.create(Person.prototype);
Employee.prototype.constructor = Employee;

const employee1 = new Employee("John", "Engineering");
employee1.sayHello(); // Hello, my name is John

在上面的示例中,Employee函数是一个子类构造函数,它继承自Person函数。Employee.prototype是一个子类原型对象,它继承自Person.prototypeemployee1是一个Employee类型的实例对象,它继承自Employee.prototypePerson.prototype。当调用employee1.sayHello()方法时,JavaScript会在employee1对象中查找sayHello方法,如果没有找到,就会沿着原型链向上查找,直到在Person.prototype对象中找到sayHello方法。

作用域:

function outer() {
  const outerVariable = "I am an outer variable";

  function inner() {
    const innerVariable = "I am an inner variable";

    console.log(outerVariable); // I am an outer variable
    console.log(innerVariable); // I am an inner variable
  }

  inner();
}

outer();

在上面的示例中,outer函数是一个外部函数,它创建了一个名为outerVariable的变量。inner函数是一个内部函数,它创建了一个名为innerVariable的变量。inner函数可以访问outer函数中的变量,但outer函数不能访问inner函数中的变量。

作用域链:

function outer() {
  const outerVariable = "I am an outer variable";

  function inner() {
    const innerVariable = "I am an inner variable";

    console.log(outerVariable); // I am an outer variable
    console.log(innerVariable); // I am an inner variable
  }

  function deeper() {
    const deeperVariable = "I am a deeper variable";

    console.log(outerVariable); // I am an outer variable
    console.log(innerVariable); // I am an inner variable
    console.log(deeperVariable); // I am a deeper variable
  }

  inner();
  deeper();
}

outer();

在上面的示例中,deeper函数是一个更深的内部函数。deeper函数可以访问outer函数中的变量和inner函数中的变量,但outer函数和inner函数都不能访问deeper函数中的变量。

闭包:

function outer() {
  const outerVariable = "I am an outer variable";

  function inner() {
    const innerVariable = "I am an inner variable";

    return function() {
      console.log(outerVariable); // I am an outer variable
      console.log(innerVariable); // I am an inner variable
    };
  }

  return inner();
}

const closure = outer();
closure();

在上面的示例中,outer函数返回了一个闭包函数。闭包函数可以访问outer函数中的变量和inner函数中的变量,即使outer函数和inner函数已经执行完毕。

原型、原型链、作用域、作用域链和闭包这些概念是JavaScript编程语言的核心。掌握这些概念对于理解JavaScript的运行机制至关重要。