【问题标题】:Constructor pattern by Douglas CrockfordDouglas Crockford 的构造函数模式
【发布时间】:2015-01-31 04:05:33
【问题描述】:

最近我看了一个 Douglas Crockford 的演讲(他的演讲让我着迷,但总是让我感到困惑)。他举了一个构造函数的例子,但我不太明白我将如何在实践中使用它:

function constructor(spec) {
  var that = other_constructor(spec),
    member,
    method = function () {
      //spec , member, method
    };

  that.method = method;
  return that;      
}

也许有人可以根据这种模式给我一个简单的工作示例?

【问题讨论】:

    标签: javascript oop constructor


    【解决方案1】:

    这是道格拉斯·克罗克福德 (Douglas Crockford) 幻灯片中的原始资料:

    function constructor(spec) {
      let {member} = spec,
          {other} = other_constructor(spec),
          method = function () {
            // member, other, method, spec
          };
      return Object.freeze({
        method,
        other
      });
    }
    

    以下示例是 Douglas Crockford 2014 年对象创建模式的更具体版本。

    Douglas Crockford 大量使用了 ECMAScript 6 功能,例如解构等!!

    在 node.js 中使用以下选项启动代码(启用 ES6):

    node --harmony --harmony_destructuring demo.js
    

    demo.js

    // Douglas Crockford 2014 Object Creation
    (function() {
      'use strict';
    
      function adress(spec) {
    
        let {
          street, city
        } = spec,
        logAdress = function() {
          console.log('Adress:', street, city);
        };
        return Object.freeze({
          logAdress
        });
      };
    
      function person(spec) {
    
        let {
          preName,
          name
        } = spec, {
          logAdress
        } = adress(spec),
          logPerson = function() {
            // member, other, method, spec
            console.log('Name: ', preName, name);
            logAdress();
          };
        return Object.freeze({
          logPerson,
          logAdress
        });
      };
    
    
      let myPerson = person({
        preName: 'Mike',
        name: 'Douglas',
        street: 'Newstreet',
        city: 'London'
      });
    
      myPerson.logPerson();
    })();
    

    根据 Douglas Crockford 的谈话,他避免使用:

    • Object.create
    • 这个!!!

    观看原始 Crockford 视频: https://www.youtube.com/watch?v=PSGEjv3Tqo0

    Crockford Douglas Object Creation Pattern 2014 的一个很好的解释是这个博客:https://weblogs.asp.net/bleroy/crockford%E2%80%99s-2014-object-creation-pattern

    【讨论】:

    • 构造函数在 JS 中应始终大写。
    • 稳住。这样做是为了符合 Crockford 的说法,即它不需要新的前缀。
    • @Rob Raisch 如果我没记错的话,他确实提到,为了不与构造函数混淆,他选择不使用大写字母。
    【解决方案2】:

    这是在工厂函数中使用另一个构造函数返回对象的示例。在这种情况下,other_constructor 是构造函数,它创建了一个other_constructor 类型的对象(理想情况下,这将被大写)。该对象存储在that 中。在这个工厂函数中,method 是一个已定义的函数,它被添加到that 以以某种方式扩展对象的功能。

    构造函数和工厂函数的区别在于工厂函数只是一个返回对象的普通函数,而构造函数有this指向新对象,通常必须用new调用它前面的关键字。

    一个典型的构造函数:

    function Dog(breed, height, name){
      this.breed = breed;
      this.animalType = "dog";
      this.height = height;
      this.name = name;
      // calling `return` isn't necessary here
    }
    

    它的用法:

    var lab = new Dog("labrador", 100, "Sugar"); // `new` is necessary (usually)
    console.log(lab.animalType); // prints out "dog"
    console.log(lab.height); // prints out 100
    

    一个典型的工厂函数:

    function createDog(breed, height, name){
      var dog = {
        breed: breed,
        height: height,
        animalType: "dog",
        name: name
      };
      return dog; 
      // `return` is necessary here, because `this` refers to the 
      // outer scope `this`, not the new object
    }
    

    及其用法:

    var lab = createDog("labrador", 100, "Sugar"); // notice no need for `new`
    console.log(lab.animalType); // prints out "dog"
    console.log(lab.height); // prints out 100
    

    at Eric Elliot's blogat Eric Elliot's blog

    【讨论】:

    • 谢谢,这对我来说很有意义。类似于面向对象语言中的类构造函数
    【解决方案3】:

    Douglas Crockford 的新构造函数模式的 Vanilla JavaScript 示例及说明:

    console.clear();
    var fauna = (function (){
      privitizeNewVariables=function (specs) {
        if (!specs.is_private) {
          var members = Object.assign({}, specs);
          members.is_private = true;
          return members;
        }
        return specs;
      },
      newAnimal=function (specs) {
        var members = privitizeNewVariables(specs);
        members.inheritance_type_list = ['Animal'];
        whenInDanger = function () {
          try{
            console.log('When in danger ', members.common_name);
            members.movesBy();
          }catch (e){
            console.log('Error - whenInDanger() has no movesBy()');
          }
        };
        var isA = function(object_type){
          if (members.inheritance_type_list.indexOf(object_type)>-1) {
            console.log(members.common_name, 'is a', object_type);
          }else{
            console.log(members.common_name, 'is not a', object_type);
          }
        }
        return Object.freeze({
          whenInDanger: whenInDanger,
          isA: isA
        });
      },
      newSnake=function (specs){
        var members = privitizeNewVariables(specs);
        members.movesBy = function () {
          console.log('Moves By: slithering');
        };
        colorScheme = function () {
          console.log('Color scheme :', members.color_scheme);
        };
        aPrivateFunction = function (){
          console.log('I only exist inside a Snake object');
        };
        var an_animal = newAnimal(members);
        members.inheritance_type_list.unshift('Snake');
        return Object.freeze({
          whenInDanger: an_animal.whenInDanger,
          isA: an_animal.isA,
          movesBy: members.movesBy,
          colorScheme: colorScheme
        });
      };
      return {
        newAnimal:newAnimal,
        newSnake: newSnake
      }
    })();
    var animal_specs = {common_name: 'Alf the animal'};
    var an_animal = fauna.newAnimal(animal_specs);
    animal_specs.common_name = "does not change Alf's common_name";
    an_animal.whenInDanger();
    console.log(an_animal);
    console.log('-');
    var snake_specs = {common_name: 'Snorky the snake',
     color_scheme:'yellow'};
    var a_snake = fauna.newSnake(snake_specs);
    a_snake.whenInDanger();
    console.log('-');
    a_snake.colorScheme();
    a_snake.isA('Animal');
    a_snake.isA('Snake');
    a_snake.isA('Bear');
    console.log('-');
    console.log(fauna);

    【讨论】:

      【解决方案4】:

      function Car(model, year, miles, price) {
      
        this.model = model;
        this.year = year;
        this.miles = miles;
        this.price = price;
      
        this.toString = function() {
          return this.model + " has done " + this.miles + " miles and cost $" + this.price;
        };
      }
      
      // We can create new instances of the car
      var civic = new Car("Toyota Prius", 2015, 1500, 12000);
      var mondeo = new Car("Ford Focus", 2010, 5000, 3000);
      
      // these objects
      console.log(civic.toString());
      console.log(mondeo.toString())

      阅读更多关于构造函数模式http://www.sga.su/constructor-pattern-javascript/

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2015-02-20
        • 1970-01-01
        • 2019-09-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-03-14
        相关资源
        最近更新 更多