JavaScript'te "f" küçük harfli "new function ()"


106

Meslektaşım JavaScript'te yeni nesneleri tanımlamak için küçük harfle "f" olan "new function ()" kullanıyor. Tüm büyük tarayıcılarda iyi çalışıyor gibi görünüyor ve ayrıca özel değişkenleri gizlemede oldukça etkili görünüyor. İşte bir örnek:

    var someObj = new function () {
        var inner = 'some value';
        this.foo = 'blah';

        this.get_inner = function () {
            return inner;
        };

        this.set_inner = function (s) {
            inner = s;
        };
    };

"Bu" kullanılır kullanılmaz, someObj'nin kamu malı haline gelir. Yani someObj.foo, someObj.get_inner () ve someObj.set_inner () herkesin kullanımına açıktır. Ek olarak, set_inner () ve get_inner () ayrıcalıklı yöntemlerdir, bu nedenle kapatmalar yoluyla "iç" e erişime sahiptirler.

Ancak, hiçbir yerde bu tekniğe referans görmedim. Douglas Crockford'un JSLint'i bile bundan şikayet ediyor:

  • garip inşaat. "Yeni" yi sil

Bu tekniği üretimde kullanıyoruz ve iyi çalışıyor gibi görünüyor, ancak bu konuda biraz endişeliyim çünkü hiçbir yerde belgelenmedi. Bunun geçerli bir teknik olup olmadığını bilen var mı?


6
Yapınızı IIFE'ye ('Hemen Çağrılan İşlev') tercih ediyorum. 1: Açık bir 'örnek' nesnesine ihtiyacınız yok, JavaScript'teki 'bu' tam olarak budur. 2: Hiçbir şeyi iade etmenize gerek yok, yani hatırlamanıza gerek yok. Kabul edilen cevabın yazarı bile başlangıçta örnek nesnesini iade etmeyi unuttu! İnsanlar, yenisinden nefret ediyorlarsa genellikle IIFE kullanmayı tercih ederler ve bunun iyi bir nedeni vardır - Bir DOM olayını işleyen bir işleviniz varsa this, nesnenizi değil, olayı tetikleyen öğeye atıfta bulunacaktır, ancak var instance = thisbunun yerine sahip olabilirsiniz .
Lee Kowalkowski

1
Soru için "küçük f" harfini belirtmek neden önemlidir?
ClearCloud8

7
Çünkü Javascript'te farklı olan 'Function' fonksiyonu (büyük harfli F ile) vardır: Fonksiyon , yeni fonksiyon nesneleri yaratabilen bir yapıcı fonksiyondur, oysa fonksiyon bir anahtar kelimedir.
Stijn de Witt


@Bergi Bağlantılarınızı okudum. Bu kalıbı gözden düşürmek için bir neden göremiyorum. Bu geçerlidir. Basit. Yani ne yanlış. JSLint, BTW ile ilgili her şeyden şikayet ediyor :)
Stijn de Witt

Yanıtlar:


64

Bu tekniği daha önce görmüştüm, geçerli, bir Yapıcı Fonksiyonmuş gibi bir fonksiyon ifadesi kullanıyorsunuz .

Ama IMHO, aynı şeyi otomatik çağıran bir fonksiyon ifadesiyle de elde edebilirsiniz, newoperatörü bu şekilde kullanmanın anlamını gerçekten görmüyorum :

var someObj = (function () {
    var instance = {},
        inner = 'some value';

    instance.foo = 'blah';

    instance.get_inner = function () {
        return inner;
    };

    instance.set_inner = function (s) {
        inner = s;
    };

    return instance;
})();

newOperatörün amacı, yeni nesne örnekleri yaratmak, [[Prototype]]dahili özelliği kurmaktır, bunun [Construct]dahili özellik tarafından nasıl yapıldığını görebilirsiniz .

Yukarıdaki kod eşdeğer bir sonuç üretecektir.


1
Bölüm 13'teki ECMAScript 262 Spesifikasyonu bunu biraz daha resmi olarak açıklamaktadır. Benzer bir şey function foo () {}, bir Functionnesne yaratmanın sonucunu döndürür [muhtemelen new Function () ile]. Sözdizimi şekeri.
Clinton Pierce

3
Sanırım return instance;sonunda bir eksiksin. Aksi takdirde, someObjsadece olur undefined. :-)
Matthew Crumley

1
Modülerliği ve bilgi gizlemeyi önemsiyorsanız, bundan vazgeçip require.js gibi bir şey kullanmaya başlamanızı önerebilir miyim? Yolun yarısındasın, neden burada duruyorsun? Eşzamansız Modül Tanımı (gerekli ..js'nin uyguladığı) bu kullanımı destekler ve size kapsam belirleme, ad aralığı ve bağımlılık yönetimi ile başa çıkmak için eksiksiz bir araç seti sunar.
Stijn de Witt

Fonksiyon bildirimini çevreleyen parantezlerin gereksiz olduğuna dikkat edin, çünkü ifade zaten=
Explosion Pills

@StijndeWitt oranın yarısında, require.js'yi kullanmak için iki kez iş yapmanız gerektiği anlamına gelir, ancak basit durumlarda ihtiyacınız olan tek şey bu olabilir.
xr280xr

15

Kodunuz daha az tuhaf yapıya benziyor

function Foo () {
    var inner = 'some value';
    this.foo = 'blah';

    ...
};
var someObj = new Foo;

9
Sadece benzer değil, tamamen aynı şeyi yapıyor ... tek istisna, Foo'yu başka bir nesne yaratmak için tekrar kullanamayacaklar.
kikito

3
OP'nin sürümü yeni someObj.constructor aracılığıyla yeniden kullanılabilir . Burada kurucu, ad alanına açıkça eklenir; doğru stil, işlevin amaçlanan amacına bağlıdır. Ayrıca, bu tarz - gerçi kesinlikle standart - unutmak eğer birisi doldurmak genel ad sağlayan yeni önce Foo .
J Bryan Price

@kikito bunun Foo'nun başka bir nesne oluşturmak için yeniden kullanılmasına izin vermediğini ne demek istiyorsun? var newObj = new Foo () yeni bir örnek oluşturmalıdır.
Bill Yang

1
@BillYang Bu 5 yıl önceydi. Fikrim yok. O zamandan beri javascript'e dokunmadım.
kikito

12

Bazı yönleri açıklığa kavuşturmak ve Douglas Crockford'un JSLint'inin kodunuzdan şikayet etmemesini sağlamak için işte bazı örnekleme örnekleri:

1. o = new Object(); // normal call of a constructor

2. o = new Object;   // accepted call of a constructor

3. var someObj = new (function () {  
    var inner = 'some value';
    this.foo = 'blah';

    this.get_inner = function () {
        return inner;
    };

    this.set_inner = function (s) {
        inner = s;
    };
})(); // normal call of a constructor

4. var someObj = new (function () {  
    var inner = 'some value';
    this.foo = 'blah';

    this.get_inner = function () {
        return inner;
    };

    this.set_inner = function (s) {
        inner = s;
    };
}); // accepted call of a constructor

Örnek 3. (...) içindeki değer olarak ifade bir işlev / yapıcıdır. Şöyle görünür: new (function () {...}) (). Öyleyse, 2. örnekteki gibi bitiş parantezlerini atlarsak, ifade yine de geçerli bir yapıcı çağrısıdır ve 4. örnek gibi görünür.

Douglas Crockford'un JSLint'i, işlevi örneğine değil, someObj'ye atamak istediğinizi "düşünüyor". Ve sonuçta bu sadece bir uyarı, bir hata değil.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.