Soru JavaScript'teki 'yeni' anahtar kelime nedir?


new JavaScript'in anahtar kelimesi, ilk karşılaşıldığında oldukça kafa karıştırıcı olabilir; çünkü insanlar, JavaScript'in nesne tabanlı bir programlama dili olmadığını düşünürler.

  • Bu ne?
  • Hangi problemleri çözer?
  • Ne zaman uygun ve uygun değil?

1559
2017-10-29 21:32


Menşei


Ayrıca, ilgili iş parçacığı - stackoverflow.com/questions/383402/... - Chetan Sastry


Cevaplar:


5 şey yapar:

  1. Yeni bir nesne oluşturur. Bu nesnenin türü basitçe nesne.
  2. Bu yeni nesnenin iç, erişilemezliğini ayarlar. [[prototip]] (Yani __proto__) constructor fonksiyonunun harici, erişilebilir olması, prototip nesne (her işlev nesnesinin otomatik olarak bir prototip mülkiyet).
  3. Yapar this Yeni oluşturulan nesneye değişken nokta.
  4. Her zaman yeni oluşturulan nesneyi kullanarak yapıcı işlevini yürütür this belirtilmiştir.
  5. Yeni oluşturulmuş nesneyi döndürür.null nesne başvurusu. Bu durumda, bu nesne başvurusu yerine döndürülür.

Not: yapıcı işlevi fonksiyonu sonra new anahtar kelime, içinde olduğu gibi

new ConstructorFunction(arg1, arg2)

Bu yapıldıktan sonra, yeni nesnenin tanımlanmamış bir özelliği istenirse, betik nesnenin kontrolünü yapar. [[prototip]] bunun yerine nesne için nesne. JavaScript'teki geleneksel sınıf kalıtımına benzer bir şey elde edebilirsiniz.

Bununla ilgili en zor kısım nokta 2'dir. Her nesne (işlevler dahil) bu dahili özelliğe sahiptir. [[prototip]]. Bu olabilir bir tek nesne oluşturma zamanında yeni, ile Object.createveya literal temeline dayanır (Function.prototype öğesinin varsayılan değerleri, Number.prototype, vb. sayıları). Sadece okunabilir Object.getPrototypeOf (someObject). Var yok hayır bu değeri ayarlamak veya okumak için başka bir yol.

Gizlilere ek olarak işlevler [[prototip]] mülkiyet, ayrıca bir özellik var prototipYaptığınız nesneler için kalıtsal özellikler ve yöntemler sağlamak için erişebileceğiniz ve değiştirebileceğiniz budur.


İşte bir örnek:

ObjMaker = function() {this.a = 'first';};
// ObjMaker is just a function, there's nothing special about it that makes 
// it a constructor.

ObjMaker.prototype.b = 'second';
// like all functions, ObjMaker has an accessible prototype property that 
// we can alter. I just added a property called 'b' to it. Like 
// all objects, ObjMaker also has an inaccessible [[prototype]] property
// that we can't do anything with

obj1 = new ObjMaker();
// 3 things just happened.
// A new, empty object was created called obj1.  At first obj1 was the same
// as {}. The [[prototype]] property of obj1 was then set to the current
// object value of the ObjMaker.prototype (if ObjMaker.prototype is later
// assigned a new object value, obj1's [[prototype]] will not change, but you
// can alter the properties of ObjMaker.prototype to add to both the
// prototype and [[prototype]]). The ObjMaker function was executed, with
// obj1 in place of this... so obj1.a was set to 'first'.

obj1.a;
// returns 'first'
obj1.b;
// obj1 doesn't have a property called 'b', so JavaScript checks 
// its [[prototype]]. Its [[prototype]] is the same as ObjMaker.prototype
// ObjMaker.prototype has a property called 'b' with value 'second'
// returns 'second'

Sınıf kalıtımına benziyor, çünkü şimdi, kullandığınız herhangi bir nesne new ObjMaker() Ayrıca 'b' özelliğini miras almış gibi görünecektir.

Bir alt sınıf gibi bir şey istiyorsanız, bunu yapın:

SubObjMaker = function () {};
SubObjMaker.prototype = new ObjMaker(); // note: this pattern is deprecated!
// Because we used 'new', the [[prototype]] property of SubObjMaker.prototype
// is now set to the object value of ObjMaker.prototype.
// The modern way to do this is with Object.create(), which was added in ECMAScript 5:
// SubObjMaker.prototype = Object.create(ObjMaker.prototype);

SubObjMaker.prototype.c = 'third';  
obj2 = new SubObjMaker();
// [[prototype]] property of obj2 is now set to SubObjMaker.prototype
// Remember that the [[prototype]] property of SubObjMaker.prototype
// is ObjMaker.prototype. So now obj2 has a prototype chain!
// obj2 ---> SubObjMaker.prototype ---> ObjMaker.prototype

obj2.c;
// returns 'third', from SubObjMaker.prototype

obj2.b;
// returns 'second', from ObjMaker.prototype

obj2.a;
// returns 'first', from SubObjMaker.prototype, because SubObjMaker.prototype 
// was created with the ObjMaker function, which assigned a for us

Sonunda bulmadan önce bu konuda bir ton çöp okudum bu sayfaBu güzel diyagramlarla çok iyi açıklandığı yerde.


1961
2017-10-29 22:22



Sadece eklemek istedim: Aslında dahili [[prototip]] 'e erişmek için __proto__ tarafından bir yol var. Ancak bu standart dışıdır ve yalnızca nispeten yeni tarayıcılar tarafından desteklenir (ve hepsi değil). Object.getPrototypeOf (obj) adı verilen standart bir yol var, ancak Ecmascript3.1, ve sadece yeni tarayıcılarda destekleniyor. Genelde bu özelliği kullanmamanız tavsiye edilir, ancak içeride çok hızlı karmaşık şeyler olur. - Blub
Soru: eğer farklıysa ne olur ObjMaker bir değer döndüren bir işlev olarak tanımlanır? - Jim Blackler
@LonelyPixel new var zorunda kalmamak için fonksiyonları / nesneleri oluşturmak / kopyalamak için fabrika yöntemlerini yazabilir. "Bunu kopyala, ebeveynin sınıfına benzet", "verimli ve doğru bir şekilde yap" ve "sadece bana, JS, dahili olarak erişilebilen miras bilgilerini sakla" anlamına gelir. Bunu yapmak için, aksi halde erişilemez dahili modunu değiştirir. prototype Yeni nesnenin, klasik OO devralma zincirlerini (çalışma zamanı değiştirilemez) taklit eden, devralınan üyeleri opak bir şekilde kapsüllemek. Bunu simüle etmeden yapabilirsiniz newama miras çalışma zamanı değiştirilebilir. İyi? Kötü? Sana bağlı. - Arcane Engineer
Eklenecek küçük bir nokta: Yeni bir anahtar kelimeyle önceliğe sahip olan bir yapıcıya yapılan çağrı, oluşturulan nesneyi otomatik olarak döndürür; kurucudan açıkça geri göndermeye gerek yoktur. - charlie roberts
Yazan bir not var Notice that this pattern is deprecated!. Bir sınıfın prototipini ayarlamak için doğru güncel model nedir? - Tom Pažourek


Bu işleve sahip olduğunuzu varsayalım:

var Foo = function(){
  this.A = 1;
  this.B = 2;
};

Bunu tek başına bir işlev olarak adlandırırsanız şöyle olur:

Foo();

Bu işlevi yürütmek, iki özellik ekler window nesne (A ve B). Bu ona ekler window Çünkü window Bunu böyle çalıştırdığınızda işlevi çağrılan nesne ve this Bir işlevde işlevi çağrılan nesnedir. En azından Javascript'te.

Şimdi buna benzer şekilde new:

var bar = new Foo();

Eklediğinizde ne olur? new Bir işlev çağrısı, yeni bir nesnenin oluşturulmasıdır (sadece var bar = new Object()) ve this fonksiyonun içinde yeni Object İşe yarayan nesneye değil, sadece yarattınız. Yani bar şimdi özellikleri olan bir nesne A ve B. Herhangi bir işlev bir kurucu olabilir, her zaman mantıklı değildir.


359
2018-06-20 23:46



Yürütme içeriğine bağlıdır. Benim durumumda (Qt betikleme) sadece küresel bir nesne. - Maxym
Bu daha fazla bellek kullanımına neden olur mu? - Jürgen Paul
çünkü pencere işlevi denen nesne - olmalıdır: çünkü pencere nesnedir içeren işlev. - Dávid Horváth
@Taurus Bir web tarayıcısında bir yöntem dışı işlev bir yöntem olacaktır window örtük. Bir kapanışta bile, anonymus olsa bile. Bununla birlikte, örnekte, pencerede basit bir yöntem çağrısıdır: Foo(); => [default context].Foo(); => window.Foo();. Bu ifadede window öyle mi bağlam (sadece arayan, önemli değil). - Dávid Horváth
@Taurus Temel olarak evet. Ancak ECMA 6 ve 7'de işler daha karmaşıktır (bkz. Lambdalar, sınıflar, vb.). - Dávid Horváth


Daniel Howard'ın cevabına ek olarak, işte burada new yapar (veya en azından öyle görünüyor):

function New(func) {
    var res = {};
    if (func.prototype !== null) {
        res.__proto__ = func.prototype;
    }
    var ret = func.apply(res, Array.prototype.slice.call(arguments, 1));
    if ((typeof ret === "object" || typeof ret === "function") && ret !== null) {
        return ret;
    }
    return res;
}

Süre

var obj = New(A, 1, 2);

eşdeğerdir

var obj = new A(1, 2);

146
2018-05-27 09:23



Javascript'in İngilizce'den daha kolay anlaşıldığını buldum: v - damphat
Mükemmel cevap. Küçük bir sorum var: Nasıl mümkün olabilir func.prototype olmak null? Biraz daha detaylandırır mısınız lütfen? - Tom Pažourek
Sadece yazarak prototip özelliğini geçersiz kılabilirsiniz. A.prototype = null; Bu durumda new A() nesne üzerinde sonuçlanacak, bu iç prototip noktaları Object nesne: jsfiddle.net/Mk42Z - basilikum
Bir ana makine nesnesi, "nesne" veya "işlev" den farklı bir şey üretebildiğinden, tür denetimi yanlış olabilir. Bir şey olup olmadığını test etmek için tercih ederim Object(ret) === ret. - Oriol
@Oriol Yorum için teşekkür ederim. Söylediğiniz ve gerçek bir testin daha sağlam bir şekilde yapılması gerektiği doğrudur. Ancak, bu kavramsal cevap için düşünüyorum typeof Test sadece sahnelerin ardında neler olduğunu anlamanızı kolaylaştırır. - basilikum


Yeni başlayanlar için daha iyi anlamak

tarayıcı konsolunda aşağıdaki kodu deneyin.

function Foo() { 
    return this; 
}

var a = Foo();       //returns window object
var b = new Foo();   //returns empty object of foo

a instanceof Window;  // true
a instanceof Foo;     // false

b instanceof Window;  // false
b instanceof Foo;     // true

Artık topluluk wiki cevabını okuyabilirsiniz :)


85
2017-10-29 21:34



İyi cevap. Ayrıca - bırakarak return this; aynı çıkışı verir. - Nelu
Bunun neden olduğuna dikkat etmek güzel olurdu. - Florian Leitgeb


bu yüzden muhtemelen yaratmak için değil   nesnenin örnekleri

Bunun için tam olarak kullanılıyor. Bir işlev kurucusunu şöyle tanımlarsınız:

function Person(name) {
    this.name = name;
}

var john = new Person('John');

Ancak ECMAScript'in sahip olduğu ekstra avantaj, .prototype özellik, öyle bir şey yapabiliriz ...

Person.prototype.getName = function() { return this.name; }

Bu kurucudan oluşturulan tüm nesneler artık bir getName erişim sahibi oldukları prototip zinciri nedeniyle.


33
2017-10-29 21:36



işlev yapıcılar sınıflar gibi kullanılır, yoktur class anahtar kelime ama aynı şeyi hemen hemen yapabilirsiniz. - meder omuraliev
Sınıf bir anahtar kelime var - sınıf gelecekteki kullanım için ayrılmıştır - Greg
Bu nedenle bir CSS sınıfını ayarlamak için .className .class kullanmamasının nedeni budur. - Greg
Sözleşmeye göre kapitalize edilmiş kişi olmalı. - eomeroff


JavaScript olduğu Nesneye yönelik bir programlama dili ve tam olarak örnek oluşturmak için kullanılır. Bu sınıf tabanlı değil, prototip tabanlı, ancak bu nesne odaklı olduğu anlamına gelmez.


26
2017-10-29 21:37



JavaScript'in tüm bu sınıf-temelli dillerden daha fazla nesne odaklı olduğunu söyleyebilirim. JavaScript'te yazdığınız her şey hemen bir nesne olur, ancak sınıf tabanlı dillerde ilk önce bildirimler yazarsınız ve ancak daha sonra sınıfların belirli örneklerini (nesneleri) yaratırsınız. Ve JavaScript prototipi, sınıf tabanlı diller için tüm bu VTABLE şeyler hatırlatacak gibi görünüyor. - JustAMartin


Javascript, nesne yönelimli programlama paradigmasını destekleyen ve yeni nesne örnekleri oluşturmak için kullanılan dinamik bir programlama dilidir.

Nesneler için sınıflar gerekli değildir - Javascript bir prototip tabanlı dil.


13
2018-05-16 07:21