Bisakah kelas / objek JavaScript memiliki konstruktor? Bagaimana mereka diciptakan?
Bisakah kelas / objek JavaScript memiliki konstruktor? Bagaimana mereka diciptakan?
Jawaban:
Menggunakan prototipe:
function Box(color) // Constructor
{
this.color = color;
}
Box.prototype.getColor = function()
{
return this.color;
};
Menyembunyikan "warna" (agak menyerupai variabel anggota pribadi):
function Box(col)
{
var color = col;
this.getColor = function()
{
return color;
};
}
Pemakaian:
var blueBox = new Box("blue");
alert(blueBox.getColor()); // will alert blue
var greenBox = new Box("green");
alert(greenBox.getColor()); // will alert green
color
. Saya sarankan yang Anda gunakan sebagian besar ke preferensi pribadi (perlindungan vs kesederhanaan)
var
membuat variabel pribadi. this
membuat variabel publik
Foo
, sedangkan dalam kasus terakhir ia akan tahu bahwa itu Foo
dipanggil. Sangat membantu untuk debugging.
Inilah templat yang terkadang saya gunakan untuk perilaku serupa OOP di JavaScript. Seperti yang Anda lihat, Anda dapat mensimulasikan anggota pribadi (baik statis maupun instan) menggunakan penutupan. Apa yang new MyClass()
akan kembali adalah objek dengan hanya properti yang ditetapkan ke this
objek dan di prototype
objek "kelas."
var MyClass = (function () {
// private static
var nextId = 1;
// constructor
var cls = function () {
// private
var id = nextId++;
var name = 'Unknown';
// public (this instance only)
this.get_id = function () { return id; };
this.get_name = function () { return name; };
this.set_name = function (value) {
if (typeof value != 'string')
throw 'Name must be a string';
if (value.length < 2 || value.length > 20)
throw 'Name must be 2-20 characters long.';
name = value;
};
};
// public static
cls.get_nextId = function () {
return nextId;
};
// public (shared across instances)
cls.prototype = {
announce: function () {
alert('Hi there! My id is ' + this.get_id() + ' and my name is "' + this.get_name() + '"!\r\n' +
'The next fellow\'s id will be ' + MyClass.get_nextId() + '!');
}
};
return cls;
})();
Saya telah ditanya tentang pewarisan menggunakan pola ini, jadi begini:
// It's a good idea to have a utility class to wire up inheritance.
function inherit(cls, superCls) {
// We use an intermediary empty constructor to create an
// inheritance chain, because using the super class' constructor
// might have side effects.
var construct = function () {};
construct.prototype = superCls.prototype;
cls.prototype = new construct;
cls.prototype.constructor = cls;
cls.super = superCls;
}
var MyChildClass = (function () {
// constructor
var cls = function (surName) {
// Call super constructor on this instance (any arguments
// to the constructor would go after "this" in call(…)).
this.constructor.super.call(this);
// Shadowing instance properties is a little bit less
// intuitive, but can be done:
var getName = this.get_name;
// public (this instance only)
this.get_name = function () {
return getName.call(this) + ' ' + surName;
};
};
inherit(cls, MyClass); // <-- important!
return cls;
})();
Dan contoh untuk menggunakan semuanya:
var bob = new MyClass();
bob.set_name('Bob');
bob.announce(); // id is 1, name shows as "Bob"
var john = new MyChildClass('Doe');
john.set_name('John');
john.announce(); // id is 2, name shows as "John Doe"
alert(john instanceof MyClass); // true
Seperti yang Anda lihat, kelas-kelas saling berinteraksi dengan benar (mereka berbagi id statis dari MyClass
, announce
metode menggunakan metode yang benar get_name
, dll.)
Satu hal yang perlu diperhatikan adalah perlunya membayangi properti instance. Anda benar-benar dapat membuat inherit
fungsi melalui semua properti instance (menggunakan hasOwnProperty
) yang merupakan fungsi, dan secara otomatis menambahkan super_<method name>
properti. Ini akan memungkinkan Anda memanggil this.super_get_name()
alih-alih menyimpannya dalam nilai sementara dan menyebutnya terikat menggunakan call
.
Untuk metode pada prototipe Anda tidak perlu khawatir tentang hal di atas, jika Anda ingin mengakses metode prototipe kelas super, Anda bisa menelepon this.constructor.super.prototype.methodName
. Jika Anda ingin membuatnya kurang verbose Anda tentu saja dapat menambahkan properti kenyamanan. :)
cls.prototype
bagian: "dibagikan di seluruh instance" hanya untuk membaca nilai (panggilan announce
). Jika Anda menetapkan myClassInstance.announce
ke nilai lain, itu membuat properti baru di myClassInstance
, jadi itu hanya berlaku untuk objek itu, bukan contoh lain dari kelas. Menugaskan untuk MyClass.prototype.announce
akan mempengaruhi semua instance.
MyClass.get_nextId()
Menurut saya sebagian besar dari Anda memberikan contoh getter dan setter bukan konstruktor, yaitu http://en.wikipedia.org/wiki/Constructor_(object-oriented_programming) .
makan siang-dan lebih dekat tetapi contohnya tidak bekerja di jsFiddle.
Contoh ini membuat fungsi konstruktor pribadi yang hanya berjalan selama pembuatan objek.
var color = 'black';
function Box()
{
// private property
var color = '';
// private constructor
var __construct = function() {
alert("Object Created.");
color = 'green';
}()
// getter
this.getColor = function() {
return color;
}
// setter
this.setColor = function(data) {
color = data;
}
}
var b = new Box();
alert(b.getColor()); // should be green
b.setColor('orange');
alert(b.getColor()); // should be orange
alert(color); // should be black
Jika Anda ingin menetapkan properti publik maka konstruktor dapat didefinisikan sebagai berikut:
var color = 'black';
function Box()
{
// public property
this.color = '';
// private constructor
var __construct = function(that) {
alert("Object Created.");
that.color = 'green';
}(this)
// getter
this.getColor = function() {
return this.color;
}
// setter
this.setColor = function(color) {
this.color = color;
}
}
var b = new Box();
alert(b.getColor()); // should be green
b.setColor('orange');
alert(b.getColor()); // should be orange
alert(color); // should be black
Box()
berfungsi :). Tetapi contoh ini serta contoh dalam jawaban lain dapat dengan mudah diperluas untuk menerima parameter.
Box
fungsi dan Anda baik untuk pergi (itu masih "pribadi"). "Pribadi" dalam Javascript berarti dapat diakses melalui ruang lingkup leksikal; tidak perlu menugaskan anggota. Selain itu: kode ini salah. Ini menciptakan __construct
variabel global , yang sangat buruk. var
harus digunakan untuk membatasi ruang lingkup __construct
.
Jadi apa gunanya properti "konstruktor"? Tidak tahu di mana itu bisa berguna, ada ide?
Inti dari properti konstruktor adalah untuk menyediakan beberapa cara berpura-pura JavaScript memiliki kelas. Salah satu hal yang tidak bisa Anda lakukan adalah mengubah konstruktor objek setelah objek dibuat. Ini rumit.
Saya menulis karya yang cukup komprehensif beberapa tahun yang lalu: http://joost.zeekat.nl/constructors-considered-mildly-confusing.html
Contoh di sini: http://jsfiddle.net/FZ5nC/
Coba templat ini:
<script>
//============================================================
// Register Namespace
//------------------------------------------------------------
var Name = Name||{};
Name.Space = Name.Space||{};
//============================================================
// Constructor - MUST BE AT TOP OF FILE
//------------------------------------------------------------
Name.Space.ClassName = function Name_Space_ClassName(){}
//============================================================
// Member Functions & Variables
//------------------------------------------------------------
Name.Space.ClassName.prototype = {
v1: null
,v2: null
,f1: function Name_Space_ClassName_f1(){}
}
//============================================================
// Static Variables
//------------------------------------------------------------
Name.Space.ClassName.staticVar = 0;
//============================================================
// Static Functions
//------------------------------------------------------------
Name.Space.ClassName.staticFunc = function Name_Space_ClassName_staticFunc(){
}
</script>
Anda harus menyesuaikan namespace Anda jika Anda mendefinisikan kelas statis:
<script>
//============================================================
// Register Namespace
//------------------------------------------------------------
var Shape = Shape||{};
Shape.Rectangle = Shape.Rectangle||{};
// In previous example, Rectangle was defined in the constructor.
</script>
Kelas contoh:
<script>
//============================================================
// Register Namespace
//------------------------------------------------------------
var Shape = Shape||{};
//============================================================
// Constructor - MUST BE AT TOP OF FILE
//------------------------------------------------------------
Shape.Rectangle = function Shape_Rectangle(width, height, color){
this.Width = width;
this.Height = height;
this.Color = color;
}
//============================================================
// Member Functions & Variables
//------------------------------------------------------------
Shape.Rectangle.prototype = {
Width: null
,Height: null
,Color: null
,Draw: function Shape_Rectangle_Draw(canvasId, x, y){
var canvas = document.getElementById(canvasId);
var context = canvas.getContext("2d");
context.fillStyle = this.Color;
context.fillRect(x, y, this.Width, this.Height);
}
}
//============================================================
// Static Variables
//------------------------------------------------------------
Shape.Rectangle.Sides = 4;
//============================================================
// Static Functions
//------------------------------------------------------------
Shape.Rectangle.CreateSmallBlue = function Shape_Rectangle_CreateSmallBlue(){
return new Shape.Rectangle(5,8,'#0000ff');
}
Shape.Rectangle.CreateBigRed = function Shape_Rectangle_CreateBigRed(){
return new Shape.Rectangle(50,25,'#ff0000');
}
</script>
Instansiasi contoh:
<canvas id="painting" width="500" height="500"></canvas>
<script>
alert("A rectangle has "+Shape.Rectangle.Sides+" sides.");
var r1 = new Shape.Rectangle(16, 12, "#aa22cc");
r1.Draw("painting",0, 20);
var r2 = Shape.Rectangle.CreateSmallBlue();
r2.Draw("painting", 0, 0);
Shape.Rectangle.CreateBigRed().Draw("painting", 10, 0);
</script>
Fungsi pemberitahuan didefinisikan sebagai AB = fungsi A_B (). Ini untuk membuat skrip Anda lebih mudah di-debug. Buka panel Elemen Inspeksi Chrome, jalankan skrip ini, dan perluas kembali jejak debug:
<script>
//============================================================
// Register Namespace
//------------------------------------------------------------
var Fail = Fail||{};
//============================================================
// Static Functions
//------------------------------------------------------------
Fail.Test = function Fail_Test(){
A.Func.That.Does.Not.Exist();
}
Fail.Test();
</script>
Ini adalah konstruktor:
function MyClass() {}
Saat kamu melakukan
var myObj = new MyClass();
MyClass
dieksekusi, dan objek baru dikembalikan dari kelas itu.
alert(valuePassedInAsArgument);
dan ini akan berjalan sekali untuk setiap instance, sehingga seluruh kelas adalah konstruktor itu sendiri.
new object is returned of that class
- Bukankah lebih seperti objek baru yang dikembalikan dari fungsi itu?
Saya menemukan tutorial ini sangat berguna. Pendekatan ini digunakan oleh sebagian besar plug-in jQuery.
var Class = function(methods) {
var klass = function() {
this.initialize.apply(this, arguments);
};
for (var property in methods) {
klass.prototype[property] = methods[property];
}
if (!klass.prototype.initialize) klass.prototype.initialize = function(){};
return klass;
};
Sekarang ,
var Person = Class({
initialize: function(name, age) {
this.name = name;
this.age = age;
},
toString: function() {
return "My name is "+this.name+" and I am "+this.age+" years old.";
}
});
var alice = new Person('Alice', 26);
alert(alice.name); //displays "Alice"
alert(alice.age); //displays "26"
alert(alice.toString()); //displays "My name is Alice and I am 26 years old" in most browsers.
//IE 8 and below display the Object's toString() instead! "[Object object]"
klass
Pola ini sangat membantu saya. Dengan pola ini, Anda membuat kelas dalam file terpisah, memuatnya ke dalam aplikasi keseluruhan "sesuai kebutuhan".
// Namespace
// (Creating new if not instantiated yet, otherwise, use existing and just add to it)
var myApp = myApp || {};
// "Package"
// Similar to how you would establish a package in other languages
(function() {
// "Class"
var MyClass = function(params) {
this.initialize(params);
}
// "Private Static" vars
// - Only accessible to functions in this class.
// - Doesn't get wiped out when we create a new instance.
var countInstances = 0;
var allInstances = [];
// "Private Static" functions
// - Same as above, but it's a function accessible
// only to other functions in this class.
function doSomething(){
}
// "Public Static" vars
// - Everyone has access.
// - Doesn't get wiped out when we create a new instance.
MyClass.counter = 0;
// "Public Static" functions
// - Same as above, but anyone can call this "static method".
// - Kinda like a singleton class situation.
MyClass.foobar = function(){
}
// Public properties and methods are built into the "prototype"
// - This is how each instance can become unique unto itself.
// - Establishing "p" as "local" (Static Private) variable
// simply so we don't have to keep typing "MyClass.prototype"
// for each property and function.
var p = MyClass.prototype;
// "Public" vars
p.id = null;
p.firstname = null;
p.lastname = null;
// "Private" vars
// - Only used by "this" instance.
// - There isn't "true" privacy for each
// instance so we have to fake it.
// - By tradition, we indicate "privacy"
// by prefixing it with an underscore.
// - So technically, anyone can access, but we simply
// don't tell anyone about it (e.g. in your API)
// so no one knows about it :)
p._foo = null;
p.initialize = function(params){
this.id = MyClass.counter++;
this.firstname = params.firstname;
this.lastname = params.lastname;
MyClass.counter++;
countInstances++;
allInstances.push(this);
}
p.doAlert = function(theMessage){
alert(this.firstname + " " + this.lastname + " said: " + theMessage + ". My id:" + this.id + ". Total People:" + countInstances + ". First Person:" + allInstances[0].firstname + " " + allInstances[0].lastname);
}
// Assign class to app
myApp.MyClass = MyClass;
// Close the "Package"
}());
// Usage example:
var bob = new myApp.MyClass({ firstname : "bob",
lastname : "er"
});
bob.doAlert("hello there");
var
di konstruktor (atau argumen fungsi, atau dalam fungsi seperti konstruktor).
Ya, Anda bisa mendefinisikan konstruktor di dalam deklarasi kelas seperti ini:
class Rectangle {
constructor(height, width) {
this.height = height;
this.width = width;
}
}
Saya kira saya akan memposting apa yang saya lakukan dengan penutupan javascript karena belum ada yang menggunakan penutupan.
var user = function(id) {
// private properties & methods goes here.
var someValue;
function doSomething(data) {
someValue = data;
};
// constructor goes here.
if (!id) return null;
// public properties & methods goes here.
return {
id: id,
method: function(params) {
doSomething(params);
}
};
};
Terima kasih dan saran untuk solusi ini. :)
Menggunakan sampel Nick di atas, Anda dapat membuat konstruktor untuk objek tanpa parameter menggunakan pernyataan kembali sebagai pernyataan terakhir dalam definisi objek Anda. Kembalikan fungsi konstruktor Anda seperti di bawah ini dan itu akan menjalankan kode dalam __construct setiap kali Anda membuat objek:
function Box()
{
var __construct = function() {
alert("Object Created.");
this.color = 'green';
}
this.color = '';
this.getColor = function() {
return this.color;
}
__construct();
}
var b = new Box();
this.getColor();
pada baris di atas alert("Object Created.");
tidak ada yang akan diperingatkan. Akan ada kesalahan seperti "getColor tidak didefinisikan". Jika Anda ingin konstruk dapat memanggil metode lain di objek itu perlu didefinisikan setelah semua metode lain. Jadi alih-alih memanggil __construct();
baris terakhir, tentukan konstruk di sana dan letakkan ()
setelahnya untuk memaksanya mengeksekusi otomatis.
()
ke akhir definisi konstruksi __ masih menghasilkan kesalahan. Saya harus menelepon __construct();
sendiri seperti pada kode asli untuk menghindari kesalahan.
Mungkin sedikit lebih sederhana, tapi di bawah ini yang saya buat sekarang di 2017:
class obj {
constructor(in_shape, in_color){
this.shape = in_shape;
this.color = in_color;
}
getInfo(){
return this.shape + ' and ' + this.color;
}
setShape(in_shape){
this.shape = in_shape;
}
setColor(in_color){
this.color = in_color;
}
}
Dalam menggunakan kelas di atas, saya memiliki yang berikut:
var newobj = new obj('square', 'blue');
//Here, we expect to see 'square and blue'
console.log(newobj.getInfo());
newobj.setColor('white');
newobj.setShape('sphere');
//Since we've set new color and shape, we expect the following: 'sphere and white'
console.log(newobj.getInfo());
Seperti yang Anda lihat, konstruktor mengambil dua parameter, dan kami mengatur properti objek. Kami juga mengubah warna dan bentuk objek dengan menggunakan setter
fungsi, dan membuktikan bahwa perubahannya tetap setelah memanggil getInfo()
setelah perubahan ini.
Agak terlambat, tapi saya harap ini membantu. Saya sudah menguji ini dengan mocha
unit-testing, dan itu bekerja dengan baik.
Mereka melakukannya jika Anda menggunakan TypeScript - open source dari MicroSoft :-)
class BankAccount {
balance: number;
constructor(initially: number) {
this.balance = initially;
}
deposit(credit: number) {
this.balance += credit;
return this.balance;
}
}
Teks skrip memungkinkan Anda 'memalsukan' konstruksi OO yang dikompilasi menjadi konstruksi javascript. Jika Anda memulai proyek besar itu mungkin menghemat banyak waktu dan hanya mencapai tonggak versi 1.0.
http://www.typescriptlang.org/Content/TypeScript%20Language%20Specification.pdf
Kode di atas 'dikompilasi' ke:
var BankAccount = (function () {
function BankAccount(initially) {
this.balance = initially;
}
BankAccount.prototype.deposit = function (credit) {
this.balance += credit;
return this.balance;
};
return BankAccount;
})();
Dalam JavaScript, jenis doa mendefinisikan perilaku fungsi:
func()
obj.func()
new func()
func.call()
ataufunc.apply()
Fungsi dipanggil sebagai konstruktor saat memanggil menggunakan new
operator:
function Cat(name) {
this.name = name;
}
Cat.prototype.getName = function() {
return this.name;
}
var myCat = new Cat('Sweet'); // Cat function invoked as a constructor
Setiap instance atau objek prototipe dalam JavaScript memiliki properti constructor
, yang merujuk pada fungsi konstruktor.
Cat.prototype.constructor === Cat // => true
myCat.constructor === Cat // => true
Periksa posting ini tentang properti konstruktor.
Saat menggunakan template Blixt yang hebat dari atas, saya menemukan bahwa itu tidak bekerja dengan baik dengan multi-level inheritance (MyGrandChildClass memperluas MyChildClass memperluas MyClass) - itu siklus memanggil konstruktor orang tua pertama berulang kali. Jadi di sini adalah solusi sederhana - jika Anda perlu warisan multi-level, daripada menggunakan this.constructor.super.call(this, surName);
penggunaan chainSuper(this).call(this, surName);
dengan fungsi rantai didefinisikan seperti ini:
function chainSuper(cls) {
if (cls.__depth == undefined) cls.__depth = 1; else cls.__depth++;
var depth = cls.__depth;
var sup = cls.constructor.super;
while (depth > 1) {
if (sup.super != undefined) sup = sup.super;
depth--;
}
return sup;
}
http://www.jsoops.net/ cukup bagus untuk oo di Js. Jika menyediakan privat, terlindungi, variabel dan fungsi publik, dan juga fitur Warisan. Kode Contoh:
var ClassA = JsOops(function (pri, pro, pub)
{// pri = private, pro = protected, pub = public
pri.className = "I am A ";
this.init = function (var1)// constructor
{
pri.className += var1;
}
pub.getData = function ()
{
return "ClassA(Top=" + pro.getClassName() + ", This=" + pri.getClassName()
+ ", ID=" + pro.getClassId() + ")";
}
pri.getClassName = function () { return pri.className; }
pro.getClassName = function () { return pri.className; }
pro.getClassId = function () { return 1; }
});
var newA = new ClassA("Class");
//***Access public function
console.log(typeof (newA.getData));
// function
console.log(newA.getData());
// ClassA(Top=I am A Class, This=I am A Class, ID=1)
//***You can not access constructor, private and protected function
console.log(typeof (newA.init)); // undefined
console.log(typeof (newA.className)); // undefined
console.log(typeof (newA.pro)); // undefined
console.log(typeof (newA.getClassName)); // undefined
hanya untuk menawarkan beberapa variasi. ds.oop adalah cara yang bagus untuk mendeklarasikan kelas dengan konstruktor dalam javascript. Ini mendukung setiap jenis warisan yang mungkin (Termasuk 1 jenis yang bahkan c # tidak mendukung) serta Antarmuka yang bagus.
var Color = ds.make.class({
type: 'Color',
constructor: function (r,g,b) {
this.r = r; /* now r,g, and b are available to */
this.g = g; /* other methods in the Color class */
this.b = b;
}
});
var red = new Color(255,0,0); // using the new keyword to instantiate the class
Di sini kita perlu memperhatikan satu poin dalam java script, ini adalah bahasa tanpa kelas namun, kita dapat mencapainya dengan menggunakan fungsi dalam java script. Cara paling umum untuk mencapai ini kita perlu membuat fungsi dalam java script dan menggunakan kata kunci baru untuk membuat objek dan menggunakan kata kunci ini untuk mendefinisikan properti dan metode. Berikut adalah contohnya.
// Function constructor
var calculator=function(num1 ,num2){
this.name="This is function constructor";
this.mulFunc=function(){
return num1*num2
};
};
var objCal=new calculator(10,10);// This is a constructor in java script
alert(objCal.mulFunc());// method call
alert(objCal.name);// property call
//Constructors With Prototypes
var calculator=function(){
this.name="Constructors With Prototypes";
};
calculator.prototype.mulFunc=function(num1 ,num2){
return num1*num2;
};
var objCal=new calculator();// This is a constructor in java script
alert(objCal.mulFunc(10,10));// method call
alert(objCal.name); // property call
Dalam sebagian besar kasus, Anda harus mendeklarasikan properti yang Anda butuhkan dengan cara apa pun sebelum Anda dapat memanggil metode yang memberikan informasi ini. Jika awalnya Anda tidak perlu mengatur properti, Anda bisa memanggil metode di dalam objek seperti itu. Mungkin bukan cara yang paling cantik untuk melakukan ini tetapi ini masih berfungsi.
var objectA = {
color: '';
callColor : function(){
console.log(this.color);
}
this.callColor();
}
var newObject = new objectA();