【问题标题】:Concept: Creating a function that acts like a constructor in JavaScript概念:在 JavaScript 中创建一个类似于构造函数的函数
【发布时间】:2017-09-07 08:47:31
【问题描述】:

我们想要一个可以将方法应用于输入对象的函数。

首先,我们创建一个函数。

$ = function () { /* Constructor Code */ };

然后,我们添加一个方法。例如,type。该方法将使用此函数:

function () { return toString.call(this).slice(8, -1);

最后,我们测试这个函数,看看我们是否得到了正确的输出。这是我们希望看到的:

$("test"); // Output: "test"
$("test").type(); // Output: "String"
$(document.body).type(); // Output: "HTMLBodyElement"

输出与输入的唯一区别是方法的应用。

使用Object.addProperties 不起作用,因为它将输入转换为对象:

$("test").type(); // Output: "Object"

此外,使用eval 相关的方法也不起作用,因为某些对象不会转换为字符串:

$(document.body).type(); // Error: Can't convert element to string!

手动将对象的属性添加到对象也是如此。

$("test").type(); // Can't apply function to literal string!

问题是,我们做什么

【问题讨论】:

    标签: javascript methods constructor properties prototype


    【解决方案1】:

    一种方法是将方法应用于输入的原始版本。

    这是通过Object.assign 完成的。这是一个快速实现:

    $ = function (_) {
      return Object.assign(_, {
        type: function () { return toString.call(this).slice(8, -1) }
      })
    };
    

    这是输出:

    $("test").type() // Output: "String"
    $(document.body).type() // Output: "Date"
    

    我们也可以使用一个变量作为方法列表,它会返回相同的输出:

    $ = function (_) {
      return Object.assign(_, $.methods)
    };
    
    $.methods = ({
      type: function () { return toString.call(this).slice(8, -1) }
    });
    

    但是,这些解决方案都需要valueOf 来检索某些对象的原始输入:

    $("test"); // Returns a "pseudo-string"
    $("test").valueOf(); // Output: "test"
    

    由于valueOf 可能不安全,我们可以在方法列表中添加一个属性来获取原始输入:

    $ = function (_) {
      return Object.assign(_, ({
        type: function () { return toString.call(this).slice(8, -1) }, val: _
      });
    };
    

    现在使用val 将在没有函数调用的情况下返回原始输出:

    $("test").val // Output: "test"
    $(document.body).val // Output: <body>...</body>
    

    还不错,但也许有办法通过方法返回真正未修改的值?

    【讨论】:

    • 这是一个有趣的概念,但我不完全确定它的适用性。您将它们传入的值强制为原始类型的对象形式(通过 Object.assign),然后将属性添加到原始对象的该实例上。您的类型似乎没有改变,但事实并非如此。 Number(5) === 5 // true,然而$(5) === 5 // false。还有typeof 5 // "number"typeof $(5) // "object"。此外Number(5) === $(5) // false
    • @mhodges 回应您的澄清,我在答案中添加了更多内容。
    • 关于您在修改后的答案末尾添加的问题 - 这样做的方法是像 jQuery 一样简单地使用对象包装器。不幸的是,您必须使用访问器方法来获取原始值,但在内部,您可以利用闭包来访问原始的、未修改的值。您实际上也可以在这里通过说 toString.call(_).slice(8, -1) 而不是使用 this 上下文来做到这一点
    • 这是一个 basic example 复制您上面的功能。
    猜你喜欢
    • 1970-01-01
    • 2014-10-07
    • 1970-01-01
    • 2011-05-30
    • 2012-04-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多