美文网首页
JavaScript基础三:Objects、Classes和面向

JavaScript基础三:Objects、Classes和面向

作者: 北雁南飞_8854 | 来源:发表于2020-11-22 14:16 被阅读0次

    对象创建(Object Creation)

    尽管使用Object构造函数或者对象字面量可以很方便的创建单个的对象,但是这也有一个明显的缺点:基于相同的接口创建多个对象时,存在大量的代码冗余。

    1. 工厂模式(The Factory Pattern)

    使用工厂模式创建特定接口的对象的例子:

    function createPerson(name, age, job) {
      let o = new Object();
      o.name = name;
      o.age = age;
      o.job = job;
      o.sayName = function() {
        console.log(this.name);
      };
      return o;
    }
    
    let person1 = createPerson("Nicholas", 29, "Software Engineer");
    let person2 = createPerson("Greg", 27, "Doctor");
    

    2. Function构造函数模式(The Function Constructor Patter)

    function Person(name, age, job){
      this.name = name;
      this.age = age;
      this.job = job;
      this.sayName = function() {
        console.log(this.name);
      };
    }
    let person1 = new Person("Nicholas", 29, "Software Engineer");
    let person2 = new Person("Greg", 27, "Doctor");
    person1.sayName(); // Nicholas
    person2.sayName(); // Greg
    

    与前面的createPerson()函数相比,Person()函数不同之处有:

    1. 没有显式的创建对象;
    2. properties和methods直接被赋给了this对象;
    3. 没有return语句。
      按照惯例,constructor函数总是以大写字母开头,非constructor函数以小写字母开头。
      以这种方式创建实例时,会执行以下流程:
    4. 在内存中创建一个新的object;
    5. 将新object的[[Prototype]]指针赋给constructor的prototype属性;
    6. 将constructor的this指针赋给新object,因此this指向了新object;
    7. 如果constructor返回了non-null的object,则返回该object;否则返回刚刚创建的object。

    Constructors as Functions

    constructor functions和其他functions之间没有语法的区别,使用new操作符调用的函数就可以视作constructor 函数。举例:

    // use as a constructor
    let person = new Person("Nicholas", 29, "Software Engineer");
    person.sayName(); // "Nicholas"
    // call as a function
    Person("Greg", 27, "Doctor"); // adds to window
    window.sayName(); // "Greg"
    // call in the scope of another object
    let o = new Object();
    Person.call(o, "Kristen", 25, "Nurse");
    o.sayName(); // "Kristen"
    

    constructor pattern的问题

    使用Constructor的主要问题是:
    每一个实例都会创建一个单独的Function实例,而这些Function实例是在做同一件事情。
    如前面的例子中,person1和person2都有一个sayName()方法,但是他们不是同一个Function实例。

    console.log(person1.sayName == person2.sayName); // false
    

    因此可以把Function的定义移到constructor的外面。

    function Person(name, age, job){
      this.name = name;
      this.age = age;
      this.job = job;
      this.sayName = sayName;
    }
    function sayName() {
      console.log(this.name);
    }
    let person1 = new Person("Nicholas", 29, "Software Engineer");
    let person2 = new Person("Greg", 27, "Doctor");
    person1.sayName(); // Nicholas
    person2.sayName(); // Greg
    

    Prototype模式(The Prototype Pattern)

    使用prototype的好处是该prototype所有的properties和methods可以在所有的对象实例之间共享。

    Prototypes是如何工作的?

    无论何时,只要一个函数被创建,它的prototype属性也会被创建。
    默认情况下,所有的prototypes会自动获取一个constructor属性指向construct函数。
    每当调用constructor来创建一个实例时,该实例拥有一个指向constructor的prototype的内部指针,称之为[[Prototype]]。并没有一个标准的方式来访问[[Prototype]],但是Firefox, Safari和Chrome都支持__proto__属性:指向constructor函数的prototype。
    需要重点理解的是,是instance和constructor的prototype之间存在直接的关联,而不是instance和constructor之间。

    1. 由相同的constructor创建的两个instances共享同一个prototype对象;
    console.log(person1.__proto__ === Person.prototype); // true
    conosle.log(person1.__proto__.constructor === Person); // true
    console.log(person1.__proto__ === person2.__proto__); // true
    

    相关文章

      网友评论

          本文标题:JavaScript基础三:Objects、Classes和面向

          本文链接:https://www.haomeiwen.com/subject/rieuiktx.html