如何在 JavaScript 中创建可链接的函数?

IT技术 javascript function return chain chainable
2021-01-24 11:03:37

让我们想象一下这样的函数:

function foo(x) {
    x += '+';
    return x;
}

它的用法如下:

var x, y;
x = 'Notepad';
y = foo(x);
console.log(y); // Prints 'Notepad+'.

我正在寻找一种方法来创建可与其他函数链接的函数。

想象一下用法:

var x, y;
x = 'Notepad';
y = x.foo().foo().toUpperCase(); // Prints 'NOTEPAD++'.
console.log(y);

我该怎么做?

3个回答

当然,诀窍是在完成修改后返回对象:

String.prototype.foo = function() {
    return this + "+";
}

var str = "Notepad";
console.log(str.foo().foo().toUpperCase());

http://jsfiddle.net/Xeon06/vyFek/

为了使该方法在 上可用String,我正在修改它的原型。但是要小心不要这样做Object,因为它会在枚举它们的属性时导致问题。

在添加之前至少检查本地类型的属性是个好主意,即 if ( !('foo' in String.prototype) ) {String.prototype.foo = function() {...} }
2021-03-18 11:03:37
@keeganwatkins 是的:)。我假设 OP 只是以字符串为例,所以我将警告保持在最低限度,但这是一个很好的观点。
2021-04-02 11:03:37
如果您想在不破坏枚举的情况下扩展对象,请使用(半现代)Object.defineProperty: Object.defineProperty( String.prototype, {value:function(){ return this+"+"; } } )默认情况下,该enumerable标志设置为false.
2021-04-08 11:03:37
很好的解决方案,我的太通用了
2021-04-09 11:03:37
您不能this在字符串中赋值而是返回结果。如果您需要执行多个操作,请将其存储在一个临时变量中并返回。例如,var str = this; str += "foo"; return str;
2021-04-12 11:03:37

如果我没记错的话,您可以使用“this”作为函数(它所属的对象)的上下文并返回它以使函数可链接。换句话说:

var obj = 
{
    f1: function() { ...do something...; return this;},
    f2: function() { ...do something...; return this;}
}

然后你可以像这样链接调用 obj.f1().f2()

请记住,您将无法通过调用 obj.f1().toUpperCase() 来实现您的期望——它将执行 f1(),返回“this”并尝试调用 obj.toUpperCase()。

这是一种无需混淆 的方法String.prototype,通过返回一个类似于字符串的对象,并使用附加方法foo()但是,这种方法有一些缺点,即不返回实际字符​​串。

// Returns an object similar to a string, with an additional method foo()
function foo(str) {
  return Object.assign(`${str ?? this}+`, {
    foo
  });
}

var str = "Notepad";
console.log(
  "EXAMPLE - foo(str).foo().toUpperCase():",  
  foo(str).foo().toUpperCase()
);

console.log("---");

console.log("Some issues with this solution:");
console.log("typeof foo(str):", typeof foo(str));
console.log("foo(str).foo():", foo(str).foo());

console.log(
  "You may need to use toString() - foo(str).foo().toString():",
  foo(str).foo().toString()
);
.as-console-wrapper { min-height: 100% }