【问题标题】:How to do class free inheritance in JavaScript (Crockford style)如何在 JavaScript 中进行无类继承(Crockford 风格)
【发布时间】:2017-07-02 17:40:07
【问题描述】:

背景

我正在努力提高我的 JS 技能,并且我正在关注 JS 世界中的一些大型实体。这样的实体就是道格拉斯·克罗克福德(Douglas Crockford),他正在宣扬一种无阶级的范式。

在 Nordic js(我强烈推荐)看过他之后,我对他 makes objects 没有任何分类的方式感到困惑。

问题

我现在尝试将他的幻灯片复制到一个使用异常的简单示例中,但我无法使其正常工作。

我不明白我的 UniformityException.js 文件如何重用来自 Exception.js 的代码并与 Crockford 的意识形态保持一致。

这里的问题是我在UniformityException.js 中的specs 变量只有一个write 方法,这是理所当然的。

看了很多次幻灯片,不大量使用Object.assign,我无法理解如何更改此代码。

代码

Exception.js

"use strict";

let jsonfile = require("jsonfile");
let _ = require("underscore");

let Exception = function(args){

    let DEFAULT_PROPS = {
        exceptionName: "Exception",
        outputFolder: "./ErrorLogs/",
        fileExtension: ".txt"
    };

    DEFAULT_PROPS.message = "A generic exception occurred.";
    DEFAULT_PROPS.outputFile = DEFAULT_PROPS.exceptionName  + "_" + _.now();

    let props = Object.assign(DEFAULT_PROPS, args);

    let write = function(){
        jsonfile.writeFile(props.outputFolder + props.outputFile + props.fileExtension, props.message, error => {
            if(_.isNull(error) || _.isUndefined(error))
                console.log(error);
        });
    };

    return Object.freeze({
        write
    });
};

module.exports = Exception;

UniformityException.js

"use strict";

let Exception = require("./Exception.js");
let jsonfile = require("jsonfile");
let _ = require("underscore");

let UniformityException = function(args){

    let specs = Exception({
        exceptionName: "UniformityException",
        fileExtension: ".json"
    });

    let write = function(info){
        jsonfile.writeFile(specs.outputFolder + specs.outputFile, info, error => {
            if(_.isNull(error) || _.isUndefined(error))
                console.log(error);
        });
    };

    return Object.freeze({
        write
    });
};

module.exports = UniformityException;

index.js

"use strict";

let UniformityException = require("./Exceptions/UniformityException.js");

let myUniformException = UniformityException();

myUniformException.write({fruit: "banana"});

问题

  1. 如何让 UniformityException.js 以符合 Crockford 风格的方式重复使用来自 Exception.js 的代码?

像往常一样,应避免使用 newthisObject.create 等关键字。

【问题讨论】:

  • 你想重用哪一部分? write 函数?
  • 一切。但在这种情况下,我想重用 Exception.js 中的 props 变量
  • 不能使用上面的代码,因为Expection 暴露的唯一属性是writeprops 是其构造函数中的私有变量。如果您希望该部分公开可用,则必须将其添加到返回(冻结)对象中。
  • 没有任何分类法” - 这不是真的。出于某种原因,他只是不使用原型继承。他的函数(我敢称它们为类吗?)确实有一个层次结构。在您的情况下,UniformityException 不能扩展 Exception,因为它的 write 方法不可重用。
  • 我不明白为什么公开props 应该违反伟大的 Crockford 的“不可或缺”的法律。这基本上就是{other} = other_constructor(spec) 在他的幻灯片中所做的。 附带说明: 有很多人不服从“JS 教父”,但仍然是伟大的开发者!过于教条不会让你成为任何语言的更好的开发者:)

标签: javascript node.js class ecmascript-6


【解决方案1】:

你需要什么

为此,您需要使用Destructuring assignment pattern。使用此模式,幻灯片中的以下代码:

function animal(spec) {
  let {body, type, name} = spec;
}

将转换为以下内容:

function animal(spec) {
    let body = spec.body;
    let type = spec.type;
    let name = spec.name;
}

这实际上是工厂模式的 ECMA6 版本,如这篇博文 constructors VS factories 中所述。

考虑到这一点,我们现在可以转到代码。

代码

index.js

"use strict";

let _ = require("underscore");
let Exception = require("./Exceptions/Exception.js");
let UniformityException = require("./Exceptions/UniformityException.js");

let jsonParams = {
    outputFolder: "./ErrorLogs/",
    fileExtension: ".txt",
    message: {info: "A generic error ocurred."},
    exceptionName: "Exception",
};

let myException = Exception(jsonParams);
myException.write();

jsonParams.fileExtension  = ".json";
jsonParams.exceptionName = "UniformException";
jsonParams.outputFileName = jsonParams.exceptionName + "_" + _.now();

let myUniformException = UniformityException(jsonParams);
myUniformException.write({
    fruit: "banana"
});

Exception.js

"use strict";

let jsonfile = require("jsonfile");
let _ = require("underscore");

let Exception = function(args) {
    let {
        outputFolder,
        fileExtension,
        exceptionName,
        message,
        outputFileName,
    } = args;

    outputFileName = outputFileName|| (exceptionName  + "_" + _.now());

    let filePath = outputFolder + outputFileName + fileExtension;

    let write = function() {
        jsonfile.writeFile(filePath, message, error => {
            if (!_.isNull(error) && !_.isUndefined(error))
                console.log(error);
        });
    };

    return Object.freeze({
        filePath,
        write
    });
};

module.exports = Exception;

UniformityException.js

"use strict";

let Exception = require("./Exception.js");
let jsonfile = require("jsonfile");
let _ = require("underscore");

let UniformityException = function(args) {

    let {filePath} = Exception(args),

        write = function(info) {
            jsonfile.writeFile(filePath, info, error => {
                if (!_.isNull(error) && !_.isUndefined(error))
                    console.log(error);
            });
        };

    return Object.freeze({
        filePath,
        write
    });
};

module.exports = UniformityException;

我想指出的是,您的 工厂函数都应该以小写字母开头 (function animal),并且可以遵循驼峰式约定并将其命名为 'animalConstructor() '。

通常,按照惯例,需要使用new 的构造函数名称带有第一个大写字母(function Animal)。为避免将来出现混淆,您应该重命名异常。

附加

我也强烈推荐的另一个资源来自邪恶帝国:

我认为这是对 Crockford 工厂功能的准确解释。

希望对您有所帮助!

【讨论】:

  • 我重新做了我的回答,希望你喜欢,Flame @Flame_Phoenix
  • “为了做到这一点,你需要使用解构赋值模式。” 你说的那个是什么?解构赋值不会启用以前不可能的任何东西。这是误导。整个答案似乎集中在 如何 做某事而不是 what 做。据我所知,重要的部分是在Exception 对象上导出filePath(这基本上是我写的,即只有暴露的才能被重用)。
  • Soldeplata 的回答比你的要好得多,因为它清楚地回答了我的问题。
【解决方案2】:

您只能“重用”Exception 重新调整的内容。 IE。如果您希望能够直接访问props,则需要公开它。没有办法解决。

这实际上与您在其他基于类的语言中发现的可见性模型一致:私有成员(例如props)只能由类本身访问。如果子类应该具有访问权限,许多语言都提供“受保护”模式,但 JS 没有这样的东西。


您可以考虑让Exception 接受一个将其“私有”成员传递给的函数,而不是将其添加到函数返回的对象中,就像Promise 所做的那样。不过,不确定 Crockford 对此有何看法。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-10-31
    • 2016-08-31
    • 2012-12-25
    • 2013-04-30
    • 1970-01-01
    • 2011-03-17
    • 2013-07-11
    • 2020-01-17
    相关资源
    最近更新 更多