"Yeni" anahtar kelimesi olmayan dünya.
Ve Object.create () ile daha basit "düzyazı benzeri" sözdizimi.
* Bu örnek ES6 sınıfları için güncellenmiştir.
Öncelikle, Javascript'in prototip bir dil olduğunu unutmayın . Sınıf temelli değildir. Bu nedenle, prototip biçiminde yazmak gerçek doğasını ortaya çıkarır ve çok basit, nesir benzeri ve güçlü olabilir.
TLDR;
const Person = { name: 'Anonymous' } // person has a name
const jack = Object.create(Person) // jack is a person
jack.name = 'Jack' // and has a name 'Jack'
Hayır, kuruculara ihtiyacınız yok, new
somutlaşma yok ( neden kullanmamanız gerektiğini okuyunnew
), hayır super
, komik komik değil __construct
. Siz sadece Nesneleri yaratıp sonra genişletir ya da dönüştürürsünüz.
( Alıcıları ve ayarlayıcıları biliyorsanız, bu kalıbın size Javascript'in başlangıçta amaçladığı şekilde nasıl ücretsiz alıcılar ve ayarlayıcılar verdiğini ve ne kadar güçlü olduklarını görmek için "Daha fazla okuma" bölümüne bakın .)
Düzyazı benzeri sözdizimi: Temel protokol
const Person = {
//attributes
firstName : 'Anonymous',
lastName: 'Anonymous',
birthYear : 0,
type : 'human',
//methods
name() { return this.firstName + ' ' + this.lastName },
greet() {
console.log('Hi, my name is ' + this.name() + ' and I am a ' + this.type + '.' )
},
age() {
// age is a function of birth time.
}
}
const person = Object.create(Person). // that's it!
Bir bakışta, çok okunabilir görünüyor.
Uzantısı, Person
* Doğru şartlar prototypes
ve onların descendants
. Gerek yok classes
, gerek yok instances
.
const Skywalker = Object.create(Person)
Skywalker.lastName = 'Skywalker'
const anakin = Object.create(Skywalker)
anakin.firstName = 'Anakin'
anakin.birthYear = '442 BBY'
anakin.gender = 'male' // you can attach new properties.
anakin.greet() // 'Hi, my name is Anakin Skywalker and I am a human.'
Person.isPrototypeOf(Skywalker) // outputs true
Person.isPrototypeOf(anakin) // outputs true
Skywalker.isPrototypeOf(anakin) // outputs true
A oluşturmanın "varsayılan" bir yolunu sağlamanın bir yolu, descendant
bir #create
yöntem eklemektir :
Skywalker.create = function(firstName, gender, birthYear) {
let skywalker = Object.create(Skywalker)
Object.assign(skywalker, {
firstName,
birthYear,
gender,
lastName: 'Skywalker',
type: 'human'
})
return skywalker
}
const anakin = Skywalker.create('Anakin', 'male', '442 BBY')
Aşağıdaki yollar daha düşük okunabilirliğe sahiptir:
"Klasik" eşdeğeriyle karşılaştırın:
function Person (firstName, lastName, birthYear, type) {
this.firstName = firstName
this.lastName = lastName
this.birthYear = birthYear
this.type = type
}
// attaching methods
Person.prototype.name = function() { return firstName + ' ' + lastName }
Person.prototype.greet = function() { ... }
Person.prototype.age = function() { ... }
function Skywalker(firstName, birthYear) {
Person.apply(this, [firstName, 'Skywalker', birthYear, 'human'])
}
// confusing re-pointing...
Skywalker.prototype = Person.prototype
Skywalker.prototype.constructor = Skywalker
const anakin = new Skywalker('Anakin', '442 BBY')
Person.isPrototypeOf(anakin) // returns false!
Skywalker.isPrototypeOf(anakin) // returns false!
"Klasik" stil kullanılarak kod okunabilirliği iyi değildir.
ES6 Sınıfları
Kuşkusuz, bu sorunların bazıları ES6 sınıfları tarafından ortadan kaldırılıyor, ancak yine de:
class Person {
constructor(firstName, lastName, birthYear, type) {
this.firstName = firstName
this.lastName = lastName
this.birthYear = birthYear
this.type = type
}
name() { return this.firstName + ' ' + this.lastName }
greet() { console.log('Hi, my name is ' + this.name() + ' and I am a ' + this.type + '.' ) }
}
class Skywalker extends Person {
constructor(firstName, birthYear) {
super(firstName, 'Skywalker', birthYear, 'human')
}
}
const anakin = new Skywalker('Anakin', '442 BBY')
// prototype chain inheritance checking is partially fixed.
Person.isPrototypeOf(anakin) // returns false!
Skywalker.isPrototypeOf(anakin) // returns true
Temel prototipin dallanması
// create a `Robot` prototype by extending the `Person` prototype:
const Robot = Object.create(Person)
Robot.type = 'robot'
Robot.variant = '' // add properties for Robot prototype
İçin benzersiz yöntemler ekleyin Robot
// Robots speak in binaries, so we need a different greet function:
Robot.machineGreet = function() { /*some function to convert strings to binary */ }
// morphing the `Robot` object doesn't affect `Person` prototypes
anakin.greet() // 'Hi, my name is Anakin Skywalker and I am a human.'
anakin.machineGreet() // error
Miras kontrolü
Person.isPrototypeOf(Robot) // outputs true
Robot.isPrototypeOf(Skywalker) // outputs false
Zaten ihtiyacınız olan her şeye sahipsiniz! Yapıcı yok, örnekleme yok. Temiz, açık nesir.
daha fazla okuma
Yazılabilirlik, Yapılandırılabilirlik ve Serbest Mektuplar ve Ayarlayıcılar!
Ücretsiz alıcılar ve ayarlayıcılar veya ekstra yapılandırma için Object.create () öğesinin ikinci argümanını aka özellikObject kullanabilirsiniz. Ayrıca # Object.defineProperty ve # Object.defineProperties dosyalarında da mevcuttur .
Bunun ne kadar güçlü olduğunu göstermek için, hepimizin Robot
kesinlikle metalden (aracılığıyla writable: false
) yapılmasını istediğimizi ve powerConsumption
değerleri (alıcılar ve ayarlayıcılar aracılığıyla ) standartlaştırdığımızı varsayalım .
const Robot = Object.create(Person, {
// define your property attributes
madeOf: {
value: "metal",
writable: false,
configurable: false,
enumerable: true
},
// getters and setters, how javascript had (naturally) intended.
powerConsumption: {
get() { return this._powerConsumption },
set(value) {
if (value.indexOf('MWh')) return this._powerConsumption = value.replace('M', ',000k')
this._powerConsumption = value
throw new Error('Power consumption format not recognised.')
}
}
})
const newRobot = Object.create(Robot)
newRobot.powerConsumption = '5MWh'
console.log(newRobot.powerConsumption) // outputs 5,000kWh
Ve tüm prototipleri başka bir şey Robot
olamaz madeOf
çünkü writable: false
.
const polymerRobot = Object.create(Robot)
polymerRobot.madeOf = 'polymer'
console.log(polymerRobot.madeOf) // outputs 'metal'
Mixins (# Object.assign kullanarak) - Anakin Skywalker
Bunun nereye gittiğini hissedebiliyor musun ...?
const darthVader = Object.create(anakin)
// for brevity, property assignments are skipped because you get the point by now.
Object.assign(darthVader, Robot)
Darth Vader şu yöntemleri alır Robot
:
darthVader.greet() // inherited from `Person`, outputs "Hi, my name is Darth Vader..."
darthVader.machineGreet() // inherited from `Robot`, outputs 001010011010...
Diğer garip şeylerle birlikte:
console.log(darthVader.type) // outputs robot.
Robot.isPrototypeOf(darthVader) // returns false.
Person.isPrototypeOf(darthVader) // returns true.
Darth Vader'ın insan mı yoksa makine mi olduğu gerçekten özneldir:
"O şimdi insandan daha fazla makine, bükülmüş ve kötü." - Obi-Wan Kenobi
"İçinde iyi olduğunu biliyorum." - Luke Skywalker
Ekstra - # Object.assign ile biraz daha kısa sözdizimi
Büyük olasılıkla, bu model sözdizimini kısaltır. Ancak ES6 # Object.assign biraz daha kısaltabilir ( Çoklu dolgunun eski tarayıcılarda kullanılması için ES6'da MDN'ye bakın ).
//instead of this
const Robot = Object.create(Person)
Robot.name = "Robot"
Robot.madeOf = "metal"
//you can do this
const Robot = Object.create(Person)
Object.assign(Robot, {
name: "Robot",
madeOf: "metal"
// for brevity, you can imagine a long list will save more code.
})