Saat ini saya mengubah dari Jawa ke Javascript, dan agak sulit bagi saya untuk mengetahui cara memperluas objek dengan cara yang saya inginkan.
Saya telah melihat beberapa orang di internet menggunakan metode yang disebut extended on object. Kode akan terlihat seperti ini:
var Person = {
name : 'Blank',
age : 22
}
var Robot = Person.extend({
name : 'Robo',
age : 4
)}
var robot = new Robot();
alert(robot.name); //Should return 'Robo'
Adakah yang tahu cara membuat ini bekerja? Saya pernah mendengar bahwa Anda perlu menulis
Object.prototype.extend = function(...);
Tetapi saya tidak tahu bagaimana cara membuat sistem ini bekerja. Jika tidak memungkinkan, tolong tunjukkan saya alternatif lain yang memperluas objek.
extend
fungsi, saya telah membuat contoh di sini: jsfiddle.net/k9LRdJawaban:
Anda ingin 'mewarisi' dari objek prototipe Orang:
sumber
Person()
konstruktor dipanggil ketika Anda melakukannyanew Robot()
? Sepertinya saya bahwa Anda harus menelepon bahwa konstruktor kelas dasar bukannya melakukanthis.name = name;
diRobot()
konstruktor ...Person.apply(this, arguments);
. Ini juga akan lebih baik melakukan penggunaanRobot.prototype = Object.create(Person.prototype);
bukannew Person();
.Dunia tanpa kata kunci "baru".
Dan sintaksis "prosa-seperti" yang lebih sederhana dengan Object.create ().
* Contoh ini diperbarui untuk kelas ES6.
Pertama, ingatlah bahwa Javascript adalah bahasa prototipe . Ini bukan berbasis kelas. Oleh karena itu, menulis dalam bentuk prototipe memperlihatkan sifat aslinya, dan bisa sangat sederhana, seperti prosa, dan kuat.
TLDR;
Tidak, Anda tidak perlu konstruktor, tidak ada
new
Instansiasi ( baca mengapa Anda tidak boleh menggunakannew
), tidaksuper
, tidak lucu lucu__construct
. Anda cukup membuat Objek dan kemudian memperluas atau mengubah mereka.( Jika Anda tahu tentang getter dan setter, lihat bagian "Bacaan lebih lanjut" untuk melihat bagaimana pola ini memberi Anda getter dan setter gratis dengan cara yang awalnya dimaksudkan untuk Javascript , dan seberapa kuat mereka .)
Sintaks yang mirip prosa: Protoype dasar
Sekilas, terlihat sangat enak dibaca.
Extension, menciptakan keturunan
Person
* Istilah yang benar adalah
prototypes
, dan merekadescendants
. Tidak adaclasses
, dan tidak perluinstances
.Salah satu cara untuk menyediakan cara "default" untuk menciptakan
descendant
, adalah dengan melampirkan#create
metode:Cara di bawah ini memiliki keterbacaan yang lebih rendah:
Bandingkan dengan padanan "klasik":
Keterbacaan kode menggunakan gaya "klasik" tidak begitu bagus.
Kelas ES6
Memang, beberapa masalah ini diberantas oleh kelas ES6, tetapi masih:
Percabangan prototipe dasar
Lampirkan metode yang unik untuk
Robot
Memeriksa warisan
Anda sudah mendapatkan semua yang Anda butuhkan! Tidak ada konstruktor, tidak ada Instansiasi. Prosa bersih, jelas.
Bacaan lebih lanjut
Ketelitian, Dapat Dikonfigurasi, dan Gratis Setter dan Setter!
Untuk getter dan setter gratis, atau konfigurasi tambahan, Anda dapat menggunakan argumen kedua Object.create () alias propertiesObject. Ini juga tersedia di # Object.defineProperty , dan # Object.defineProperties .
Untuk mengilustrasikan betapa kuatnya ini, misalkan kita ingin semua
Robot
terbuat dari logam (viawritable: false
), dan menstandarkanpowerConsumption
nilai-nilai (via getter dan setter).Dan semua prototipe
Robot
tidak bisa menjadimadeOf
sesuatu yang lain karenawritable: false
.Mixins (menggunakan # Object.assign) - Anakin Skywalker
Bisakah Anda merasakan ke mana arahnya ...?
Darth Vader mendapatkan metode
Robot
:Bersama dengan hal-hal aneh lainnya:
Ya, apakah Darth Vader adalah manusia atau mesin memang subjektif:
Extra - Sintaks sedikit lebih pendek dengan # Object.assign
Kemungkinan besar, pola ini mempersingkat sintaksis Anda. Tetapi ES6 # Object.assign dapat mempersingkat lebih banyak (Untuk polyfill untuk digunakan pada browser lama, lihat MDN pada ES6 ).
sumber
Object.assign(Robot, {a:1}
adalah alternatif yang baik untukextend()
metode Anda ? 2) Bagaimana cara menggantigreet()
metode sehingga mengembalikan teks yang sama, tetapi dengan "override ucapan" ditambahkan?#Object.assign
memang terlihat seperti alternatif yang baik. Tetapi dukungan browser lebih rendah. 2) Anda akan menggunakan__proto__
properti objek untuk mengakses fungsi sambutan prototipe-nya. maka Anda memanggil fungsi sapaan prototipe dengan lingkup callee yang dimasukkan. dalam hal ini fungsinya adalah log konsol, jadi tidak mungkin untuk "menambahkan". Tetapi dengan contoh ini saya pikir Anda mengerti.skywalker.greet = function() { this.__proto__.greet.call(this); console.log('a greet override'); }
Jika Anda belum menemukan cara, gunakan properti asosiatif objek JavaScript untuk menambahkan fungsi perluasan ke
Object.prototype
seperti yang ditunjukkan di bawah ini.Anda kemudian dapat menggunakan fungsi ini seperti yang ditunjukkan di bawah ini.
sumber
Pendekatan berbeda: Object.create
Per @osahyoun menjawab, saya menemukan yang berikut ini sebagai cara yang lebih baik dan efisien untuk 'mewarisi' dari objek prototipe Person:
Buat instance baru:
Sekarang, dengan menggunakan Object.create :
Periksa juga dokumentasi MDN .
sumber
name
parameter ke konstruktor induk, seperti ini: jsfiddle.net/3brm0a7a/3 (perbedaan ada di baris # 8)Di ES6 , Anda dapat menggunakan spread operator like
Untuk info lebih lanjut, lihat tautan, Sintaksis Menyebar MDN
Jawaban lama:
Di ES6 , ada
Object.assign
untuk menyalin nilai properti. Gunakan{}
sebagai param pertama jika Anda tidak ingin memodifikasi objek target (param pertama berlalu).Untuk detail lebih lanjut lihat tautan, MDN - Object.assign ()
Jika Anda membutuhkan Polyfill untuk ES5 , tautannya juga menawarkannya. :)
sumber
Dan setahun kemudian, saya bisa memberi tahu Anda ada jawaban yang bagus.
Jika Anda tidak menyukai cara kerja prototipe untuk memperluas objek / kelas, perhatikan hal ini: https://github.com/haroldiedema/joii
Contoh kode kemungkinan cepat (dan banyak lagi):
sumber
Orang-orang yang masih berjuang untuk pendekatan sederhana dan terbaik, dapat Anda gunakan
Spread Syntax
untuk memperluas objek.Catatan: Ingatlah bahwa, properti yang paling jauh ke kanan akan mendapat prioritas. Dalam contoh ini,
person2
ada di sisi kanan, jadinewObj
akan ada nama Robo di dalamnya.sumber
Anda mungkin ingin mempertimbangkan untuk menggunakan perpustakaan pembantu seperti underscore.js , yang memiliki implementasi sendiri
extend()
.Dan ini juga cara yang bagus untuk belajar dengan melihat kode sumbernya. The kode sumber halaman dijelaskan cukup berguna.
sumber
_.extend()
membuat fungsinya cukup jelas: lostechies.com/chrismissal/2012/10/05/…Objek 'mengumumkan' Mozilla membentang dari ECMAScript 6.0:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes/extends
CATATAN: Ini adalah teknologi eksperimental, bagian dari proposal ECMAScript 6 (Harmony).
Teknologi ini tersedia di Gecko (Google Chrome / Firefox) - 03/2015 malam membangun.
sumber
Di sebagian besar proyek ada beberapa implementasi dari objek extending: garis bawah, jquery, lodash: memperpanjang .
Ada juga implementasi javascript murni, yang merupakan bagian dari ECMAscript 6: Object.assign : https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign
sumber
Kemudian:
Pembaruan 01/2017:
Tolong, Abaikan jawaban saya tahun 2015 karena Javascript sekarang mendukung
extends
kata kunci sejak ES6 (Ecmasctipt6)- ES6:
- ES7:
sumber
new ParentClass()
sebelum menimpa konstruktor, Anda sudah mengeksekusi konstruktor induk. Saya tidak berpikir itu perilaku yang benar jika Anda bertanya kepada saya ...Ringkasan:
Javascript menggunakan mekanisme yang disebut pewarisan prototypal . Warisan prototipe digunakan ketika mencari properti pada objek. Saat kami memperluas properti dalam javascript, kami mewarisi properti ini dari objek yang sebenarnya. Ini bekerja dengan cara berikut:
myObj.foo
ataumyObj['foo']
) mesin JS pertama-tama akan mencari properti itu pada objek itu sendiriKetika kita ingin memperluas dari suatu objek dalam javascript kita cukup menautkan objek ini dalam rantai prototipe. Ada banyak cara untuk mencapai ini, saya akan menjelaskan 2 metode yang umum digunakan.
Contoh:
1.
Object.create()
Object.create()
adalah fungsi yang mengambil objek sebagai argumen dan membuat objek baru. Objek yang dilewatkan sebagai argumen akan menjadi prototipe objek yang baru dibuat. Sebagai contoh:2. Secara eksplisit mengatur properti prototipe
Saat membuat objek menggunakan fungsi konstruktor, kita dapat mengatur properti tambah ke properti objek prototipe. Objek yang dibuat membentuk fungsi konstruktor saat menggunakan
new
kata kunci, mengatur prototipe ke prototipe fungsi konstruktor. Sebagai contoh:sumber
Anda cukup melakukannya dengan menggunakan:
Kemudian gunakan seperti:
Ini juga menghasilkan:
sumber
TOLONG TAMBAH ALASAN UNTUK DOWNVOTE
Tidak perlu menggunakan perpustakaan eksternal untuk memperluas
Dalam JavaScript, semuanya adalah objek (kecuali untuk tiga tipe data primitif, dan bahkan mereka secara otomatis dibungkus dengan objek saat diperlukan). Selanjutnya, semua objek bisa berubah.
terima kasih untuk kerusakan ross, dustin diaz
sumber
Ini akan membuat memperluas properti Anda membuat Objek baru dengan prototipe parameter objek tanpa mengubah objek yang dikirimkan.
Tetapi jika Anda ingin memperluas Objek Anda tanpa memodifikasi parameternya, Anda dapat menambahkan extendedProperty ke objek Anda.
sumber
Prototyping adalah cara yang baik, tetapi prototipe kadang-kadang cukup berbahaya dan dapat menyebabkan bug. Saya lebih suka merangkum ini menjadi objek dasar, seperti yang dilakukan Ember.js untuk itu Ember.Object.extend dan Ember.Object.reopen. Itu jauh lebih aman untuk digunakan.
Saya membuat inti dengan bagaimana Anda akan mengatur sesuatu yang mirip dengan apa yang digunakan Ember.Object.
Inilah tautannya: https://gist.github.com/WebCloud/cbfe2d848c80d4b9e9bd
sumber
Prototyping is a nice way, but prototype is quite dangerous sometimes and can lead to bugs.
Bagaimana apanya? Menggunakan rantai prototipe dalam JavaScript dapat menyebabkan bug? Ini seperti mengatakan bahwa menggunakan kelas di Java dapat menyebabkan bug dan sama sekali tidak masuk akal.Object
prototipe, fungsi Anda mungkin memiliki nama yang sama dengan fungsi JavaScript di masa depan dan menyebabkan kode Anda meledak saat dijalankan di masa depan. Misalnya, Anda menambahkanrepeat()
fungsi keObject
dan memanggilnya diString
instance dan kemudian runtime JavaScript Anda diperbarui ke ES6?prototype
fitur bahasa .