javascript - this'i bağlamadan fonksiyon argümanları nasıl bağlanır?


Javascript'te, this parametresini bağlamadan bir fonksiyona argümanları nasıl bağlayabilirim?

Örneğin:

//Example function.
var c = function(a, b, c, callback) {};

//Bind values 1, 2, and 3 to a, b, and c, leave callback unbound.
var b = c.bind(null, 1, 2, 3); //How can I do this without binding scope?

Fonksiyonun kapsamını bağlamak zorunda kalma yan etkisinden (örneğin this=null olarak ayarlamak) nasıl kaçınabilirim?

Düzenle:

Karışıklık için özür dilerim. Argümanları bağlamak istiyorum, sonra bağlanmış fonksiyonu daha sonra çağırabilmek ve tıpkı orijinal fonksiyonu çağırıp ona bağlı argümanları vermişim gibi davranmasını sağlamak istiyorum:

var x = 'outside object';

var obj = {
  x: 'inside object',
  c: function(a, b, c, callback) {
    console.log(this.x);
  }
};

var b = obj.c.bind(null, 1, 2, 3);

//These should both have exact same output.
obj.c(1, 2, 3, function(){});
b(function(){});

//The following works, but I was hoping there was a better way:
var b = obj.c.bind(obj, 1, 2, 3); //Anyway to make it work without typing obj twice?

Bunda hâlâ yeniyim, karışıklık için özür dilerim.

Teşekkürler!

Cevap #1

Bunu yapabilirsiniz, ama en iyisi bunu 'bağlama' olarak düşünmekten kaçınmak çünkü bu terim 'this' değerinin ayarlanması için kullanılır. Belki bunu argümanları bir fonksiyonun içine 'sarmak' olarak düşünebilirsiniz?

Yapmanız gereken, istediğiniz argümanların kapanışlar aracılığıyla içine yerleştirildiği bir fonksiyon oluşturmaktır:

var withWrappedArguments = function(arg1, arg2)
    {
        return function() { ... do your stuff with arg1 and arg2 ... };
    }(actualArg1Value, actualArg2Value);

Umarım sözdizimini doğru yazmışımdır. Yaptığı şey, withWrappedArguments() adında bir fonksiyon oluşturmak (detaya girecek olursak, değişkene atanmış anonim bir fonksiyondur) ve bu fonksiyonu istediğiniz zaman, istediğiniz yerde çağırabilirsiniz; bu çağrı her zaman actualArg1Value ve actualArg2Value ile çalışır ve ayrıca içine eklemek istediğiniz başka şeyleri de alabilir. Ayrıca isterseniz, fonksiyon çağrılırken ek argümanlar da kabul etmesini sağlayabilirsiniz. Sırrı, son kapanış parantezinden sonraki parantezlerde yatıyor. Bu parantezler, dıştaki fonksiyonun hemen yürütülmesini, verilen değerlerle çalışmasını ve daha sonra çağrılabilecek iç fonksiyonu oluşturmasını sağlar. Fonksiyon oluşturulduğunda geçirilen değerler de sabitlenir.

Bu aslında bind'in yaptığı şeydir, ancak bu şekilde, sarılı argümanların sadece yerel değişkenler üzerinde kapanışlar olduğu açıkça belirtilir ve this'in davranışını değiştirmeye gerek yoktur.

Cevap #2

ES6'da, bu, yayılma operatörü ile birlikte kalan parametreler kullanılarak kolayca yapılır.

Bu nedenle, yalnızca argümanların bağlandığı, fakat bağlamın (this) bağlanmadığı bind gibi çalışan bir bindArgs fonksiyonu tanımlayabiliriz.

Function.prototype.bindArgs =
    function (...boundArgs)
    {
        const targetFunction = this;
        return function (...args) { return targetFunction.call(this, ...boundArgs, ...args); };
    };

Sonra, belirli bir foo fonksiyonu ve bir obj nesnesi için, ifade

return foo.call(obj, 1, 2, 3, 4);

eşdeğerdir

let bar = foo.bindArgs(1, 2);
return bar.call(obj, 3, 4);

sadece birinci ve ikinci argümanların bar'a bağlandığı, çağrıda belirtilen obj bağlamının kullanıldığı ve ekstra argümanların bağlı argümanların ardından eklendiği durumdur. Dönüş değeri basitçe iletilir.

Cevap #3

Yerel bind yönteminde sonuç fonksiyonundaki this değeri kaybolur. Ancak, yaygın shim'i bağlam için bir argüman kullanmayacak şekilde kolayca yeniden kodlayabilirsiniz:

Function.prototype.arg = function() {
    if (typeof this !== "function")
        throw new TypeError("Function.prototype.arg needs to be called on a function");
    var slice = Array.prototype.slice,
        args = slice.call(arguments), 
        fn = this, 
        partial = function() {
            return fn.apply(this, args.concat(slice.call(arguments)));
//                          ^^^^
        };
    partial.prototype = Object.create(this.prototype);
    return partial;
};

Cevap #4

var b = function() {
    return c(1,2,3);
};

İlgili makaleler