2012-01-07 10 views
20

JavaScript birinci sınıf fonksiyonlara sahip sözde, bu nedenle bu aşağıdaki gibi çalışmak gerektiğini gibi görünüyor:JavaScript'in birinci sınıf işlevleri varsa, neden bu işlevi değişken bir işte çağırmıyorsunuz?

var f = document.getElementById; 
var x = f('x'); 

Ama her birinde farklı bir şifreli hata mesajı ile, tüm tarayıcılarda başarısız olur. Safari “Type error” yazıyor. Chrome, “Yasa dışı işlem” diyor. Firefox “JavaScript argümanını dönüştüremedi” diyor.

Neden?

cevap

19

JavaScript işlevlerinde bağlamına bağlı olarak bağlanır (this). Sen bind() kullanabilirsiniz:

var f = document.getElementById.bind(document); 
+4

belgede 'Söz konusu yanıtı,' this' netleştirmek için:

function f(){ return document.getElementById(...arguments); }; 

Babel Bu veriyor .getElementById() '' document' iken, kapsamınızı yürütürken bu 'global', yani '' '' 'window' nesnesidir. –

36

Javascript'te obj.method() numaralı telefonu aradığınızda, yöntem obj olarak geçer. Bu nedenle document.getElementById('x') numaralı telefonu arayarak this değerini document olarak ayarlayın. Sadece f = document.getElementById yazarsanız

Ancak artık işleve yeni referansı var, ama bu referans artık document için "bağlı" dır.

Yani kodunuz çalışmaz, çünkü f'u çıplak işlev adı olarak çağırdığınızda, genel nesneye bağlı olarak sona erer (window). Fonksiyonun içgüdüleri this'u kullanmayı denediğinde, artık document yerine window olduğunu ve şaşırtıcı bir şekilde bunun hoşuna gitmediğini fark eder. Açıkça f çağırır fakat

var x = f.call(document, 'x'); 

document bağlam ayarlar:

Sen

bunu dersek f işi yapabilir.

var f = document.getElementById.bind(document); 

ve doğru olarak bağlamı ayarlar kendi sarıcı oluşturmak için gerçekten sadece bir genelleştirilmiş kestirme:

Bunu düzeltmek için başkalarının yolu ES5 yalnızca kullanılabilir Function.bind() kullanmaktır

3

ES6 en yayılma operatörü kullanarak, aynı zamanda deneyebilirsiniz:

function f() { 
    var _document; 
    return (_document = document).getElementById.apply(_document, arguments); 
}; 
İlgili konular