SORU
17 HAZİRAN 2009, ÇARŞAMBA


JavaScript fonksiyon't değil aliasing çalışmıyor gibi görünüyor

Sadece this question ve işlevi-sarıcı yöntemi yerine diğer yöntemi denemek istedim okuyordum, ama Firefox 3 ya da 3'te işe almak gibi olamaz.Test web sayfası hata ayıklama pencereleri ve 5beta4, veya Google Chrome.

Firebug:

>>> window.myAlias = document.getElementById
function()
>>> myAlias('item1')
>>> window.myAlias('item1')
>>> document.getElementById('item1')
<div id="item1">

Eğer bir web sayfasına baksaydınız, myAlias çağrısı bana bu hata veriyor:

uncaught exception: [Exception... "Illegal operation on WrappedNative prototype object" nsresult: "0x8057000c (NS_ERROR_XPC_BAD_OP_ON_WN_PROTO)" location: "JS frame :: file:///[...snip...]/test.html :: <TOP_LEVEL> :: line 7" data: no]

Chrome ( ^<< . 'açıklık getirmek için eklenen s):

>>> window.myAlias = document.getElementById
function getElementById() { [native code] }
>>> window.myAlias('item1')
TypeError: Illegal invocation
>>> document.getElementById('item1')
<div id=?"item1">?

Ve test sayfasında da "Yasadışı çağırma".

Yanlış bir şey mi yapıyorum? Herkesten bu yeniden?

Ayrıca, işin garibi, ben sadece denedim ve IE8 çalışır.

CEVAP
21 Temmuz 2009, Salı


Bu özel davranışı anlamak için derin kazılmış ve iyi bir açıklama buldum sanırım.

Ben document.getElementById diğer mümkün değil, neden oraya nasıl JavaScript/nesneleri işe anlatmaya çalışacağım.

Sen bir JavaScript işlevini çağırmak zaman, JavaScript yorumlayıcı bir kapsam belirler ve işlevine geçirir.

Fonksiyon düşünün

function sum(a, b)
{
    return a   b;
}

sum(10, 20); // returns 30;

Bu fonksiyon toplam fonksiyonu Window genel nesne olacak içinde this değerini çağırmak Pencere kapsamda bildirildi.

'' İşlevi, değeri ne olursa olsun önemli değil 'bu' bunu kullanarak değil gibi. sum için


Fonksiyon düşünün

function Person(birthDate)
{
    this.birthDate = birthDate;    
    this.getAge = function() { return new Date().getFullYear() - this.birthDate.getFullYear(); };
}

var dave = new Person(new Date(1909, 1, 1)); 
dave.getAge(); //returns 100.

Dave çağırdığınızda.getAge fonksiyonu, JavaScript yorumlayıcısı dave 30 *ayarlar* 32 *fonksiyonu çağırır dave nesne üzerinde getAge işlevi çağırmadan olduğunu görür. getAge() doğru 100 dönecektir.


JavaScript kapsam apply yöntemi kullanarak belirtebilirsiniz. Hadi bir deneyelim.

var dave = new Person(new Date(1909, 1, 1)); //Age 100 in 2009
var bob = new Person(new Date(1809, 1, 1)); //Age 200 in 2009

dave.getAge.apply(bob); //returns 200.

JavaScript kapsamında karar vermektense yukarıdaki satırı el ile kapsamı bob nesnesi olarak geçiyor. getAge şimdi 'düşünce' dave nesne getAge dedin. olsa bile 200 döndürecektir


Yukarıdaki tüm bunların anlamı ne? Fonksiyonları 'gevşek' JavaScript nesneleri bağlı. E. g. yapabilirsiniz

var dave = new Person(new Date(1909, 1, 1));
var bob = new Person(new Date(1809, 1, 1));

bob.getAge = function() { return -1; };

bob.getAge(); //returns -1
dave.getAge(); //returns 100

Bir sonraki adım atalım.

var dave = new Person(new Date(1909, 1, 1));
var ageMethod = dave.getAge;

dave.getAge(); //returns 100;
ageMethod(); //returns ?????

ageMethod yürütme bir hata atar! Ne oldu?

Eğer sen oku, ben yukarıdaki noktaları dikkatle, olur not dave.getAge yöntem çağrıldı dave this nesne ise JavaScript belirlenemedi 'kapsam' ageMethod yürütme. Küresel geçti '' 'bu'. gibi Pencere Şimdi window birthDate bir özelliği yok gibi, 51* *yürütme başarısız olur.

Bunu nasıl düzeltebilirim? Basit

ageMethod.apply(dave); //returns 100.

Yukarıdakilerin hepsi mantıklı mı? Eğer bunu yaparsa, o zaman diğer 53* *mümkün değil neden açıklamak mümkün olacak:

var $ = document.getElementById;

$('someElement'); 

$ this window olarak adlandırılır ve eğer getElementById uygulama this document, özür dilerim, eğer başarısız olur.

Tekrar bunu düzeltmek için yapabilirsiniz

$.apply(document, ['someElement']);

Neden Internet Explorer işliyor?

IE getElementById iç uygulaması bilmiyorum ama jQuery kaynak olarak bir açıklama (inArray yöntem uygulama) YANİ o, 64* *diyor. Eğer durum buysa, o zaman document.getElementById aliasing YANİ çalışmak gerekir.

Bu daha fazla göstermek için, ayrıntılı bir örnek oluşturdum. Person işlevi aşağıda bir göz atın.

function Person(birthDate)
{
    var self = this;

    this.birthDate = birthDate;

    this.getAge = function()
    {
        //Let's make sure that getAge method was invoked 
        //with an object which was constructed from our Person function.
        if(this.constructor == Person)
            return new Date().getFullYear() - this.birthDate.getFullYear();
        else
            return -1;
    };

    //Smarter version of getAge function, it will always refer to the object
    //it was created with.
    this.getAgeSmarter = function()
    {
        return self.getAge();
    };

    //Smartest version of getAge function.
    //It will try to use the most appropriate scope.
    this.getAgeSmartest = function()
    {
        var scope = this.constructor == Person ? this : self;
        return scope.getAge();
    };

}

Person yukarıdaki fonksiyonu için, burada getAge çeşitli yöntemler nasıl davranacağını.

Hadi iki nesne Person fonksiyon kullanarak oluşturun.

var yogi = new Person(new Date(1909, 1,1)); //Age is 100
var anotherYogi = new Person(new Date(1809, 1, 1)); //Age is 200

console.log(yogi.getAge()); //Output: 100.

Yalındır, getAge yöntemi this yogi nesne alır ve 100 çıktılar.


var ageAlias = yogi.getAge;
console.log(ageAlias()); //Output: -1

JavaScript interepreter this getAge yöntem -1 döner window nesne ayarlar.


console.log(ageAlias.apply(yogi)); //Output: 100

Eğer doğru kapsam kurarsak, ageAlias yöntemi kullanabilirsiniz.


console.log(ageAlias.apply(anotherYogi)); //Output: 200

Eğer başka bir kişi, nesne olarak görürsek, hala yaşı doğru olarak hesaplıyor.

var ageSmarterAlias = yogi.getAgeSmarter;    
console.log(ageSmarterAlias()); //Output: 100

ageSmarter işlevi artık doğru kapsam temin endişelenmenize gerek yok bu yüzden this orijinal nesneyi ele geçirdi.


console.log(ageSmarterAlias.apply(anotherYogi)); //Output: 100 !!!

ageSmarter ile sorun asla başka bir nesneye kapsam ayarlayabilirsiniz.


var ageSmartestAlias = yogi.getAgeSmartest;
console.log(ageSmartestAlias()); //Output: 100
console.log(ageSmartestAlias.apply(document)); //Output: 100

ageSmartest eğer işlevini geçersiz kapsamında sağlanan özgün kapsam kullanır.


console.log(ageSmartestAlias.apply(anotherYogi)); //Output: 200

Hala 93 ** Person başka bir nesne geçmek mümkün olacak. :)

Bunu Paylaş:
  • Google+
  • E-Posta
Etiketler:

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • Skrillex

    Skrillex

    6 NİSAN 2010
  • soyacincautv

    soyacincautv

    14 NİSAN 2010
  • wafflepwn

    wafflepwn

    14 AĞUSTOS 2008